"""Offline verification of captured practice evidence; never contacts simulator.""" import json import math from pathlib import Path import unittest from geometry import Measurement, solve ROOT=Path(__file__).resolve().parents[1] class PracticeReplayTests(unittest.TestCase): def test_action_log_and_derived_geometry(self): folder=ROOT/'output/q1/practice' files=list(folder.glob('*_actions.json')) self.assertTrue(files, '缺少本次演练采集证据') for path in files: events=json.loads(path.read_text(encoding='utf-8')) pos=(0,0);channel=1;virtual=0 self.assertEqual(events[0]['path'],'/enter') self.assertEqual(events[-1]['path'],'/exit') self.assertEqual(events[-1]['response']['exit_reason'],'user_exit') ids=[] for event in events: self.assertIn(event['path'],('/enter','/measure','/exit')) request,response=event['request'],event['response'] self.assertTrue(response['accepted']) ids.append(request['request_id']) if event['path']=='/measure': new=(request['position']['x'],request['position']['y']) virtual+=math.dist(pos,new)/5+5+(request['channel']!=channel) pos,channel=new,request['channel'] self.assertAlmostEqual(virtual,response['virtual_time_s'],places=5) self.assertEqual(len(ids),len(set(ids))) observation_path=path.with_name(path.name.replace('_actions','_observations')) data=json.loads(observation_path.read_text(encoding='utf-8')) ms=[Measurement(**m) for m in data['measurements']] recomputed=solve(ms) self.assertAlmostEqual(recomputed['diameter_m'],data['result']['diameter_m'],places=9) self.assertEqual(data['source'],'official_practice') self.assertIsNone(data['ground_truth']) directions=[e for e in events if e['response'].get('measure_result')=='direction'] self.assertEqual(directions[0]['request']['position'],directions[1]['request']['position']) self.assertEqual(directions[0]['response']['svd_deg'],directions[1]['response']['svd_deg']) if __name__=='__main__': unittest.main()