"""tools/lgbot_rec.py: parsing a recording and the movement stats.""" import os, sys, unittest sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import lgbot_rec as r # noqa: E402 def rec(seconds, human_fn, bot_fn, dt=0.025): """Recording lines: human_fn/bot_fn(t) -> (x, y, z, vx, vy, vz).""" lines = ["# start 0 map test"] t = 0.0 while t < seconds: for who, fn, state in (("h1", human_fn, ""), ("bot", bot_fn, "steer")): x, y, z, vx, vy, vz = fn(t) lines.append("%.3f,%s,1,100,%.0f,%.0f,%.0f,%.0f,%.0f,%.0f,%s" % (t, who, x, y, z, vx, vy, vz, state)) t += dt return lines def adad(hold_s): # sideways (y) at 320 u/s, switching every hold_s, standing 450 in front of the other on x def fn(t): d = 1 if int(t / hold_s) % 2 == 0 else -1 return (0, 0, 0, 0, 320 * d, 0) return fn def still_at(x): return lambda t: (x, 0, 0, 0, 0, 0) class Stats(unittest.TestCase): def test_strafe_holds_and_sideways(self): s = r.parse(rec(10, adad(0.5), still_at(450))) st = r.analyze(r.by_kind(r.fight_frames(s[0]))["human"]) self.assertAlmostEqual(st["hold_ms"][1], 500, delta=30) self.assertGreater(st["sideways_share"], 0.95) self.assertEqual(st["air_share"], 0) self.assertAlmostEqual(st["ground_speed"][1], 320, delta=1) self.assertAlmostEqual(st["seconds"], 10, delta=0.1) def test_bot_steer_share_and_stopped(self): s = r.parse(rec(5, adad(0.5), still_at(450))) st = r.analyze(r.by_kind(r.fight_frames(s[0]))["bot"]) self.assertEqual(st["steer_share"], 1) self.assertEqual(st["stopped_share"], 1) def test_jumps_counted(self): def hop(t): # one jump a second: 0.7 s in the air, then ground ph = t % 1.0 return (0, 0, 0, 0, 320, 270 - 800 * ph if ph < 0.7 else 0) st = r.analyze(r.by_kind(r.fight_frames(r.parse(rec(10, hop, still_at(450)))[0]))["human"]) self.assertAlmostEqual(st["jumps_per_s"], 1.0, delta=0.15) self.assertAlmostEqual(st["air_share"], 0.7, delta=0.05) def test_far_or_other_floor_is_not_fight_time(self): far = r.fight_frames(r.parse(rec(2, adad(0.5), still_at(1500)))[0]) up = r.fight_frames(r.parse(rec(2, adad(0.5), lambda t: (450, 0, 400, 0, 0, 0)))[0]) self.assertEqual(far, {}) self.assertEqual(up, {}) def test_sessions_do_not_join(self): lines = rec(2, adad(0.5), still_at(450)) + rec(2, adad(0.5), still_at(450)) sessions = r.parse(lines) self.assertEqual(len(sessions), 2) frames = r.fight_frames(sessions[0])["h1"] + r.fight_frames(sessions[1])["h1"] self.assertAlmostEqual(r.analyze(frames)["seconds"], 4, delta=0.1) def test_two_humans_kept_apart(self): # h1 strafes with 0.5 s holds, h2 with 0.25 s holds, no bot: each is measured on its own lines = ["# start 0 map test"] for i in range(400): t = i * 0.025 for who, hold, x in (("h1", 0.5, 0), ("h2", 0.25, 450)): d = 1 if int(t / hold) % 2 == 0 else -1 lines.append("%.3f,%s,1,100,%d,0,0,0,%d,0," % (t, who, x, 320 * d)) per = r.fight_frames(r.parse(lines)[0]) self.assertEqual(sorted(per), ["h1", "h2"]) self.assertAlmostEqual(r.analyze(per["h1"])["hold_ms"][1], 500, delta=30) self.assertAlmostEqual(r.analyze(per["h2"])["hold_ms"][1], 250, delta=30) both = r.by_kind(per)["human"] self.assertAlmostEqual(r.analyze(both)["seconds"], 20, delta=0.2) self.assertEqual(r.analyze(r.by_kind(per)["bot"])["frames"], 0) def test_report_prints(self): st = r.analyze(r.fight_frames(r.parse(rec(2, adad(0.5), still_at(450)))[0])["h1"]) self.assertIn("strafe hold", r.report(st, r.analyze([]))) if __name__ == "__main__": unittest.main()