diff --git a/game/debriefing.py b/game/debriefing.py index 8d8fcb89..dd6a53b8 100644 --- a/game/debriefing.py +++ b/game/debriefing.py @@ -6,22 +6,14 @@ import os import threading import time from collections import defaultdict -from dataclasses import dataclass, field -from typing import ( - Any, - Callable, - Dict, - Iterator, - List, - Type, - TYPE_CHECKING, -) +from dataclasses import dataclass +from typing import Any, Callable, Dict, List, Type, TYPE_CHECKING from dcs.unittype import FlyingType, UnitType from game import db -from game.theater import Airfield, ControlPoint -from game.unitmap import Building, FrontLineUnit, GroundObjectUnit, UnitMap +from game.theater import Airfield, ControlPoint, TheaterGroundObject +from game.unitmap import UnitMap from gen.flights.flight import Flight if TYPE_CHECKING: @@ -30,6 +22,12 @@ if TYPE_CHECKING: DEBRIEFING_LOG_EXTENSION = "log" +@dataclass(frozen=True) +class DebriefingDeadUnitInfo: + player_unit: bool + type: Type[UnitType] + + @dataclass(frozen=True) class DebriefingDeadAircraftInfo: #: The Flight that resulted in the generated unit. @@ -40,6 +38,27 @@ class DebriefingDeadAircraftInfo: return self.flight.departure.captured +@dataclass(frozen=True) +class DebriefingDeadFrontLineUnitInfo: + #: The Flight that resulted in the generated unit. + unit_type: Type[UnitType] + control_point: ControlPoint + + @property + def player_unit(self) -> bool: + return self.control_point.captured + + +@dataclass(frozen=True) +class DebriefingDeadBuildingInfo: + #: The ground object this building was present at. + ground_object: TheaterGroundObject + + @property + def player_unit(self) -> bool: + return self.ground_object.control_point.captured + + @dataclass(frozen=True) class AirLosses: losses: List[DebriefingDeadAircraftInfo] @@ -61,12 +80,18 @@ class AirLosses: return flight.count - losses -@dataclass -class GroundLosses: - front_line: List[FrontLineUnit] = field(default_factory=list) - ground_objects: List[GroundObjectUnit] = field(default_factory=list) - buildings: List[Building] = field(default_factory=list) - airfields: List[Airfield] = field(default_factory=list) +@dataclass(frozen=True) +class FrontLineLosses: + losses: List[DebriefingDeadFrontLineUnitInfo] + + def by_type(self, player: bool) -> Dict[Type[UnitType], int]: + losses_by_type: Dict[Type[UnitType], int] = defaultdict(int) + for loss in self.losses: + if loss.control_point.captured != player: + continue + + losses_by_type[loss.unit_type] += 1 + return losses_by_type @dataclass(frozen=True) @@ -106,51 +131,80 @@ class Debriefing: self.game = game self.unit_map = unit_map + logging.info("--------------------------------") + logging.info("Starting Debriefing preprocessing") + logging.info("--------------------------------") + logging.info(self.state_data) + logging.info("--------------------------------") + self.player_country_id = db.country_id_from_name(game.player_country) self.enemy_country_id = db.country_id_from_name(game.enemy_country) self.air_losses = self.dead_aircraft() - self.ground_losses = self.dead_ground_units() + self.front_line_losses = self.dead_front_line_units() + self.dead_units = [] + self.damaged_runways = self.find_damaged_runways() + self.dead_aaa_groups: List[DebriefingDeadUnitInfo] = [] + self.dead_buildings: List[DebriefingDeadBuildingInfo] = [] - @property - def front_line_losses(self) -> Iterator[FrontLineUnit]: - yield from self.ground_losses.front_line + for unit_name in self.state_data.killed_ground_units: + for cp in game.theater.controlpoints: + if cp.captured: + country = self.player_country_id + else: + country = self.enemy_country_id + player_unit = (country == self.player_country_id) - @property - def ground_object_losses(self) -> Iterator[GroundObjectUnit]: - yield from self.ground_losses.ground_objects + for ground_object in cp.ground_objects: + # TODO: This seems to destroy an arbitrary building? + if ground_object.is_same_group(unit_name): + self.dead_buildings.append( + DebriefingDeadBuildingInfo(ground_object)) + elif ground_object.dcs_identifier in ["AA", "CARRIER", + "LHA"]: + for g in ground_object.groups: + for u in g.units: + if u.name != unit_name: + continue + unit_type = db.unit_type_from_name(u.type) + if unit_type is None: + logging.error( + f"Could not determine type of %s", + unit_name) + continue + self.dead_units.append(DebriefingDeadUnitInfo( + player_unit, unit_type)) - @property - def building_losses(self) -> Iterator[Building]: - yield from self.ground_losses.buildings + self.player_dead_units = [a for a in self.dead_units if a.player_unit] + self.enemy_dead_units = [a for a in self.dead_units if not a.player_unit] + self.player_dead_buildings = [a for a in self.dead_buildings if a.player_unit] + self.enemy_dead_buildings = [a for a in self.dead_buildings if not a.player_unit] - @property - def damaged_runways(self) -> Iterator[Airfield]: - yield from self.ground_losses.airfields + self.player_dead_units_dict: Dict[Type[UnitType], int] = defaultdict(int) + for a in self.player_dead_units: + self.player_dead_units_dict[a.type] += 1 - def casualty_count(self, control_point: ControlPoint) -> int: - return len( - [x for x in self.front_line_losses if x.origin == control_point] - ) + self.enemy_dead_units_dict: Dict[Type[UnitType], int] = defaultdict(int) + for a in self.enemy_dead_units: + self.enemy_dead_units_dict[a.type] += 1 - def front_line_losses_by_type( - self, player: bool) -> Dict[Type[UnitType], int]: - losses_by_type: Dict[Type[UnitType], int] = defaultdict(int) - for loss in self.ground_losses.front_line: - if loss.origin.captured != player: - continue + self.player_dead_buildings_dict: Dict[str, int] = defaultdict(int) + for b in self.player_dead_buildings: + self.player_dead_buildings_dict[b.ground_object.dcs_identifier] += 1 - losses_by_type[loss.unit_type] += 1 - return losses_by_type + self.enemy_dead_buildings_dict: Dict[str, int] = defaultdict(int) + for b in self.enemy_dead_buildings: + self.enemy_dead_buildings_dict[b.ground_object.dcs_identifier] += 1 - def building_losses_by_type(self, player: bool) -> Dict[str, int]: - losses_by_type: Dict[str, int] = defaultdict(int) - for loss in self.ground_losses.buildings: - if loss.ground_object.control_point.captured != player: - continue - - losses_by_type[loss.ground_object.dcs_identifier] += 1 - return losses_by_type + logging.info("--------------------------------") + logging.info("Debriefing pre process results :") + logging.info("--------------------------------") + logging.info(self.air_losses) + logging.info(self.front_line_losses) + logging.info(self.player_dead_units_dict) + logging.info(self.enemy_dead_units_dict) + logging.info(self.player_dead_buildings_dict) + logging.info(self.enemy_dead_buildings_dict) def dead_aircraft(self) -> AirLosses: losses = [] @@ -162,38 +216,30 @@ class Debriefing: losses.append(DebriefingDeadAircraftInfo(flight)) return AirLosses(losses) - def dead_ground_units(self) -> GroundLosses: - losses = GroundLosses() + def dead_front_line_units(self) -> FrontLineLosses: + losses = [] for unit_name in self.state_data.killed_ground_units: - front_line_unit = self.unit_map.front_line_unit(unit_name) - if front_line_unit is not None: - losses.front_line.append(front_line_unit) + unit = self.unit_map.front_line_unit(unit_name) + if unit is None: + # Killed "ground units" might also be runways or TGO units, so + # no need to log an error. continue + losses.append( + DebriefingDeadFrontLineUnitInfo(unit.unit_type, unit.origin)) + return FrontLineLosses(losses) - ground_object_unit = self.unit_map.ground_object_unit(unit_name) - if ground_object_unit is not None: - losses.ground_objects.append(ground_object_unit) + def find_damaged_runways(self) -> List[Airfield]: + losses = [] + for name in self.state_data.killed_ground_units: + airfield = self.unit_map.airfield(name) + if airfield is None: continue - - building = self.unit_map.building(unit_name) - if building is not None: - losses.buildings.append(building) - continue - - airfield = self.unit_map.airfield(unit_name) - if airfield is not None: - losses.airfields.append(airfield) - continue - - # Only logging as debug because we don't currently track infantry - # deaths, so we expect to see quite a few unclaimed dead ground - # units. We should start tracking those and covert this to a - # warning. - logging.debug(f"Death of untracked ground unit {unit_name} will " - "have no effect. This may be normal behavior.") - + losses.append(airfield) return losses + def _is_airfield(self, unit_name: str) -> bool: + return self.unit_map.airfield(unit_name) is not None + @property def base_capture_events(self): """Keeps only the last instance of a base capture event for each base ID.""" diff --git a/game/event/event.py b/game/event/event.py index eb2e53b7..706da279 100644 --- a/game/event/event.py +++ b/game/event/event.py @@ -2,20 +2,21 @@ from __future__ import annotations import logging import math -from typing import Dict, List, TYPE_CHECKING, Type +from collections import defaultdict +from typing import Dict, List, Optional, TYPE_CHECKING, Type from dcs.mapping import Point from dcs.task import Task from dcs.unittype import UnitType -from game import persistency +from game import db, persistency from game.debriefing import AirLosses, Debriefing from game.infos.information import Information -from game.operation.operation import Operation from game.theater import ControlPoint from gen import AirTaskingOrder from gen.ground_forces.combat_stance import CombatStance from ..unitmap import UnitMap +from game.operation.operation import Operation if TYPE_CHECKING: from ..game import Game @@ -129,10 +130,12 @@ class Event: cp.base.aircraft[aircraft] -= 1 @staticmethod - def commit_front_line_losses(debriefing: Debriefing) -> None: - for loss in debriefing.front_line_losses: + def commit_front_line_losses(debriefing: Debriefing) -> Dict[int, int]: + killed_unit_count_by_cp: Dict[int, int] = defaultdict(int) + for loss in debriefing.front_line_losses.losses: unit_type = loss.unit_type - control_point = loss.origin + control_point = loss.control_point + killed_unit_count_by_cp[control_point.id] += 1 available = control_point.base.total_units_of_type(unit_type) if available <= 0: logging.error( @@ -142,41 +145,64 @@ class Event: logging.info(f"{unit_type} destroyed from {control_point}") control_point.base.armor[unit_type] -= 1 - - @staticmethod - def commit_ground_object_losses(debriefing: Debriefing) -> None: - for loss in debriefing.ground_object_losses: - # TODO: This should be stored in the TGO, not in the pydcs Group. - if not hasattr(loss.group, "units_losts"): - loss.group.units_losts = [] - - loss.group.units.remove(loss.unit) - loss.group.units_losts.append(loss.unit) - if not loss.ground_object.alive_unit_count: - loss.ground_object.is_dead = True - - def commit_building_losses(self, debriefing: Debriefing) -> None: - for loss in debriefing.building_losses: - loss.ground_object.is_dead = True - self.game.informations.append(Information( - "Building destroyed", - f"{loss.ground_object.dcs_identifier} has been destroyed at " - f"location {loss.ground_object.obj_name}", self.game.turn - )) - - @staticmethod - def commit_damaged_runways(debriefing: Debriefing) -> None: - for damaged_runway in debriefing.damaged_runways: - damaged_runway.damage_runway() + return killed_unit_count_by_cp def commit(self, debriefing: Debriefing): logging.info("Committing mission results") + for damaged_runway in debriefing.damaged_runways: + damaged_runway.damage_runway() + self.commit_air_losses(debriefing) - self.commit_front_line_losses(debriefing) - self.commit_ground_object_losses(debriefing) - self.commit_building_losses(debriefing) - self.commit_damaged_runways(debriefing) + killed_unit_count_by_cp = self.commit_front_line_losses(debriefing) + + # ------------------------------ + # Static ground objects + for destroyed_ground_unit_name in debriefing.state_data.killed_ground_units: + for cp in self.game.theater.controlpoints: + if not cp.ground_objects: + continue + + # -- Static ground objects + for i, ground_object in enumerate(cp.ground_objects): + if ground_object.is_dead: + continue + + if ( + (ground_object.group_name == destroyed_ground_unit_name) + or + (ground_object.is_same_group(destroyed_ground_unit_name)) + ): + logging.info("cp {} killing ground object {}".format(cp, ground_object.group_name)) + cp.ground_objects[i].is_dead = True + + info = Information("Building destroyed", + ground_object.dcs_identifier + " has been destroyed at location " + ground_object.obj_name, + self.game.turn) + self.game.informations.append(info) + + + # -- AA Site groups + destroyed_units = 0 + info = Information("Units destroyed at " + ground_object.obj_name, + "", + self.game.turn) + for i, ground_object in enumerate(cp.ground_objects): + if ground_object.dcs_identifier in ["AA", "CARRIER", "LHA", "EWR"]: + for g in ground_object.groups: + if not hasattr(g, "units_losts"): + g.units_losts = [] + for u in g.units: + if u.name == destroyed_ground_unit_name: + g.units.remove(u) + g.units_losts.append(u) + destroyed_units = destroyed_units + 1 + info.text = u.type + ucount = sum([len(g.units) for g in ground_object.groups]) + if ucount == 0: + ground_object.is_dead = True + if destroyed_units > 0: + self.game.informations.append(info) # ------------------------------ # Captured bases @@ -231,8 +257,8 @@ class Event: delta = 0.0 player_won = True - ally_casualties = debriefing.casualty_count(cp) - enemy_casualties = debriefing.casualty_count(enemy_cp) + ally_casualties = killed_unit_count_by_cp[cp.id] + enemy_casualties = killed_unit_count_by_cp[enemy_cp.id] ally_units_alive = cp.base.total_armor enemy_units_alive = enemy_cp.base.total_armor diff --git a/game/operation/operation.py b/game/operation/operation.py index d2c46f58..a63f1f85 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -265,8 +265,7 @@ class Operation: cls.current_mission, cls.game, cls.radio_registry, - cls.tacan_registry, - cls.unit_map + cls.tacan_registry ) cls.groundobjectgen.generate() diff --git a/game/theater/base.py b/game/theater/base.py index 14b96ce2..ba8a72f8 100644 --- a/game/theater/base.py +++ b/game/theater/base.py @@ -23,7 +23,7 @@ class Base: def __init__(self): self.aircraft: Dict[Type[FlyingType], int] = {} - self.armor: Dict[Type[VehicleType], int] = {} + self.armor: Dict[VehicleType, int] = {} self.aa: Dict[AirDefence, int] = {} self.commision_points: Dict[Type, float] = {} self.strength = 1 diff --git a/game/theater/theatergroundobject.py b/game/theater/theatergroundobject.py index 796c2aa9..be5c0a18 100644 --- a/game/theater/theatergroundobject.py +++ b/game/theater/theatergroundobject.py @@ -136,10 +136,6 @@ class TheaterGroundObject(MissionTarget): ] yield from super().mission_types(for_player) - @property - def alive_unit_count(self) -> int: - return sum(len(g.units) for g in self.groups) - class BuildingGroundObject(TheaterGroundObject): def __init__(self, name: str, category: str, group_id: int, object_id: int, diff --git a/game/unitmap.py b/game/unitmap.py index b97fba8e..9c6e20e6 100644 --- a/game/unitmap.py +++ b/game/unitmap.py @@ -2,41 +2,25 @@ from dataclasses import dataclass from typing import Dict, Optional, Type -from dcs.unit import Unit -from dcs.unitgroup import FlyingGroup, Group, StaticGroup -from dcs.unittype import VehicleType +from dcs.unitgroup import FlyingGroup, Group +from dcs.unittype import UnitType from game import db -from game.theater import Airfield, ControlPoint, TheaterGroundObject -from game.theater.theatergroundobject import BuildingGroundObject +from game.theater import Airfield, ControlPoint from gen.flights.flight import Flight -@dataclass(frozen=True) +@dataclass class FrontLineUnit: - unit_type: Type[VehicleType] + unit_type: Type[UnitType] origin: ControlPoint -@dataclass(frozen=True) -class GroundObjectUnit: - ground_object: TheaterGroundObject - group: Group - unit: Unit - - -@dataclass(frozen=True) -class Building: - ground_object: BuildingGroundObject - - class UnitMap: def __init__(self) -> None: self.aircraft: Dict[str, Flight] = {} self.airfields: Dict[str, Airfield] = {} self.front_line_units: Dict[str, FrontLineUnit] = {} - self.ground_object_units: Dict[str, GroundObjectUnit] = {} - self.buildings: Dict[str, Building] = {} def add_aircraft(self, group: FlyingGroup, flight: Flight) -> None: for unit in group.units: @@ -68,36 +52,7 @@ class UnitMap: unit_type = db.unit_type_from_name(unit.type) if unit_type is None: raise RuntimeError(f"Unknown unit type: {unit.type}") - if not issubclass(unit_type, VehicleType): - raise RuntimeError( - f"{name} is a {unit_type.__name__}, expected a VehicleType") self.front_line_units[name] = FrontLineUnit(unit_type, origin) def front_line_unit(self, name: str) -> Optional[FrontLineUnit]: return self.front_line_units.get(name, None) - - def add_ground_object_units(self, ground_object: TheaterGroundObject, - group: Group) -> None: - for unit in group.units: - # The actual name is a String (the pydcs translatable string), which - # doesn't define __eq__. - name = str(unit.name) - if name in self.ground_object_units: - raise RuntimeError(f"Duplicate TGO unit: {name}") - self.ground_object_units[name] = GroundObjectUnit(ground_object, - group, unit) - - def ground_object_unit(self, name: str) -> Optional[GroundObjectUnit]: - return self.ground_object_units.get(name, None) - - def add_building(self, ground_object: BuildingGroundObject, - building: StaticGroup) -> None: - # The actual name is a String (the pydcs translatable string), which - # doesn't define __eq__. - name = str(building.name) - if name in self.buildings: - raise RuntimeError(f"Duplicate TGO unit: {name}") - self.buildings[name] = Building(ground_object) - - def building(self, name: str) -> Optional[Building]: - return self.buildings.get(name, None) diff --git a/gen/groundobjectsgen.py b/gen/groundobjectsgen.py index 26ae027e..e2c30846 100644 --- a/gen/groundobjectsgen.py +++ b/gen/groundobjectsgen.py @@ -9,7 +9,7 @@ from __future__ import annotations import logging import random -from typing import Dict, Iterator, Optional, TYPE_CHECKING, Type +from typing import Dict, Iterator, Optional, TYPE_CHECKING from dcs import Mission from dcs.country import Country @@ -33,7 +33,7 @@ from game.theater.theatergroundobject import ( GenericCarrierGroundObject, LhaGroundObject, ShipGroundObject, ) -from game.unitmap import UnitMap +from .conflictgen import Conflict from .radios import RadioFrequency, RadioRegistry from .runways import RunwayData from .tacan import TacanBand, TacanChannel, TacanRegistry @@ -52,12 +52,11 @@ class GenericGroundObjectGenerator: Currently used only for SAM and missile (V1/V2) sites. """ def __init__(self, ground_object: TheaterGroundObject, country: Country, - game: Game, mission: Mission, unit_map: UnitMap) -> None: + game: Game, mission: Mission) -> None: self.ground_object = ground_object self.country = country self.game = game self.m = mission - self.unit_map = unit_map def generate(self) -> None: if self.game.position_culled(self.ground_object.position): @@ -90,10 +89,9 @@ class GenericGroundObjectGenerator: self.enable_eplrs(vg, unit_type) self.set_alarm_state(vg) - self._register_unit_group(vg) @staticmethod - def enable_eplrs(group: Group, unit_type: Type[UnitType]) -> None: + def enable_eplrs(group: Group, unit_type: UnitType) -> None: if hasattr(unit_type, 'eplrs'): if unit_type.eplrs: group.points[0].tasks.append(EPLRS(group.id)) @@ -104,9 +102,6 @@ class GenericGroundObjectGenerator: else: group.points[0].tasks.append(OptAlarmState(1)) - def _register_unit_group(self, group: Group) -> None: - self.unit_map.add_ground_object_units(self.ground_object, group) - class BuildingSiteGenerator(GenericGroundObjectGenerator): """Generator for building sites. @@ -138,17 +133,16 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator): def generate_vehicle_group(self, unit_type: UnitType) -> None: if not self.ground_object.is_dead: - group = self.m.vehicle_group( + self.m.vehicle_group( country=self.country, name=self.ground_object.group_name, _type=unit_type, position=self.ground_object.position, heading=self.ground_object.heading, ) - self._register_unit_group(group) def generate_static(self, static_type: StaticType) -> None: - group = self.m.static_group( + self.m.static_group( country=self.country, name=self.ground_object.group_name, _type=static_type, @@ -156,11 +150,6 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator): heading=self.ground_object.heading, dead=self.ground_object.is_dead, ) - self._register_building(group) - - def _register_building(self, building: StaticGroup) -> None: - assert isinstance(self.ground_object, BuildingGroundObject) - self.unit_map.add_building(self.ground_object, building) class GenericCarrierGenerator(GenericGroundObjectGenerator): @@ -172,8 +161,8 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator): control_point: ControlPoint, country: Country, game: Game, mission: Mission, radio_registry: RadioRegistry, tacan_registry: TacanRegistry, icls_alloc: Iterator[int], - runways: Dict[str, RunwayData], unit_map: UnitMap) -> None: - super().__init__(ground_object, country, game, mission, unit_map) + runways: Dict[str, RunwayData]) -> None: + super().__init__(ground_object, country, game, mission) self.ground_object = ground_object self.control_point = control_point self.radio_registry = radio_registry @@ -201,9 +190,8 @@ class GenericCarrierGenerator(GenericGroundObjectGenerator): brc = self.steam_into_wind(ship_group) self.activate_beacons(ship_group, tacan, tacan_callsign, icls) self.add_runway_data(brc or 0, atc, tacan, tacan_callsign, icls) - self._register_unit_group(ship_group) - def get_carrier_type(self, group: Group) -> Type[UnitType]: + def get_carrier_type(self, group: Group) -> UnitType: unit_type = unit_type_from_name(group.units[0].type) if unit_type is None: raise RuntimeError( @@ -340,9 +328,8 @@ class ShipObjectGenerator(GenericGroundObjectGenerator): self.generate_group(group, unit_type) - def generate_group(self, group_def: Group, - first_unit_type: Type[UnitType]) -> None: - group = self.m.ship_group(self.country, group_def.name, first_unit_type, + def generate_group(self, group_def: Group, unit_type: UnitType): + group = self.m.ship_group(self.country, group_def.name, unit_type, position=group_def.position, heading=group_def.units[0].heading) group.units[0].name = self.m.string(group_def.units[0].name) @@ -356,7 +343,6 @@ class ShipObjectGenerator(GenericGroundObjectGenerator): ship.heading = unit.heading group.add_unit(ship) self.set_alarm_state(group) - self._register_unit_group(group) class GroundObjectsGenerator: @@ -369,13 +355,11 @@ class GroundObjectsGenerator: """ def __init__(self, mission: Mission, game: Game, - radio_registry: RadioRegistry, tacan_registry: TacanRegistry, - unit_map: UnitMap) -> None: + radio_registry: RadioRegistry, tacan_registry: TacanRegistry): self.m = mission self.game = game self.radio_registry = radio_registry self.tacan_registry = tacan_registry - self.unit_map = unit_map self.icls_alloc = iter(range(1, 21)) self.runways: Dict[str, RunwayData] = {} @@ -389,26 +373,25 @@ class GroundObjectsGenerator: for ground_object in cp.ground_objects: if isinstance(ground_object, BuildingGroundObject): - generator = BuildingSiteGenerator( - ground_object, country, self.game, self.m, - self.unit_map) + generator = BuildingSiteGenerator(ground_object, country, + self.game, self.m) elif isinstance(ground_object, CarrierGroundObject): - generator = CarrierGenerator( - ground_object, cp, country, self.game, self.m, - self.radio_registry, self.tacan_registry, - self.icls_alloc, self.runways, self.unit_map) + generator = CarrierGenerator(ground_object, cp, country, + self.game, self.m, + self.radio_registry, + self.tacan_registry, + self.icls_alloc, self.runways) elif isinstance(ground_object, LhaGroundObject): - generator = CarrierGenerator( - ground_object, cp, country, self.game, self.m, - self.radio_registry, self.tacan_registry, - self.icls_alloc, self.runways, self.unit_map) + generator = CarrierGenerator(ground_object, cp, country, + self.game, self.m, + self.radio_registry, + self.tacan_registry, + self.icls_alloc, self.runways) elif isinstance(ground_object, ShipGroundObject): - generator = ShipObjectGenerator( - ground_object, country, self.game, self.m, - self.unit_map) + generator = ShipObjectGenerator(ground_object, country, + self.game, self.m) else: - - generator = GenericGroundObjectGenerator( - ground_object, country, self.game, self.m, - self.unit_map) + generator = GenericGroundObjectGenerator(ground_object, + country, self.game, + self.m) generator.generate() diff --git a/qt_ui/windows/QDebriefingWindow.py b/qt_ui/windows/QDebriefingWindow.py index 6ef9ef81..4b52d585 100644 --- a/qt_ui/windows/QDebriefingWindow.py +++ b/qt_ui/windows/QDebriefingWindow.py @@ -41,6 +41,13 @@ class QDebriefingWindow(QDialog): self.layout.addWidget(header) self.layout.addStretch() + # Result + #if self.gameEvent.is_successfull(self.debriefing): + # title = QLabel("Operation end !") + # title.setProperty("style", "title-success") + #else: + # title = QLabel("Operation end !") + # title.setProperty("style", "title-danger") title = QLabel("Casualty report") self.layout.addWidget(title) @@ -61,7 +68,7 @@ class QDebriefingWindow(QDialog): logging.exception( f"Issue adding {unit_type} to debriefing information") - front_line_losses = self.debriefing.front_line_losses_by_type( + front_line_losses = self.debriefing.front_line_losses.by_type( player=True ) for unit_type, count in front_line_losses.items(): @@ -74,10 +81,9 @@ class QDebriefingWindow(QDialog): logging.exception( f"Issue adding {unit_type} to debriefing information") - building_losses = self.debriefing.building_losses_by_type(player=True) - for building, count in building_losses.items(): + for building, count in self.debriefing.player_dead_buildings_dict.items(): try: - lostUnitsLayout.addWidget(QLabel(building), row, 0) + lostUnitsLayout.addWidget(QLabel(building, row, 0)) lostUnitsLayout.addWidget(QLabel(str(count)), row, 1) row += 1 except AttributeError: @@ -91,6 +97,12 @@ class QDebriefingWindow(QDialog): enemylostUnitsLayout = QGridLayout() enemylostUnits.setLayout(enemylostUnitsLayout) + #row = 0 + #if self.debriefing.destroyed_objects: + # enemylostUnitsLayout.addWidget(QLabel("Ground assets"), row, 0) + # enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1) + # row += 1 + enemy_air_losses = self.debriefing.air_losses.by_type(player=False) for unit_type, count in enemy_air_losses.items(): try: @@ -102,7 +114,7 @@ class QDebriefingWindow(QDialog): logging.exception( f"Issue adding {unit_type} to debriefing information") - front_line_losses = self.debriefing.front_line_losses_by_type( + front_line_losses = self.debriefing.front_line_losses.by_type( player=False ) for unit_type, count in front_line_losses.items(): @@ -112,8 +124,7 @@ class QDebriefingWindow(QDialog): enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1) row += 1 - building_losses = self.debriefing.building_losses_by_type(player=False) - for building, count in building_losses.items(): + for building, count in self.debriefing.enemy_dead_buildings_dict.items(): try: enemylostUnitsLayout.addWidget(QLabel(building), row, 0) enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1) @@ -124,8 +135,6 @@ class QDebriefingWindow(QDialog): self.layout.addWidget(enemylostUnits) - # TODO: Display dead ground object units and runways. - # confirm button okay = QPushButton("Okay") okay.clicked.connect(self.close) diff --git a/qt_ui/windows/QWaitingForMissionResultWindow.py b/qt_ui/windows/QWaitingForMissionResultWindow.py index 5551dda0..f780091c 100644 --- a/qt_ui/windows/QWaitingForMissionResultWindow.py +++ b/qt_ui/windows/QWaitingForMissionResultWindow.py @@ -138,21 +138,15 @@ class QWaitingForMissionResultWindow(QDialog): updateLayout.addWidget( QLabel("Front line units destroyed"), 1, 0) updateLayout.addWidget( - QLabel(str(len(list(debriefing.front_line_losses)))), 1, 1) + QLabel(str(len(debriefing.front_line_losses.losses))), 1, 1) updateLayout.addWidget( QLabel("Other ground units destroyed"), 2, 0) - updateLayout.addWidget( - QLabel(str(len(list(debriefing.ground_object_losses)))), 2, 1) + updateLayout.addWidget(QLabel(str(len(debriefing.dead_units))), 2, 1) + updateLayout.addWidget(QLabel("Base Capture Events"), 3, 0) updateLayout.addWidget( - QLabel("Buildings destroyed"), 3, 0) - updateLayout.addWidget( - QLabel(str(len(list(debriefing.building_losses)))), 3, 1) - - updateLayout.addWidget(QLabel("Base Capture Events"), 4, 0) - updateLayout.addWidget( - QLabel(str(len(debriefing.base_capture_events))), 4, 1) + QLabel(str(len(debriefing.base_capture_events))), 3, 1) # Clear previous content of the window for i in reversed(range(self.gridLayout.count())):