"""Independent yaw alignment and exact native lock-selection verification.""" import math import re from ordinary_look_evidence import validate_look_evidence from ordinary_gate_evidence import join_gate_snapshots, validate_gate_geometry from prison_approach_evidence import validate_approach_evidence, need, number, horizontal, norm, yaw, angle, neutral def validate_alignment_evidence(content, nonce, look_proof, approach_proof, proof): result={'verified':False,'errors':[],'scope':'stationary yaw-only alignment and native selection of the original prison lock after a verified interior approach; no F hold, unlock, exit or multiplayer qualification','held_action_verified':False,'escape_verified':False} try: approach=validate_approach_evidence(content,nonce,look_proof,approach_proof) need(approach['verified'],'prior native approach is unverified: '+str(approach['errors'])) calibration=validate_look_evidence(content,nonce,look_proof) need(calibration['verified'],'same-run native calibration is unverified: '+str(calibration['errors'])) gain=calibration['response_yaw_degrees']/24 need(.01<=abs(gain)<=.5,'native calibration gain outside alignment range') need(type(proof) is dict and not proof.get('events') and proof.get('requested') is True and proof.get('completed') is True and proof.get('nonce')==nonce and not proof.get('error'),'alignment did not complete under this nonce') start=number(proof['started_monotonic']);finish=number(proof['finished_monotonic']);deadline=number(proof['deadline_monotonic']) need(approach_proof['finished_monotonic']<=start=start] native_begin=current[0] if current else first need(samples[last]['real_ms']-samples[native_begin]['real_ms']<=8000,'current native alignment interval exceeds eight seconds') def heading(s): eye=s['look']['camera'];handle=s['geometry']['context'] need(.25<=horizontal(eye,handle)<=5,'native handle bearing is degenerate or out of scope') return math.degrees(math.atan2(handle[0]-eye[0],handle[2]-eye[2])) motions=proof['motions'];need(type(motions) is list and len(motions)<=6,'too many alignment motions') old_index=first;old_time=start;pixel_sum=0 for motion in motions: dx=motion['dx'];at=number(motion['monotonic']);before=motion['after_sample'];after=motion['response_sample'] need(type(dx) is int and 1<=abs(dx)<=128 and type(motion['dy']) is int and motion['dy']==0,'alignment motion is not bounded horizontal input') need(type(before) is int and type(after) is int and old_index<=before3 and dx*gain*wanted>0 and .05<=abs(change)<=15 and change*dx*gain>0,'native turn did not follow same-run signed calibration toward handle') for i in range(before,after+1): d=angle(yaw(samples[i]['look']['direction']),baseline) need(abs(d)<=15 and (abs(d)<.05 or d*dx*gain>0),'intermediate native turn reversed or exceeded bound') need(after-1>=before and 100<=samples[after]['real_ms']-samples[after-1]['real_ms']<=500 and abs(angle(yaw(samples[after]['look']['direction']),yaw(samples[after-1]['look']['direction'])))<=.2,'native turn response did not settle over consecutive samples') need(samples[after]['real_ms']-samples[before]['real_ms']<=2500,'native turn response interval is unbounded') old_index=after;old_time=at;pixel_sum+=abs(dx) need(pixel_sum<=768,'alignment pixel budget exceeded') pair=proof['selection_samples'];need(type(pair) is list and len(pair)==2 and all(type(i) is int for i in pair) and first<=pair[0] and pair[1]==pair[0]+1 and pair[1]<=last,'selection lacks consecutive references') one,two=(samples[i] for i in pair) need(100<=two['real_ms']-one['real_ms']<=500 and abs(angle(yaw(two['look']['direction']),yaw(one['look']['direction'])))<=.2,'selection view did not settle') for i in range(pair[0],last+1): s=samples[i];a=s['action'] need(a['selected'] and a['context_selected'] and a['cached_performable'] and a['progress_bound'] and a['duration']==4,'original native lock/context not selected and bound') need(abs(angle(heading(s),yaw(s['look']['direction'])))<=3,'view not aligned to actual handle bearing') result.update(verified=True,first_sample=first,last_sample=last,selection_samples=pair,turn_count=len(motions),native_duration_ms=samples[last]['real_ms']-samples[first]['real_ms'],final_yaw_error_degrees=abs(angle(heading(samples[last]),yaw(samples[last]['look']['direction'])))) except (ValueError,KeyError,TypeError,OverflowError,IndexError) as error: result['errors'].append(str(error)) return result