Add tests for LaserCodeRegistry, clean up.

* Store a deque rather than an iterator so it can be pickled
* Remove mangling from staticmethod (and rename now that it's no longer
  a generator)
* Rename "get" to "alloc" to make the mutation clear
* Move to its own package (the changes I'm working on make this no
  longer mission generator specific)
* Remove useless exception class. It's never caught so the unique type
  isn't needed
This commit is contained in:
Dan Albert 2023-07-21 23:35:01 -07:00 committed by Raffson
parent 485229b92f
commit 279572ae09
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
8 changed files with 29 additions and 22 deletions

View File

@ -0,0 +1 @@
from .lasercoderegistry import LaserCodeRegistry

View File

@ -1,30 +1,21 @@
from collections import deque from collections import deque
from typing import Iterator
class OutOfLaserCodesError(RuntimeError):
def __init__(self) -> None:
super().__init__(
f"All JTAC laser codes have been allocated. No available codes."
)
class LaserCodeRegistry: class LaserCodeRegistry:
def __init__(self) -> None: def __init__(self) -> None:
self.allocated_codes: set[int] = set() self.allocated_codes: set[int] = set()
self.allocator: Iterator[int] = LaserCodeRegistry.__laser_code_generator() self.available_codes = LaserCodeRegistry._all_valid_laser_codes()
def get_next_laser_code(self) -> int: def alloc_laser_code(self) -> int:
try: try:
while (code := next(self.allocator)) in self.allocated_codes: code = self.available_codes.popleft()
pass
self.allocated_codes.add(code) self.allocated_codes.add(code)
return code return code
except StopIteration: except IndexError:
raise OutOfLaserCodesError raise RuntimeError("All laser codes have been allocated")
@staticmethod @staticmethod
def __laser_code_generator() -> Iterator[int]: def _all_valid_laser_codes() -> deque[int]:
# Valid laser codes are as follows # Valid laser codes are as follows
# First digit is always 1 # First digit is always 1
# Second digit is 5-7 # Second digit is 5-7
@ -34,4 +25,4 @@ class LaserCodeRegistry:
# We start with the default of 1688 and wrap around when we reach the end # We start with the default of 1688 and wrap around when we reach the end
q.rotate(-q.index(1688)) q.rotate(-q.index(1688))
return iter(q) return q

View File

@ -21,7 +21,7 @@ from game.ato.flightstate import Completed, WaitingForStart
from game.ato.flighttype import FlightType from game.ato.flighttype import FlightType
from game.ato.package import Package from game.ato.package import Package
from game.ato.starttype import StartType from game.ato.starttype import StartType
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry from game.lasercodes import LaserCodeRegistry
from game.missiongenerator.missiondata import MissionData from game.missiongenerator.missiondata import MissionData
from game.radio.radios import RadioRegistry from game.radio.radios import RadioRegistry
from game.radio.tacan import TacanRegistry from game.radio.tacan import TacanRegistry

View File

@ -16,7 +16,7 @@ from dcs.unitgroup import FlyingGroup
from game.ato import Flight, FlightType from game.ato import Flight, FlightType
from game.callsigns import callsign_for_support_unit from game.callsigns import callsign_for_support_unit
from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry from game.lasercodes import LaserCodeRegistry
from game.missiongenerator.logisticsgenerator import LogisticsGenerator from game.missiongenerator.logisticsgenerator import LogisticsGenerator
from game.missiongenerator.missiondata import MissionData, AwacsInfo, TankerInfo from game.missiongenerator.missiondata import MissionData, AwacsInfo, TankerInfo
from game.radio.radios import RadioFrequency, RadioRegistry from game.radio.radios import RadioFrequency, RadioRegistry
@ -148,7 +148,7 @@ class FlightGroupConfigurator:
) -> None: ) -> None:
self.set_skill(unit, member) self.set_skill(unit, member)
if member.loadout.has_weapon_of_type(WeaponTypeEnum.TGP) and member.is_player: if member.loadout.has_weapon_of_type(WeaponTypeEnum.TGP) and member.is_player:
laser_codes.append(self.laser_code_registry.get_next_laser_code()) laser_codes.append(self.laser_code_registry.alloc_laser_code())
else: else:
laser_codes.append(None) laser_codes.append(None)
settings = self.flight.coalition.game.settings settings = self.flight.coalition.game.settings

View File

@ -37,6 +37,7 @@ from game.ground_forces.ai_ground_planner import (
DISTANCE_FROM_FRONTLINE, DISTANCE_FROM_FRONTLINE,
) )
from game.ground_forces.combat_stance import CombatStance from game.ground_forces.combat_stance import CombatStance
from game.lasercodes import LaserCodeRegistry
from game.naming import namegen from game.naming import namegen
from game.radio.radios import RadioRegistry from game.radio.radios import RadioRegistry
from game.theater.controlpoint import ControlPoint from game.theater.controlpoint import ControlPoint
@ -44,7 +45,6 @@ from game.unitmap import UnitMap
from game.utils import Heading from game.utils import Heading
from .frontlineconflictdescription import FrontLineConflictDescription from .frontlineconflictdescription import FrontLineConflictDescription
from .groundforcepainter import GroundForcePainter from .groundforcepainter import GroundForcePainter
from .lasercoderegistry import LaserCodeRegistry
from .missiondata import JtacInfo, MissionData from .missiondata import JtacInfo, MissionData
from ..ato import FlightType from ..ato import FlightType
@ -152,7 +152,7 @@ class FlotGenerator:
if self.game.settings.plugins.get("ctld.fc3LaserCode"): if self.game.settings.plugins.get("ctld.fc3LaserCode"):
code = 1113 code = 1113
else: else:
code = self.laser_code_registry.get_next_laser_code() code = self.laser_code_registry.alloc_laser_code()
utype = self.game.blue.faction.jtac_unit utype = self.game.blue.faction.jtac_unit
if utype is None: if utype is None:

View File

@ -32,7 +32,7 @@ from .flotgenerator import FlotGenerator
from .forcedoptionsgenerator import ForcedOptionsGenerator from .forcedoptionsgenerator import ForcedOptionsGenerator
from .frontlineconflictdescription import FrontLineConflictDescription from .frontlineconflictdescription import FrontLineConflictDescription
from .kneeboard import KneeboardGenerator from .kneeboard import KneeboardGenerator
from .lasercoderegistry import LaserCodeRegistry from game.lasercodes import LaserCodeRegistry
from .luagenerator import LuaGenerator from .luagenerator import LuaGenerator
from .missiondata import MissionData from .missiondata import MissionData
from .tgogenerator import TgoGenerator from .tgogenerator import TgoGenerator

View File

View File

@ -0,0 +1,15 @@
from game.lasercodes.lasercoderegistry import LaserCodeRegistry
def test_initial_laser_codes() -> None:
reg = LaserCodeRegistry()
assert list(reg.available_codes)[:5] == [1688, 1687, 1686, 1685, 1684]
assert list(reg.available_codes)[-5:] == [1715, 1714, 1713, 1712, 1711]
assert len(reg.available_codes) == 192
def test_alloc_laser_code() -> None:
reg = LaserCodeRegistry()
assert reg.alloc_laser_code() == 1688
assert 1688 not in reg.available_codes
assert len(reg.available_codes) == 191