mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Use unique callsigns for each flight (#3445)
This PR partially addresses #1561 by automatically generating unique callsigns for each flight.
This commit is contained in:
parent
0e9a8ac1a1
commit
25b93b5d6d
@ -4,12 +4,14 @@ Saves from 11.x are not compatible with 12.0.0.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** Support for DCS 2.9.8.1214.
|
||||
* **[Campaign]** Removed deprecated settings for generating persistent and invulnerable AWACs and tankers.
|
||||
* **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3.
|
||||
* **[Campaign]** Do not allow aircraft from a captured control point to retreat if the captured control point has a damaged runway.
|
||||
* **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Campaign]** Flights are assigned different callsigns appropriate to the faction.
|
||||
|
||||
# 11.1.1
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ from ..sidc import (
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.callsigns.callsigngenerator import Callsign
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.sim.gameupdateevents import GameUpdateEvents
|
||||
from game.sim.simulationresults import SimulationResults
|
||||
@ -49,6 +50,7 @@ class Flight(SidcDescribable):
|
||||
custom_name: Optional[str] = None,
|
||||
cargo: Optional[TransferOrder] = None,
|
||||
roster: Optional[FlightRoster] = None,
|
||||
callsign: Optional[Callsign] = None,
|
||||
) -> None:
|
||||
self.id = uuid.uuid4()
|
||||
self.package = package
|
||||
@ -69,6 +71,8 @@ class Flight(SidcDescribable):
|
||||
# Only used by transport missions.
|
||||
self.cargo = cargo
|
||||
|
||||
self.callsign = callsign
|
||||
|
||||
# Flight properties that can be set in the mission editor. This is used for
|
||||
# things like HMD selection, ripple quantity, etc. Any values set here will take
|
||||
# the place of the defaults defined by DCS.
|
||||
|
||||
248
game/callsigns/callsigngenerator.py
Normal file
248
game/callsigns/callsigngenerator.py
Normal file
@ -0,0 +1,248 @@
|
||||
from __future__ import annotations
|
||||
from abc import ABC
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from collections import deque
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from dcs.country import Country
|
||||
from dcs.countries import countries_by_name
|
||||
|
||||
from game.ato.flight import Flight
|
||||
from game.ato.flighttype import FlightType
|
||||
|
||||
|
||||
MAX_GROUP_ID = 99
|
||||
|
||||
|
||||
class CallsignCategory(StrEnum):
|
||||
AIR = "Air"
|
||||
TANKERS = "Tankers"
|
||||
AWACS = "AWACS"
|
||||
GROUND_UNITS = "GroundUnits"
|
||||
HELIPADS = "Helipad"
|
||||
GRASS_AIRFIELDS = "GrassAirfield"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Callsign:
|
||||
name: Optional[
|
||||
str
|
||||
] # Callsign name e.g. "Enfield" for western callsigns. None for eastern callsigns.
|
||||
group_id: int # ID of the group e.g. 2 in Enfield-2-3 for western callsigns. First two digits of eastern callsigns.
|
||||
unit_id: int # ID of the unit e.g. 3 in Enfield-2-3 for western callsigns. Last digit of eastern callsigns.
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.group_id < 1 or self.group_id > MAX_GROUP_ID:
|
||||
raise ValueError(
|
||||
f"Invalid group ID {self.group_id}. Group IDs have to be between 1 and {MAX_GROUP_ID}."
|
||||
)
|
||||
if self.unit_id < 1 or self.unit_id > 9:
|
||||
raise ValueError(
|
||||
f"Invalid unit ID {self.unit_id}. Unit IDs have to be between 1 and 9."
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.name is not None:
|
||||
return f"{self.name}{self.group_id}{self.unit_id}"
|
||||
else:
|
||||
return str(self.group_id * 10 + self.unit_id)
|
||||
|
||||
def lead_callsign(self) -> Callsign:
|
||||
return Callsign(self.name, self.group_id, 1)
|
||||
|
||||
def unit_callsign(self, unit_id: int) -> Callsign:
|
||||
return Callsign(self.name, self.group_id, unit_id)
|
||||
|
||||
def group_name(self) -> str:
|
||||
if self.name is not None:
|
||||
return f"{self.name}-{self.group_id}"
|
||||
else:
|
||||
return str(self.lead_callsign())
|
||||
|
||||
def pydcs_dict(self, country: str) -> dict[Any, Any]:
|
||||
country_obj = countries_by_name[country]()
|
||||
for category in CallsignCategory:
|
||||
if category in country_obj.callsign:
|
||||
for index, name in enumerate(country_obj.callsign[category]):
|
||||
if name == self.name:
|
||||
return {
|
||||
"name": str(self),
|
||||
1: index + 1,
|
||||
2: self.group_id,
|
||||
3: self.unit_id,
|
||||
}
|
||||
raise ValueError(f"Could not find callsign {name} in {country}.")
|
||||
|
||||
|
||||
class WesternGroupIdRegistry:
|
||||
|
||||
def __init__(self, country: Country, max_group_id: int = MAX_GROUP_ID):
|
||||
self._names: dict[str, deque[int]] = {}
|
||||
for category in CallsignCategory:
|
||||
if category in country.callsign:
|
||||
for name in country.callsign[category]:
|
||||
self._names[name] = deque()
|
||||
self._max_group_id = max_group_id
|
||||
self.reset()
|
||||
|
||||
def reset(self) -> None:
|
||||
for name in self._names:
|
||||
self._names[name] = deque()
|
||||
for i in range(
|
||||
self._max_group_id, 0, -1
|
||||
): # Put group IDs on FIFO queue so 1 gets popped first
|
||||
self._names[name].appendleft(i)
|
||||
|
||||
def alloc_group_id(self, name: str) -> int:
|
||||
return self._names[name].popleft()
|
||||
|
||||
def release_group_id(self, callsign: Callsign) -> None:
|
||||
if callsign.name is None:
|
||||
raise ValueError("Releasing eastern callsign")
|
||||
self._names[callsign.name].appendleft(callsign.group_id)
|
||||
|
||||
|
||||
class EasternGroupIdRegistry:
|
||||
|
||||
def __init__(self, max_group_id: int = MAX_GROUP_ID):
|
||||
self._max_group_id = max_group_id
|
||||
self._queue: deque[int] = deque()
|
||||
self.reset()
|
||||
|
||||
def reset(self) -> None:
|
||||
self._queue = deque()
|
||||
for i in range(
|
||||
self._max_group_id, 0, -1
|
||||
): # Put group IDs on FIFO queue so 1 gets popped first
|
||||
self._queue.appendleft(i)
|
||||
|
||||
def alloc_group_id(self) -> int:
|
||||
return self._queue.popleft()
|
||||
|
||||
def release_group_id(self, callsign: Callsign) -> None:
|
||||
self._queue.appendleft(callsign.group_id)
|
||||
|
||||
|
||||
class RoundRobinNameAllocator:
|
||||
|
||||
def __init__(self, names: List[str]):
|
||||
self.names = names
|
||||
self._index = 0
|
||||
|
||||
def allocate(self) -> str:
|
||||
this_index = self._index
|
||||
if this_index == len(self.names) - 1:
|
||||
self._index = 0
|
||||
else:
|
||||
self._index += 1
|
||||
return self.names[this_index]
|
||||
|
||||
|
||||
class FlightTypeNameAllocator:
|
||||
def __init__(self, names: List[str]):
|
||||
self.names = names
|
||||
|
||||
def allocate(self, flight: Flight) -> str:
|
||||
index = self.FLIGHT_TYPE_LOOKUP.get(flight.flight_type, 0)
|
||||
return self.names[index]
|
||||
|
||||
FLIGHT_TYPE_LOOKUP: dict[FlightType, int] = {
|
||||
FlightType.TARCAP: 1,
|
||||
FlightType.BARCAP: 1,
|
||||
FlightType.INTERCEPTION: 1,
|
||||
FlightType.SWEEP: 1,
|
||||
FlightType.CAS: 2,
|
||||
FlightType.ANTISHIP: 2,
|
||||
FlightType.BAI: 2,
|
||||
FlightType.STRIKE: 3,
|
||||
FlightType.OCA_RUNWAY: 3,
|
||||
FlightType.OCA_AIRCRAFT: 3,
|
||||
FlightType.SEAD: 4,
|
||||
FlightType.DEAD: 4,
|
||||
FlightType.ESCORT: 5,
|
||||
FlightType.AIR_ASSAULT: 6,
|
||||
FlightType.TRANSPORT: 7,
|
||||
FlightType.FERRY: 7,
|
||||
}
|
||||
|
||||
|
||||
class WesternFlightCallsignGenerator:
|
||||
"""Generate western callsign for lead unit in a group"""
|
||||
|
||||
def __init__(self, country: str) -> None:
|
||||
self._country = countries_by_name[country]()
|
||||
self._group_id_registry = WesternGroupIdRegistry(self._country)
|
||||
self._awacs_name_allocator = None
|
||||
self._tankers_name_allocator = None
|
||||
|
||||
if CallsignCategory.AWACS in self._country.callsign:
|
||||
self._awacs_name_allocator = RoundRobinNameAllocator(
|
||||
self._country.callsign[CallsignCategory.AWACS]
|
||||
)
|
||||
if CallsignCategory.TANKERS in self._country.callsign:
|
||||
self._tankers_name_allocator = RoundRobinNameAllocator(
|
||||
self._country.callsign[CallsignCategory.TANKERS]
|
||||
)
|
||||
self._air_name_allocator = FlightTypeNameAllocator(
|
||||
self._country.callsign[CallsignCategory.AIR]
|
||||
)
|
||||
|
||||
def reset(self) -> None:
|
||||
self._group_id_registry.reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
if flight.flight_type == FlightType.AEWC:
|
||||
if self._awacs_name_allocator is None:
|
||||
raise ValueError(f"{self._country.name} does not have AWACs callsigns")
|
||||
name = self._awacs_name_allocator.allocate()
|
||||
elif flight.flight_type == FlightType.REFUELING:
|
||||
if self._tankers_name_allocator is None:
|
||||
raise ValueError(f"{self._country.name} does not have tanker callsigns")
|
||||
name = self._tankers_name_allocator.allocate()
|
||||
else:
|
||||
name = self._air_name_allocator.allocate(flight)
|
||||
group_id = self._group_id_registry.alloc_group_id(name)
|
||||
return Callsign(name, group_id, 1)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._group_id_registry.release_group_id(callsign)
|
||||
|
||||
|
||||
class EasternFlightCallsignGenerator:
|
||||
"""Generate eastern callsign for lead unit in a group"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._group_id_registry = EasternGroupIdRegistry()
|
||||
|
||||
def reset(self) -> None:
|
||||
self._group_id_registry.reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
group_id = self._group_id_registry.alloc_group_id()
|
||||
return Callsign(None, group_id, 1)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._group_id_registry.release_group_id(callsign)
|
||||
|
||||
|
||||
class FlightCallsignGenerator:
|
||||
|
||||
def __init__(self, country: str):
|
||||
self._generators: dict[
|
||||
bool, WesternFlightCallsignGenerator | EasternFlightCallsignGenerator
|
||||
] = {
|
||||
True: WesternFlightCallsignGenerator(country),
|
||||
False: EasternFlightCallsignGenerator(),
|
||||
}
|
||||
self._use_western_callsigns = countries_by_name[country]().use_western_callsigns
|
||||
|
||||
def reset(self) -> None:
|
||||
self._generators[self._use_western_callsigns].reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
return self._generators[self._use_western_callsigns].alloc_callsign(flight)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._generators[self._use_western_callsigns].release_callsign(callsign)
|
||||
@ -7,6 +7,7 @@ from faker import Faker
|
||||
|
||||
from game.armedforces.armedforces import ArmedForces
|
||||
from game.ato.airtaaskingorder import AirTaskingOrder
|
||||
from game.callsigns.callsigngenerator import FlightCallsignGenerator
|
||||
from game.campaignloader.defaultsquadronassigner import DefaultSquadronAssigner
|
||||
from game.commander import TheaterCommander
|
||||
from game.commander.missionscheduler import MissionScheduler
|
||||
@ -46,6 +47,7 @@ class Coalition:
|
||||
self.air_wing = AirWing(player, game, self.faction)
|
||||
self.armed_forces = ArmedForces(self.faction)
|
||||
self.transfers = PendingTransfers(game, player)
|
||||
self.callsign_generator = FlightCallsignGenerator(faction.country)
|
||||
|
||||
# Late initialized because the two coalitions in the game are mutually
|
||||
# dependent, so must be both constructed before this property can be set.
|
||||
@ -163,6 +165,8 @@ class Coalition:
|
||||
# is handled correctly.
|
||||
self.transfers.perform_transfers()
|
||||
|
||||
self.callsign_generator.reset()
|
||||
|
||||
def preinit_turn_0(self) -> None:
|
||||
"""Runs final Coalition initialization.
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from game.callsigns.callsigngenerator import FlightCallsignGenerator
|
||||
from game.theater import ControlPoint, MissionTarget, OffMapSpawn
|
||||
from game.utils import nautical_miles
|
||||
from ..ato.flight import Flight
|
||||
@ -26,6 +27,7 @@ class PackageBuilder:
|
||||
closest_airfields: ClosestAirfields,
|
||||
air_wing: AirWing,
|
||||
laser_code_registry: LaserCodeRegistry,
|
||||
callsign_generator: FlightCallsignGenerator,
|
||||
flight_db: Database[Flight],
|
||||
is_player: bool,
|
||||
package_country: str,
|
||||
@ -38,6 +40,7 @@ class PackageBuilder:
|
||||
self.package = Package(location, flight_db, auto_asap=asap)
|
||||
self.air_wing = air_wing
|
||||
self.laser_code_registry = laser_code_registry
|
||||
self.callsign_generator = callsign_generator
|
||||
self.start_type = start_type
|
||||
|
||||
def plan_flight(self, plan: ProposedFlight) -> bool:
|
||||
@ -71,6 +74,7 @@ class PackageBuilder:
|
||||
member.assign_tgp_laser_code(
|
||||
self.laser_code_registry.alloc_laser_code()
|
||||
)
|
||||
flight.callsign = self.callsign_generator.alloc_callsign(flight)
|
||||
self.package.add_flight(flight)
|
||||
return True
|
||||
|
||||
|
||||
@ -142,6 +142,7 @@ class PackageFulfiller:
|
||||
ObjectiveDistanceCache.get_closest_airfields(mission.location),
|
||||
self.air_wing,
|
||||
self.coalition.laser_code_registry,
|
||||
self.coalition.callsign_generator,
|
||||
self.flight_db,
|
||||
self.is_player,
|
||||
self.coalition.country_name,
|
||||
|
||||
@ -6,7 +6,7 @@ from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from dcs.flyingunit import FlyingUnit
|
||||
|
||||
from game.callsigns import create_group_callsign_from_unit
|
||||
from game.callsigns.callsign import create_group_callsign_from_unit
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato import FlightType, FlightWaypoint, Package
|
||||
|
||||
@ -10,7 +10,8 @@ from dcs.unit import Skill
|
||||
from dcs.unitgroup import FlyingGroup
|
||||
|
||||
from game.ato import Flight, FlightType
|
||||
from game.callsigns import callsign_for_support_unit
|
||||
from game.callsigns.callsign import callsign_for_support_unit
|
||||
from game.callsigns.callsigngenerator import Callsign, FlightCallsignGenerator
|
||||
from game.data.weapons import Pylon
|
||||
from game.missiongenerator.logisticsgenerator import LogisticsGenerator
|
||||
from game.missiongenerator.missiondata import AwacsInfo, MissionData, TankerInfo
|
||||
@ -115,6 +116,8 @@ class FlightGroupConfigurator:
|
||||
self.flight.flight_plan.waypoints,
|
||||
)
|
||||
|
||||
self.set_callsigns()
|
||||
|
||||
return FlightData(
|
||||
package=self.flight.package,
|
||||
aircraft_type=self.flight.unit_type,
|
||||
@ -269,3 +272,17 @@ class FlightGroupConfigurator:
|
||||
# our own tracking, so undo that.
|
||||
# https://github.com/pydcs/dcs/commit/303a81a8e0c778599fe136dd22cb2ae8123639a6
|
||||
unit.fuel = self.flight.unit_type.dcs_unit_type.fuel_max
|
||||
|
||||
def set_callsigns(self) -> None:
|
||||
if self.flight.callsign is None:
|
||||
return
|
||||
for unit_index, unit in enumerate(self.group.units):
|
||||
unit_callsign = self.flight.callsign.unit_callsign(unit_index + 1)
|
||||
if (
|
||||
unit_callsign.name is None
|
||||
): # pydcs needs unit.callsign to be set for eastern callsigns
|
||||
unit.callsign = str(unit_callsign) # type: ignore
|
||||
else: # Use western callsign
|
||||
unit.callsign_dict = unit_callsign.pydcs_dict(
|
||||
country=self.flight.country
|
||||
)
|
||||
|
||||
@ -27,7 +27,7 @@ from dcs.triggers import Event, TriggerOnce
|
||||
from dcs.unit import Skill, Vehicle
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game.callsigns import callsign_for_support_unit
|
||||
from game.callsigns.callsign import callsign_for_support_unit
|
||||
from game.data.units import UnitClass
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
|
||||
@ -177,6 +177,9 @@ class PackageModel(QAbstractListModel):
|
||||
"""Removes the given flight from the package."""
|
||||
with self.game_model.sim_controller.paused_sim():
|
||||
index = self.package.flights.index(flight)
|
||||
self.game_model.game.blue.callsign_generator.release_callsign(
|
||||
flight.callsign
|
||||
)
|
||||
self.beginRemoveRows(QModelIndex(), index, index)
|
||||
self.package.remove_flight(flight)
|
||||
self.endRemoveRows()
|
||||
@ -302,6 +305,10 @@ class AtoModel(QAbstractListModel):
|
||||
self.package_models.release(package)
|
||||
index = self.ato.packages.index(package)
|
||||
self.beginRemoveRows(QModelIndex(), index, index)
|
||||
for flight in package.flights:
|
||||
self.game_model.game.blue.callsign_generator.release_callsign(
|
||||
flight.callsign
|
||||
)
|
||||
self.ato.remove_package(package)
|
||||
self.endRemoveRows()
|
||||
# noinspection PyUnresolvedReferences
|
||||
|
||||
@ -202,6 +202,8 @@ class QFlightCreator(QDialog):
|
||||
self.game.laser_code_registry.alloc_laser_code()
|
||||
)
|
||||
|
||||
flight.callsign = self.game.blue.callsign_generator.alloc_callsign(flight)
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.created.emit(flight)
|
||||
self.accept()
|
||||
|
||||
@ -18,9 +18,19 @@ class QFlightTypeTaskInfo(QGroupBox):
|
||||
self.task_type = QLabel(str(flight.flight_type))
|
||||
self.task_type.setProperty("style", flight.flight_type.name)
|
||||
|
||||
self.callsign_label = QLabel("Flight Lead Callsign:")
|
||||
if flight.callsign is not None:
|
||||
callsign = flight.callsign.group_name()
|
||||
else:
|
||||
callsign = ""
|
||||
self.callsign = QLabel(callsign)
|
||||
|
||||
layout.addWidget(self.aircraft_icon, 0, 0)
|
||||
|
||||
layout.addWidget(self.task, 1, 0)
|
||||
layout.addWidget(self.task_type, 1, 1)
|
||||
|
||||
layout.addWidget(self.callsign_label, 2, 0)
|
||||
layout.addWidget(self.callsign, 2, 1)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
@ -36,7 +36,7 @@ pre-commit==3.5.0
|
||||
pydantic==2.5.2
|
||||
pydantic-settings==2.1.0
|
||||
pydantic_core==2.14.5
|
||||
pydcs @ git+https://github.com/dcs-liberation/dcs@47b524e3cfaa945d1f42717ee00f949b3354125c
|
||||
pydcs @ git+https://github.com/dcs-liberation/dcs@52b1a3510829dd46d52bbb79ba18e85e8608f25c
|
||||
pyinstaller==5.13.1
|
||||
pyinstaller-hooks-contrib==2023.6
|
||||
pyproj==3.6.1
|
||||
|
||||
79
tests/callsigns/test_callsign_generator.py
Normal file
79
tests/callsigns/test_callsign_generator.py
Normal file
@ -0,0 +1,79 @@
|
||||
import pytest
|
||||
|
||||
from dcs.countries import countries_by_name
|
||||
|
||||
from game.callsigns.callsigngenerator import (
|
||||
Callsign,
|
||||
EasternGroupIdRegistry,
|
||||
WesternGroupIdRegistry,
|
||||
RoundRobinNameAllocator,
|
||||
)
|
||||
|
||||
|
||||
def test_callsign() -> None:
|
||||
|
||||
valid_callsign = Callsign("Enfield", 2, 3)
|
||||
assert str(valid_callsign) == "Enfield23"
|
||||
assert valid_callsign.group_name() == "Enfield-2"
|
||||
assert valid_callsign.pydcs_dict("USA") == {"name": "Enfield23", 1: 1, 2: 2, 3: 3}
|
||||
|
||||
# Invalid callsign, group ID too large.
|
||||
with pytest.raises(ValueError):
|
||||
Callsign("Enfield", 1000, 3)
|
||||
|
||||
# Invalid callsign, group ID zero.
|
||||
with pytest.raises(ValueError):
|
||||
Callsign("Enfield", 0, 3)
|
||||
|
||||
# Invalid callsign, unit ID zero.
|
||||
with pytest.raises(ValueError):
|
||||
Callsign("Enfield", 1, 0)
|
||||
|
||||
# Invalid callsign, unit ID too large.
|
||||
with pytest.raises(ValueError):
|
||||
Callsign("Enfield", 1, 11)
|
||||
|
||||
|
||||
def test_western_group_id_registry() -> None:
|
||||
registry = WesternGroupIdRegistry(countries_by_name["USA"]())
|
||||
|
||||
# Check registry increments group IDs.
|
||||
assert registry.alloc_group_id("Enfield") == 1
|
||||
assert registry.alloc_group_id("Enfield") == 2
|
||||
|
||||
# Check allocation on a new name Springfield.
|
||||
assert registry.alloc_group_id("Springfield") == 1
|
||||
|
||||
# Check release of Enfield-1.
|
||||
registry.release_group_id(Callsign("Enfield", 1, 1))
|
||||
assert registry.alloc_group_id("Enfield") == 1
|
||||
|
||||
# Reset and check allocation og Enfield-1 and Springfield-1.
|
||||
registry.reset()
|
||||
assert registry.alloc_group_id("Enfield") == 1
|
||||
assert registry.alloc_group_id("Springfield") == 1
|
||||
|
||||
|
||||
def test_eastern_group_id_registry() -> None:
|
||||
registry = EasternGroupIdRegistry()
|
||||
|
||||
# Check registry increments group IDs.
|
||||
assert registry.alloc_group_id() == 1
|
||||
assert registry.alloc_group_id() == 2
|
||||
|
||||
# Check release.
|
||||
registry.release_group_id(Callsign(None, 1, 1))
|
||||
assert registry.alloc_group_id() == 1
|
||||
|
||||
# Reset and check allocation.
|
||||
registry.reset()
|
||||
assert registry.alloc_group_id() == 1
|
||||
|
||||
|
||||
def test_round_robin_allocator() -> None:
|
||||
allocator = RoundRobinNameAllocator(["A", "B", "C"])
|
||||
|
||||
assert allocator.allocate() == "A"
|
||||
assert allocator.allocate() == "B"
|
||||
assert allocator.allocate() == "C"
|
||||
assert allocator.allocate() == "A"
|
||||
Loading…
x
Reference in New Issue
Block a user