async def test_transfer_success_case(self): await self.system_clock_fast_forward(speed_multiplier=25) commutator, error = await self.login('player', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) miner_1_cargo = modules.get_cargo(commutator=miner_1, name='cargo') self.assertIsNotNone(miner_1_cargo) miner_2 = modules.get_ship(commutator, ShipType.MINER.value, "miner-2") self.assertIsNotNone(miner_2) miner_2_cargo = modules.get_cargo(commutator=miner_2, name='cargo') self.assertIsNotNone(miner_2_cargo) # Opening a port on miner_2 access_key = 12456 status, port = await miner_2_cargo.open_port(access_key=access_key) self.assertTrue(status.is_success()) self.assertNotEqual(0, port) total_transferred_amount: float = 0.0 # Will be accumulated in progress callback def cb_progress_report(item: ResourceItem): self.assertEqual(ResourceType.e_METALS, item.resource_type) nonlocal total_transferred_amount total_transferred_amount += item.amount # Transferring resources from miner_1 to miner_2 status = await miner_1_cargo.transfer(port=port, access_key=access_key, progress_cb=cb_progress_report, resource=ResourceItem( ResourceType.e_METALS, 30000)) self.assertEqual(ResourceContainerI.Status.SUCCESS, status) self.assertAlmostEqual(30000, total_transferred_amount) # Check resources in containers content = await miner_1_cargo.get_content() self.assertAlmostEqual(20000, content.resources[ResourceType.e_METALS]) self.assertAlmostEqual(20000, content.resources[ResourceType.e_SILICATES]) self.assertAlmostEqual(15000, content.resources[ResourceType.e_ICE]) content = await miner_2_cargo.get_content() self.assertAlmostEqual(35000, content.resources[ResourceType.e_METALS]) self.assertAlmostEqual(5000, content.resources[ResourceType.e_SILICATES]) self.assertAlmostEqual(10000, content.resources[ResourceType.e_ICE])
async def test_simple_scan(self): randomizer = Randomizer(seed=3284) await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) clock = modules.get_system_clock(commutator) self.assertIsNotNone(clock) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) scanner = modules.PassiveScanner.get_by_name(miner_1, "perceiver") self.assertIsNotNone(scanner) spec = await scanner.get_specification() self.assertIsNotNone(spec) ship_position = await miner_1.get_position() spawned_asteroids: List[types.PhysicalObject] = [ await self.administrator.get_spawner().spawn_asteroid( position=randomizer.random_position( center=ship_position, radius=2 * spec.scanning_radius_km * 1000), composition=types.make_resources(ice=100, metals=32), radius=randomizer.random_value(5, 20)) for i in range(1000) ] # Take 10 seconds to scan scanned_objects = await TestCase.scanning(scanner, clock, 10000) for candidate in spawned_asteroids: distance = ship_position.distance_to(candidate.position) if distance <= spec.scanning_radius_km * 1000: self.assertIn(candidate.object_id, scanned_objects)
async def test_scanning(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner) scanner = modules.get_celestial_scanner(miner, "scanner") self.assertIsNotNone(scanner) result = [] errors = [] def scanning_cb(objects, e): if objects: result.extend(objects) else: errors.append(e) self.assertIsNone(await scanner.scan(scanning_radius_km=20, minimal_radius_m=300, scanning_cb=scanning_cb)) self.assertIsNone(error) self.assertEqual([], result) self.assertIsNone(await scanner.scan(scanning_radius_km=20, minimal_radius_m=200, scanning_cb=scanning_cb)) self.assertIsNone(error) self.assertEqual(1, len(result))
async def test_stop_mining(self): await self.system_clock_fast_forward(speed_multiplier=50) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) status, miner_spec = await miner.get_specification() self.assertEqual(status, AsteroidMinerI.Status.SUCCESS) self.assertIsNotNone(miner_spec) status = await miner.bind_to_cargo("cargo") self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertEqual("cargo", miner.cargo_name) status = await miner.stop_mining() self.assertEqual(AsteroidMinerI.Status.MINER_IS_IDLE, status) # Looking for the asteroid, that should be nearby scanner: modules.CelestialScanner = modules.get_celestial_scanner( miner_ship, "scanner") self.assertIsNotNone(scanner) self.assertIsNotNone(scanner) result, error = await scanner.scan_sync(scanning_radius_km=1, minimal_radius_m=5) self.assertIsNone(error) self.assertIsNotNone(result) self.assertEqual(1, len(result)) asteroid = result[0] # Mining an asteroid def progress_cb(status: AsteroidMinerI.Status, item: ResourceItem) -> bool: return True mining_task = asyncio.get_running_loop().create_task( miner.start_mining(asteroid_id=asteroid.object_id, progress_cb=progress_cb)) # waiting for some cycles ok, _ = await self.system_clock_proceed(proceed_ms=int( miner_spec.cycle_time_ms * 5.5), timeout_s=5) self.assertTrue(ok) self.assertFalse(mining_task.done()) # Stopping mining process await self.system_clock_fast_forward(50) status = await miner.stop_mining() self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) status = await asyncio.wait_for(mining_task, 0.1) self.assertEqual(AsteroidMinerI.Status.INTERRUPTED_BY_USER, status)
async def test_move_to(self): commutator, error = await self.login('spy007', server_ip="127.0.0.1") self.assertIsNone(error) system_clock = modules.get_system_clock(commutator) self.assertIsNotNone(system_clock) fast_forward_clock = FastForwardAdapter( system_clock=system_clock, switch_to_real_time=self.system_clock_play, fast_forward=self.system_clock_fast_forward, fast_forward_multiplier=50) scout_1: modules.Ship = modules.get_ship(commutator, "Probe", "scout-1") self.assertIsNotNone(scout_1) scout_1_state = await scout_1.get_state() self.assertIsNotNone(scout_1_state) scout_2: modules.Ship = modules.get_ship(commutator, "Ship/Probe", "scout-2") self.assertIsNotNone(scout_1) engine = modules.get_engine(scout_1, "main_engine") self.assertIsNotNone(engine) engine_spec = await engine.get_specification() self.assertIsNotNone(engine_spec) amax = engine_spec.max_thrust / scout_1_state.weight position, target = \ await asyncio.gather(scout_1.get_position(), scout_2.get_position()) flight_plan = procedures.approach_to_plan( position=position, target=target, amax=amax ) success = await procedures.follow_flight_plan( scout_1, engine, flight_plan, fast_forward_clock ) self.assertTrue(success)
async def test_mining(self): await self.system_clock_fast_forward(speed_multiplier=50) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) status = await miner.bind_to_cargo("cargo") self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertEqual("cargo", miner.cargo_name) # Looking for the asteroid, that should be nearby scanner: modules.CelestialScanner = modules.get_celestial_scanner( miner_ship, "scanner") self.assertIsNotNone(scanner) result, error = await scanner.scan_sync(scanning_radius_km=1, minimal_radius_m=5) self.assertIsNone(error) self.assertIsNotNone(result) self.assertEqual(1, len(result)) asteroid = result[0] # Mining until we have 1000 of metals collected_resources: Dict[ResourceType, float] = { ResourceType.e_METALS: 0 } def progress_cb(status: AsteroidMinerI.Status, resources: ResourcesDict) -> bool: for resource_type, amount in resources.items(): if resource_type in collected_resources: collected_resources[resource_type] += amount else: collected_resources[resource_type] = amount return collected_resources[ResourceType.e_METALS] < 1000 # Mining an asteroid await self.system_clock_fast_forward(speed_multiplier=500) status = await miner.start_mining(asteroid_id=asteroid.object_id, progress_cb=progress_cb) self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) await self.system_clock_fast_forward(speed_multiplier=50) # Check the cargo content cargo = modules.get_cargo(miner_ship, "cargo") self.assertIsNotNone(cargo) content = await cargo.get_content() self.assertIsNotNone(content) self.assertLessEqual(1000, content.resources[ResourceType.e_METALS])
async def test_start_mining(self): await self.system_clock_fast_forward(speed_multiplier=50) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) status = await miner.bind_to_cargo("cargo") self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertEqual("cargo", miner.cargo_name) def progress_cb(status: AsteroidMinerI.Status, resources: ResourcesDict) -> bool: return False # Stop mining immediately # Trying to mine a non-existing asteroid status = await miner.start_mining(asteroid_id=100500, progress_cb=progress_cb) self.assertEqual(AsteroidMinerI.Status.ASTEROID_DOESNT_EXIST, status) # Looking for the asteroid, that should be away scanner: modules.CelestialScanner = modules.get_celestial_scanner( miner_ship, "scanner") self.assertIsNotNone(scanner) result, error = await scanner.scan_sync(scanning_radius_km=10, minimal_radius_m=15) self.assertIsNone(error) self.assertIsNotNone(result) self.assertEqual(1, len(result)) asteroid = result[0] # Mining an asteroid status = await miner.start_mining(asteroid_id=asteroid.object_id, progress_cb=progress_cb) self.assertEqual(AsteroidMinerI.Status.ASTEROID_TOO_FAR, status) # Looking for the asteroid, that should be nearby result, error = await scanner.scan_sync(scanning_radius_km=1, minimal_radius_m=5) self.assertIsNone(error) self.assertIsNotNone(result) self.assertEqual(1, len(result)) asteroid = result[0] # Mining an asteroid status = await miner.start_mining(asteroid_id=asteroid.object_id, progress_cb=progress_cb) self.assertEqual(AsteroidMinerI.Status.SUCCESS, status)
async def test_transfer_fails_cases(self): await self.system_clock_fast_forward(speed_multiplier=25) commutator, error = await self.login('player', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) miner_1_cargo = modules.get_cargo(commutator=miner_1, name='cargo') self.assertIsNotNone(miner_1_cargo) miner_2 = modules.get_ship(commutator, ShipType.MINER.value, "miner-2") self.assertIsNotNone(miner_2) miner_2_cargo = modules.get_cargo(commutator=miner_2, name='cargo') self.assertIsNotNone(miner_2_cargo) # Port is not opened error: status = await miner_1_cargo.transfer(port=4, access_key=123456, resource=ResourceItem( ResourceType.e_METALS, 30000)) self.assertEqual(ResourceContainerI.Status.PORT_IS_NOT_OPENED, status) # Opening a port on miner_2 access_key = 12456 status, port = await miner_2_cargo.open_port(access_key=access_key) self.assertTrue(status.is_success()) self.assertNotEqual(0, port) # Invalid access key status = await miner_1_cargo.transfer(port=port, access_key=access_key - 1, resource=ResourceItem( ResourceType.e_METALS, 30000)) self.assertEqual(ResourceContainerI.Status.INVALID_ACCESS_KEY, status)
async def test_cargo_is_full(self): await self.system_clock_fast_forward(speed_multiplier=50) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) status, miner_spec = await miner.get_specification() self.assertEqual(status, AsteroidMinerI.Status.SUCCESS) self.assertIsNotNone(miner_spec) status = await miner.bind_to_cargo("tiny_cargo") self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertEqual("tiny_cargo", miner.cargo_name) # Looking for the asteroid, that should be nearby scanner: modules.CelestialScanner = modules.get_celestial_scanner( miner_ship, "scanner") self.assertIsNotNone(scanner) result, error = await scanner.scan_sync(scanning_radius_km=1, minimal_radius_m=5) self.assertIsNone(error) self.assertIsNotNone(result) self.assertEqual(1, len(result)) asteroid = result[0] # Mining an asteroid def progress_cb(status: AsteroidMinerI.Status, item: ResourceItem) -> bool: return True # This will take a long time await self.system_clock_fast_forward(1000) status = await miner.start_mining(asteroid_id=asteroid.object_id, progress_cb=progress_cb) self.assertEqual(AsteroidMinerI.Status.NO_SPACE_AVAILABLE, status) # Check that cargo is full of ice cargo = modules.get_cargo(miner_ship, "tiny_cargo") self.assertIsNotNone(cargo) content = await cargo.get_content() self.assertIsNotNone(content) self.assertAlmostEqual(content.volume, content.used)
async def test_get_specification(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) scanner = modules.PassiveScanner.get_by_name(miner_1, "perceiver") self.assertIsNotNone(scanner) spec = await scanner.get_specification() self.assertIsNotNone(spec)
async def test_get_specification(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner) scanner = modules.get_celestial_scanner(miner, "scanner") self.assertIsNotNone(scanner) spec = await scanner.get_specification() self.assertIsNotNone(spec) self.assertEqual(1000, spec.max_radius_km) self.assertEqual(10000, spec.processing_time_us)
async def test_get_content(self): await self.system_clock_fast_forward(speed_multiplier=25) commutator, error = await self.login('player', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) cargo = modules.get_cargo(commutator=miner_1, name='cargo') self.assertIsNotNone(cargo) content = await cargo.get_content() self.assertAlmostEqual(20000, content.resources[ResourceType.e_SILICATES]) self.assertAlmostEqual(50000, content.resources[ResourceType.e_METALS]) self.assertAlmostEqual(15000, content.resources[ResourceType.e_ICE])
async def test_open_close_port(self): await self.system_clock_fast_forward(speed_multiplier=25) commutator, error = await self.login('player', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) cargo = modules.get_cargo(commutator=miner_1, name='cargo') self.assertIsNotNone(cargo) self.assertIsNone(cargo.get_opened_port()) # Trying to close a port, that has not been opened status = await cargo.close_port() self.assertEqual(ResourceContainerI.Status.PORT_IS_NOT_OPENED, status) # Opening a port access_key = 12456 status, port = await cargo.open_port(access_key=access_key) self.assertTrue(status.is_success()) self.assertNotEqual(0, port) self.assertEqual(port, cargo.get_opened_port()[0]) self.assertEqual(access_key, cargo.get_opened_port()[1]) # Trying to open yet another port status, port = await cargo.open_port(access_key=access_key * 2) self.assertEqual(ResourceContainerI.Status.PORT_ALREADY_OPEN, status) self.assertEqual(0, port) # Closing port (twice) status = await cargo.close_port() self.assertEqual(ResourceContainerI.Status.SUCCESS, status) status = await cargo.close_port() self.assertEqual(ResourceContainerI.Status.PORT_IS_NOT_OPENED, status) # Opening a port again status, port = await cargo.open_port(access_key=access_key) self.assertTrue(status.is_success()) self.assertNotEqual(0, port)
async def test_binding_to_cargo(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNone(error) self.assertIsNotNone(commutator) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) status = await miner.bind_to_cargo("invalid cargo") self.assertEqual(AsteroidMinerI.Status.NOT_BOUND_TO_CARGO, status) self.assertIsNone(miner.cargo_name) status = await miner.bind_to_cargo("cargo") self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertEqual("cargo", miner.cargo_name)
async def test_get_specification(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_ship = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner_ship) miner = modules.get_asteroid_miner(miner_ship, "miner") self.assertIsNotNone(miner) miner_blueprint = asteroid_miner_blueprints["basic"] status, spec = await miner.get_specification() self.assertEqual(AsteroidMinerI.Status.SUCCESS, status) self.assertIsNotNone(spec) self.assertEqual(miner_blueprint.max_distance, spec.max_distance) self.assertEqual(miner_blueprint.cycle_time_ms, spec.cycle_time_ms) self.assertEqual(miner_blueprint.yield_per_cycle, spec.yield_per_cycle)
async def test_scanning_sync(self): await self.system_clock_fast_forward(speed_multiplier=20) commutator, error = await self.login('oreman', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner = modules.get_ship(commutator, "Miner", "miner-1") self.assertIsNotNone(miner) scanner = modules.get_celestial_scanner(miner, "scanner") self.assertIsNotNone(scanner) result, error = await scanner.scan_sync(scanning_radius_km=20, minimal_radius_m=300) self.assertIsNone(error) self.assertEqual([], result) result, error = await scanner.scan_sync(scanning_radius_km=20, minimal_radius_m=200) self.assertIsNone(error) self.assertEqual(1, len(result))
async def test_transfer_monitoring(self): await self.system_clock_fast_forward(speed_multiplier=10) commutator, error = await self.login('player', "127.0.0.1") self.assertIsNotNone(commutator) self.assertIsNone(error) miner_1 = modules.get_ship(commutator, ShipType.MINER.value, "miner-1") self.assertIsNotNone(miner_1) miner_1_cargo = modules.get_cargo(commutator=miner_1, name='cargo') self.assertIsNotNone(miner_1_cargo) miner_2 = modules.get_ship(commutator, ShipType.MINER.value, "miner-2") self.assertIsNotNone(miner_2) miner_2_cargo = modules.get_cargo(commutator=miner_2, name='cargo') self.assertIsNotNone(miner_2_cargo) # Opening a port on miner_2 access_key = 12456 status, port = await miner_2_cargo.open_port(access_key=access_key) self.assertTrue(status.is_success()) self.assertNotEqual(0, port) # Will be collected during transferring transactions: List[ResourceItem] = [] # Will be collected in monitoring tasks miner_1_cargo_journal: List[ResourceContainerI.Content] = [] miner_2_cargo_journal: List[ResourceContainerI.Content] = [] async def do_monitoring( container: modules.ResourceContainer, journal: List[ResourceContainerI.Content]) \ -> ResourceContainerI.Status: async for status, content in container.monitor(): if content: journal.append(content) else: return status return ResourceContainerI.Status.SUCCESS miner_1_cargo_monitoring = asyncio.create_task( do_monitoring(miner_1_cargo, miner_1_cargo_journal), ) miner_2_cargo_monitoring = asyncio.create_task( do_monitoring(miner_2_cargo, miner_2_cargo_journal), ) status = await miner_1_cargo.transfer(port=port, access_key=access_key, progress_cb=transactions.append, resource=ResourceItem( ResourceType.e_METALS, 30000)) # Wait some additional time for monitoring events await asyncio.sleep(0.2) self.assertTrue(miner_1_cargo_monitoring.cancel()) self.assertTrue(miner_2_cargo_monitoring.cancel()) await asyncio.wait( [miner_1_cargo_monitoring, miner_2_cargo_monitoring]) # Check that all data are consistent self.assertEqual(len(miner_1_cargo_journal), len(miner_2_cargo_journal)) self.assertEqual(len(miner_1_cargo_journal), len(transactions) + 1) self.assertEqual(len(miner_2_cargo_journal), len(transactions) + 1) current_content = miner_1_cargo_journal[0] for updated_content, transaction in \ zip(miner_1_cargo_journal[1:], transactions): resource_type = transaction.resource_type amount = transaction.amount self.assertAlmostEqual( updated_content.resources[resource_type], current_content.resources[resource_type] - amount) current_content = updated_content current_content = miner_2_cargo_journal[0] for updated_content, transaction in \ zip(miner_2_cargo_journal[1:], transactions): resource_type = transaction.resource_type amount = transaction.amount self.assertAlmostEqual( updated_content.resources[resource_type], current_content.resources[resource_type] + amount) current_content = updated_content