def test_bg_foi(): bristol = Ward("Bristol") london = Ward("London") oxford = Ward("Oxford") bristol.set_num_players(100) london.set_num_players(100) oxford.set_num_players(100) bristol.set_bg_foi(10) london.set_bg_foi(1) wards = bristol + london + oxford lurgy = Disease("lurgy") lurgy.add("E", beta=0.0, progress=1.0) lurgy.add("I", beta=0.0, progress=1.0) lurgy.add("R") params = Parameters() params.set_disease(lurgy) network = Network.from_wards(wards, params=params) outdir = os.path.join(script_dir, "test_bg_foi") with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.run(population=Population(), output_dir=output_dir, extractor=_check_infections) OutputFiles.remove(outdir, prompt=None) # the only source of infection should be the bg. Should have # no infections in oxford, some in london and most in bristol print(trajectory[-1]) assert trajectory[-1].recovereds <= 200 assert trajectory[-1].susceptibles >= 100
def test_go_ward(): bristol = Ward("bristol") london = Ward("london") oxford = Ward("oxford") bristol.set_num_players(100) london.set_num_players(100) oxford.set_num_players(100) bristol.add_workers(0, destination=london) bristol.add_workers(0, destination=oxford) oxford.add_workers(0, destination=bristol) oxford.add_workers(0, destination=london) london.add_workers(0, destination=bristol) london.add_workers(0, destination=oxford) disease = Disease(name="lurgy") disease.add(name="E", beta=0.5, progress=0.5) disease.add(name="I", beta=0.8, progress=0.25) disease.add(name="R") disease.assert_sane() params = Parameters() params.set_disease(disease) params.add_seeds("1 20 bristol") outdir = os.path.join(script_dir, "test_go_ward_output") network = Network.from_wards(bristol + london + oxford, params=params) with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, nthreads=1) print(trajectory[-1]) # there are no workers, so can only infect the 100 Bristolians assert trajectory[-1].recovereds <= 100 # Repeat with a different number of threads to test parallel code outdir = os.path.join(script_dir, "test_go_ward_output") with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, nthreads=4) print(trajectory[-1]) # there are no workers, so can only infect the 100 Bristolians assert trajectory[-1].recovereds <= 100 # now do a cyclic move, from "R" to "S" with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, mover=move_cycle, nsteps=200) print(trajectory[-1]) # we should have completed all 200 steps as this will never end assert trajectory[-1].day == 200 assert trajectory[-1].recovereds <= 100 # move everyone to Bristol with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, mover=move_bristol) print(trajectory[-1]) assert trajectory[-1].recovereds > 100 # now move through all of bristol, london, oxford with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, mover=move_travel) print(trajectory[-1]) assert trajectory[-1].recovereds > 100 OutputFiles.remove(outdir, prompt=None)
def test_go_record(): bristol = Ward("bristol") london = Ward("london") oxford = Ward("oxford") bristol.set_num_players(100) london.set_num_players(100) oxford.set_num_players(100) bristol.add_workers(0, destination=london) bristol.add_workers(0, destination=oxford) oxford.add_workers(0, destination=bristol) oxford.add_workers(0, destination=london) london.add_workers(0, destination=bristol) london.add_workers(0, destination=oxford) disease = Disease(name="lurgy") disease.add(name="E", beta=0.5, progress=0.5) disease.add(name="I", beta=0.8, progress=0.25) disease.add(name="R") disease.assert_sane() params = Parameters() params.set_disease(disease) params.add_seeds("1 20 bristol") outdir = os.path.join(script_dir, "test_go_ward_output") network = Network.from_wards(bristol + london + oxford, params=params) with OutputFiles(outdir, force_empty=True, prompt=None) as output_dir: trajectory = network.copy().run(population=Population(), output_dir=output_dir, mover=move_bristol) OutputFiles.remove(outdir, prompt=None) # despite the moves, only Bristolians can be infected as there # are no work movements assert trajectory[-1].recovereds <= 100
def test_ward_params(): bristol = Ward("Bristol") london = Ward("London") oxford = Ward("Oxford") bristol.set_num_players(1000) london.set_num_players(5000) oxford.set_num_players(800) bristol.add_workers(500, destination=bristol) bristol.add_workers(200, destination=oxford) bristol.add_workers(900, destination=london) oxford.add_workers(100, destination=bristol) oxford.add_workers(1000, destination=oxford) oxford.add_workers(2000, destination=london) london.add_workers(100, destination=bristol) london.add_workers(400, destination=oxford) london.add_workers(10000, destination=london) bristol.add_player_weight(0.1, destination=oxford) oxford.add_player_weight(0.2, destination=bristol) oxford.add_player_weight(0.15, destination=london) london.add_player_weight(0.3, destination=oxford) bristol.set_scale_uv(0.5) bristol.set_cutoff(5.0) london.set_scale_uv(1.5) oxford.set_cutoff(15.4) bristol.set_bg_foi(10.8) london.set_bg_foi(-5.2) bristol.set_custom("something", 9.9) oxford.set_custom("else", 22.1) assert bristol.scale_uv() == 0.5 assert bristol.cutoff() == 5.0 assert bristol.bg_foi() == 10.8 assert bristol.custom("something") == 9.9 assert bristol.custom("else") == 0.0 assert bristol.custom("else", 1.0) == 1.0 assert london.scale_uv() == 1.5 assert london.bg_foi() == -5.2 assert oxford.cutoff() == 15.4 assert oxford.bg_foi() == 0.0 assert oxford.custom("else") == 22.1 wards = bristol + london + oxford assert wards[bristol].scale_uv() == 0.5 assert wards[oxford].custom("else") == 22.1 assert wards[bristol].bg_foi() == 10.8 assert wards[oxford].bg_foi() == 0.0 s = wards.to_json() print(s) assert wards == Wards.from_json(s) network = Network.from_wards(wards) assert network.nodes.scale_uv[1] == 0.5 assert network.nodes.scale_uv[2] == 1.5 assert network.nodes.scale_uv[3] == 1.0 assert network.nodes.cutoff[1] == 5.0 assert network.nodes.cutoff[2] == 99999.99 assert network.nodes.cutoff[3] == 15.4 assert network.nodes.bg_foi[1] == 10.8 assert network.nodes.bg_foi[2] == -5.2 assert network.nodes.bg_foi[3] == 0.0 something = network.nodes.get_custom("something") els = network.nodes.get_custom("else") miss = network.nodes.get_custom("missing", 99.9) assert something[1] == 9.9 assert something[2] == 0.0 assert something[3] == 0.0 assert els[1] == 0.0 assert els[2] == 0.0 assert els[3] == 22.1 assert miss[1] == 99.9 assert miss[2] == 99.9 assert miss[3] == 99.9 network2 = Network.from_wards(network.to_wards()) for i in range(0, len(network.info)): assert network.info[i] == network2.info[i] for i in range(1, network.nnodes + 1): assert network.nodes.scale_uv[i] == network2.nodes.scale_uv[i] assert network.nodes.cutoff[i] == network2.nodes.cutoff[i] assert network.nodes.bg_foi[i] == network2.nodes.bg_foi[i] assert network.nodes.get_custom("something")[i] == \ network2.nodes.get_custom("something")[i] assert network.nodes.get_custom("else")[i] == \ network2.nodes.get_custom("else")[i]
def test_ward_json(): w = WardInfo(name="something", alternate_names=["one", "two"], code="123", alternate_codes=["1", "2", "cat"], authority="somewhere", authority_code="s123", region="place name", region_code="r789") s = json.dumps(w.to_data()) print(s) w2 = WardInfo.from_data(json.loads(s)) assert w == w2 ward = Ward(id=10, info=w) ward.set_position(x=1500, y=2500, units="m") ward.set_num_players(1200) ward.set_num_workers(500) ward.add_workers(number=30, destination=1) ward.add_workers(number=20, destination=30) ward.add_player_weight(weight=0.2, destination=30) ward.add_player_weight(weight=0.5, destination=1) print(ward) s = json.dumps(ward.to_data()) print(s) ward2 = Ward.from_data(json.loads(s)) assert json.dumps(ward.to_data()) == json.dumps(ward2.to_data()) assert ward == ward2 ward2 = Ward(id=1, name="something else") ward3 = Ward(id=30, name="another name") wards = Wards([ward, ward2, ward3]) print(wards) _assert_equal(wards[ward.id()], ward) _assert_equal(wards[ward2.id()], ward2) _assert_equal(wards[ward3.id()], ward3) s = json.dumps(wards.to_data()) print(s) wards2 = Wards.from_data(json.loads(s)) assert wards == wards2 ward3 = Ward(id=50, name="another ward") wards2.insert(ward3) assert wards != wards2
def test_harmonise_wards(): bristol = Ward("Bristol") london = Ward("London") oxford = Ward("Oxford") bristol.set_num_players(1000) london.set_num_players(5000) oxford.set_num_players(800) bristol.add_workers(500, destination=bristol) bristol.add_workers(200, destination=oxford) bristol.add_workers(900, destination=london) oxford.add_workers(100, destination=bristol) oxford.add_workers(1000, destination=oxford) oxford.add_workers(2000, destination=london) london.add_workers(100, destination=bristol) london.add_workers(400, destination=oxford) london.add_workers(10000, destination=london) bristol.add_player_weight(0.1, destination=oxford) oxford.add_player_weight(0.2, destination=bristol) oxford.add_player_weight(0.15, destination=london) london.add_player_weight(0.3, destination=oxford) home_wards = bristol + london + oxford print(home_wards) holiday = Ward("holiday") bristol = Ward("Bristol") oxford = Ward("Oxford") holiday.add_player_weight(0.5, destination=bristol) holiday.add_player_weight(0.5, destination=oxford) holiday_wards = bristol + oxford + holiday print(holiday_wards) hospital = Ward("hospital") london = Ward("London") london.add_workers(50, destination=hospital) hospital.set_num_players(150) hospital_wards = london + hospital print(hospital_wards) overall, harmonised = Wards.harmonise( [home_wards, holiday_wards, hospital_wards]) print(overall) print(harmonised) assert overall.num_workers() == home_wards.num_workers() + \ holiday_wards.num_workers() + \ hospital_wards.num_workers() assert overall.num_players() == home_wards.num_players() + \ holiday_wards.num_players() + \ hospital_wards.num_players() assert harmonised[0].num_workers() == home_wards.num_workers() assert harmonised[0].num_players() == home_wards.num_players() assert harmonised[1].num_workers() == holiday_wards.num_workers() assert harmonised[1].num_players() == holiday_wards.num_players() assert harmonised[2].num_workers() == hospital_wards.num_workers() assert harmonised[2].num_players() == hospital_wards.num_players() print(overall.to_json())
def test_duplicate_wards(): bristol = Ward("Bristol") bristol.set_num_players(100) london = Ward("London") london.set_num_players(200) bristol.add_workers(50, london) bristol.add_player_weight(0.5, london) wards = bristol + london print(wards) assert bristol in wards assert london in wards assert wards.num_workers() == bristol.num_workers() + london.num_workers() assert wards.num_players() == bristol.num_players() + london.num_players() print(wards.to_json()) wlist1 = wards[bristol].get_worker_lists() plist1 = wards[bristol].get_player_lists() wards += bristol print(wards) print(wards.to_json()) assert wards[bristol].num_players() == 2 * bristol.num_players() assert wards[bristol].num_workers() == 2 * bristol.num_workers() wlist2 = wards[bristol].get_worker_lists() plist2 = wards[bristol].get_player_lists() print(wlist1) print(wlist2) assert wlist1[0][0] == wlist2[0][0] assert 2 * wlist1[1][0] == wlist2[1][0] print(plist1) print(plist2) assert plist1 == plist2
def test_add_wards(): bristol = Ward("Bristol") london = Ward("London") glasgow = Ward("Glasgow") wards = Wards() assert bristol not in wards assert london not in wards assert glasgow not in wards bristol.add_workers(5, london) bristol.add_workers(10, bristol) bristol.add_workers(15, glasgow) assert not bristol.is_resolved() print(bristol._workers, bristol._players) bristol.add_player_weight(0.2, london) bristol.add_player_weight(0.5, glasgow) wards.add(bristol) assert bristol in wards assert london not in wards assert glasgow not in wards wards.add(london) assert london in wards assert glasgow not in wards assert bristol + london == wards wards2 = wards + glasgow assert glasgow in wards2 wards += glasgow assert wards == wards2 assert bristol + london + glasgow == wards print(wards) print(bristol._workers, bristol._players) assert not bristol.is_resolved() bristol2 = bristol.resolve(wards) print(bristol2) print(bristol2._workers, bristol2._players) assert bristol2.is_resolved() assert bristol != bristol2 bristol2 = bristol2.dereference(wards) assert not bristol2.is_resolved() assert bristol == bristol2 assert wards == wards2 sheffield = Ward("Sheffield") norwich = Ward("Norwich") wards2 = sheffield + norwich print(wards) print(wards2) wards3 = wards + wards2 print(wards3) assert bristol in wards3 assert london in wards3 assert glasgow in wards3 assert sheffield in wards3 assert norwich in wards3 wards3 = wards2 + wards bristol2 = wards3["Bristol"] assert bristol2.is_resolved() print(bristol2._workers, bristol2._players) bristol2 = bristol2.dereference(wards3) assert not bristol2.is_resolved() print(bristol2._workers, bristol2._players) assert bristol == bristol2
def test_wards(): wards = Wards() bristol = Ward(name="Bristol") london = Ward(name="London") bristol.add_workers(500, destination=bristol) bristol.add_workers(500, destination=london) bristol.set_num_players(750) london.add_workers(8500, destination=london) london.add_workers(100, destination=bristol) london.set_num_players(10000) print(bristol) print(london) wards.add(bristol) wards.add(london) print(wards) assert wards.num_workers() == 9600 assert wards.num_players() == 10750 assert wards.population() == 10750 + 9600 data = wards.to_data() print(data) wards2 = Wards.from_data(data) print(wards2) assert wards == wards2 try: filename = "_test_wards.json" with open(filename, "w") as FILE: json.dump(data, FILE, indent=2) print("".join(open(filename).readlines())) with open(filename) as FILE: data2 = json.load(FILE) wards2 = Wards.from_data(data2) print(wards2) assert wards == wards2 finally: import os os.unlink(filename) network = Network.from_wards(wards, disease="lurgy") assert network.work_population == wards.num_workers() assert network.play_population == wards.num_players() assert network.population == wards.population() wards2 = network.to_wards() assert len(wards) == len(wards2) for w1, w2 in zip(wards, wards2): if w1 is None: assert w2 is None continue assert w1.id() == w2.id() assert w1.name() == w2.name() assert w1.info() == w2.info() assert w1.num_workers() == w2.num_workers() assert w1.num_players() == w2.num_players() assert w1.get_player_lists() == w2.get_player_lists() assert w1.get_worker_lists() == w2.get_worker_lists() assert w1.position() == w2.position() s = wards.to_json() wards2 = Wards.from_json(s) assert wards2 == wards filename = wards.to_json("_test_wards_data.json", indent=4) print(filename) try: wards2 = Wards.from_json(filename) finally: import os os.unlink(filename) assert wards2 == wards
def test_move_generator(): m = MoveGenerator(fraction=0.3) assert m.fraction() == 0.3 m = MoveGenerator(number=1000) assert m.number() == 1000 params = Parameters() params.set_disease("lurgy") network = Network.single(params, Population(initial=1000)) m = MoveGenerator(from_stage="E") assert m.generate(network) == [[0, 1, 0, 1]] assert m.should_move_all() assert m.fraction() == 1.0 assert m.number() >= 1000000000 m = MoveGenerator(from_stage="E", to_stage="R") assert m.generate(network) == [[0, 1, 0, 4]] assert m.should_move_all() m = MoveGenerator(to_stage="R") assert m.generate(network) == [[0, -1, 0, 4], [0, 0, 0, 4], [0, 1, 0, 4], [0, 2, 0, 4], [0, 3, 0, 4], [0, 4, 0, 4]] assert m.should_move_all() m = MoveGenerator(from_stage=["E", "I1"]) assert m.generate(network) == [[0, 1, 0, 1], [0, 2, 0, 2]] assert m.should_move_all() m = MoveGenerator(from_stage=["E", "I1"], to_stage=["I1", "I2"]) assert m.generate(network) == [[0, 1, 0, 2], [0, 2, 0, 3]] assert m.should_move_all() m = MoveGenerator(from_stage=["E", "I1"], to_stage="R") assert m.generate(network) == [[0, 1, 0, 4], [0, 2, 0, 4]] assert m.should_move_all() m = MoveGenerator() assert m.generate(network) == [[0, -1, 0, -1], [0, 0, 0, 0], [0, 1, 0, 1], [0, 2, 0, 2], [0, 3, 0, 3], [0, 4, 0, 4]] assert m.should_move_all() demographics = Demographics.load(demography_json) networks = demographics.specialise(network) m = MoveGenerator() assert m.generate(networks) == [[0, -1, 0, -1], [0, 0, 0, 0], [0, 1, 0, 1], [0, 2, 0, 2], [0, 3, 0, 3], [0, 4, 0, 4], [1, -1, 1, -1], [1, 0, 1, 0], [1, 1, 1, 1], [1, 2, 1, 2], [1, 3, 1, 3], [1, 4, 1, 4], [2, -1, 2, -1], [2, 0, 2, 0], [2, 1, 2, 1], [2, 2, 2, 2], [2, 3, 2, 3], [2, 4, 2, 4]] m = MoveGenerator(from_stage="E") assert m.generate(networks) == [[0, 1, 0, 1], [1, 1, 1, 1], [2, 1, 2, 1]] m = MoveGenerator(to_stage="R") assert m.generate(networks) == [[0, -1, 0, 4], [0, 0, 0, 4], [0, 1, 0, 4], [0, 2, 0, 4], [0, 3, 0, 4], [0, 4, 0, 4], [1, -1, 1, 4], [1, 0, 1, 4], [1, 1, 1, 4], [1, 2, 1, 4], [1, 3, 1, 4], [1, 4, 1, 4], [2, -1, 2, 4], [2, 0, 2, 4], [2, 1, 2, 4], [2, 2, 2, 4], [2, 3, 2, 4], [2, 4, 2, 4]] m = MoveGenerator(from_demographic="red") assert m.generate(networks) == [[0, -1, 0, -1], [0, 0, 0, 0], [0, 1, 0, 1], [0, 2, 0, 2], [0, 3, 0, 3], [0, 4, 0, 4]] m = MoveGenerator(to_demographic="blue") assert m.generate(networks) == [[0, -1, 2, -1], [0, 0, 2, 0], [0, 1, 2, 1], [0, 2, 2, 2], [0, 3, 2, 3], [0, 4, 2, 4], [1, -1, 2, -1], [1, 0, 2, 0], [1, 1, 2, 1], [1, 2, 2, 2], [1, 3, 2, 3], [1, 4, 2, 4], [2, -1, 2, -1], [2, 0, 2, 0], [2, 1, 2, 1], [2, 2, 2, 2], [2, 3, 2, 3], [2, 4, 2, 4]] m = MoveGenerator(to_demographic="blue", to_stage="R") assert m.generate(networks) == [[0, -1, 2, 4], [0, 0, 2, 4], [0, 1, 2, 4], [0, 2, 2, 4], [0, 3, 2, 4], [0, 4, 2, 4], [1, -1, 2, 4], [1, 0, 2, 4], [1, 1, 2, 4], [1, 2, 2, 4], [1, 3, 2, 4], [1, 4, 2, 4], [2, -1, 2, 4], [2, 0, 2, 4], [2, 1, 2, 4], [2, 2, 2, 4], [2, 3, 2, 4], [2, 4, 2, 4]] m = MoveGenerator(from_demographic="red", to_demographic="blue", from_stage=["I1", "I2"], to_stage="S") assert m.generate(networks) == [[0, 2, 2, -1], [0, 3, 2, -1]] m = MoveGenerator(from_demographic="blue", from_stage="E", to_stage="I1") print(m.generate(networks)) assert m.generate(networks) == [[2, 1, 2, 2]] m = MoveGenerator(to_ward=1) player = PersonType.PLAYER worker = PersonType.WORKER assert m.generate_wards(network) == [[None, (player, 1, 2)]] assert m.generate_wards(networks) == [[None, (player, 1, 2)]] assert not m.should_move_all() assert m.fraction() == 1.0 assert m.number() >= 1000000000 bristol = Ward("bristol") london = Ward("london") oxford = Ward("oxford") bristol.add_workers(0, destination=london) bristol.add_workers(0, destination=oxford) london.add_workers(0, destination=bristol) london.add_workers(0, destination=oxford) network = Network.from_wards(bristol + london + oxford) assert len(network.nodes) == network.nnodes + 1 assert len(network.links) == network.nlinks + 1 assert network.nnodes == 3 assert network.nlinks == 4 m = MoveGenerator(from_ward=["bristol", WardID("bristol", "london")], to_ward="oxford", fraction=0.3, number=100) assert not m.should_move_all() assert m.fraction() == 0.3 assert m.number() == 100 print(m.generate_wards(network)) assert m.generate_wards(network) == [[(player, 1, 2), (player, 3, 4)], [(worker, 1, 2), (player, 3, 4)]] m = MoveGenerator(from_ward=WardID("oxford", "bristol"), to_ward=1) assert m.generate_wards(network) == [[(worker, -1, -1), (player, 1, 2)]] oxford.add_workers(0, destination=bristol) network = Network.from_wards(bristol + london + oxford) print(m.generate_wards(network)) assert m.generate_wards(network) == [[(worker, 5, 6), (player, 1, 2)]] m = MoveGenerator(from_ward=WardID("bristol", "bristol"), to_ward="oxford") print(m.generate_wards(network)) assert m.generate_wards(network) == [[(worker, -1, -1), (player, 3, 4)]] bristol.add_workers(0, destination=bristol) network = Network.from_wards(bristol + london + oxford) print(m.generate_wards(network)) assert m.generate_wards(network) == [[(worker, 1, 2), (player, 3, 4)]] assert network.links.ifrom[1] == network.links.ito[1] assert network.links.ifrom[1] == network.get_node_index("bristol") m = MoveGenerator(to_ward=WardID("london", "bristol")) print(m.generate_wards(network)) assert m.generate_wards(network) == [[None, (worker, 4, 5)]] assert network.links.ifrom[4] == network.get_node_index("london") assert network.links.ito[4] == network.get_node_index("bristol") m = MoveGenerator( from_stage="S", to_stage="R", from_ward=[WardID("bristol", all_commute=True), WardID("bristol")], to_ward="oxford", number=42, fraction=0.5) print(m.generate(network)) print(m.generate_wards(network)) assert m.generate(network) == [[0, -1, 0, 4]] assert m.generate_wards(network) == [[(worker, 1, 4), (player, 3, 4)], [(player, 1, 2), (player, 3, 4)]] record = MoveRecord() for stage in m.generate(network): for ward in m.generate_wards(network): from_type = ward[0][0] ifrom_begin = ward[0][1] ifrom_end = ward[0][2] to_type = ward[1][0] ito_begin = ward[1][1] ito_end = ward[1][2] n = ifrom_end - ifrom_begin print(ifrom_begin, ifrom_end, ito_begin, ito_end) if ito_end - ito_begin == 0: raise ValueError("Cannot move individuals to a non-existent " "ward or ward-link") elif ito_end - ito_begin == 1: # this is a single to-ward (or link) ito_delta = 0 elif ito_end - ito_begin != ifrom_end - ifrom_begin: # different number of links raise ValueError( "Cannot move individuals as the number of from " "and to links are not the same: " f"{ifrom_begin}:{ifrom_end} versus " f"{ito_begin}:{ito_end}") else: ito_delta = 1 for i in range(0, n): ifrom = ifrom_begin + i ito = ito_begin + (i * ito_delta) record.add(from_demographic=stage[0], from_stage=stage[1], to_demographic=stage[2], to_stage=stage[3], from_type=from_type, from_ward=ifrom, to_type=to_type, to_ward=ito, number=m.number() * m.fraction()) from array import array records = [ array("i", (0, -1, 1, 1, 0, 4, 2, 3, 21)), array("i", (0, -1, 1, 2, 0, 4, 2, 3, 21)), array("i", (0, -1, 1, 3, 0, 4, 2, 3, 21)), array("i", (0, -1, 2, 1, 0, 4, 2, 3, 21)) ] print(record._record) for i, move in enumerate(record): print(f"{move} == {records[i]}") assert move == records[i]