Fix empty convoys (#1327)

* Hopefully getting rid of empty convoys for good

* changing Dict to dict for type checks
This commit is contained in:
bgreman 2021-06-23 19:48:16 -04:00 committed by GitHub
parent c3b8c48ca2
commit 3274f3ec35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 17 deletions

View File

@ -40,6 +40,7 @@ Saves from 3.x are not compatible with 4.0.
* **[Mission Generation]** Fixed problem with mission load when control point name contained an apostrophe. * **[Mission Generation]** Fixed problem with mission load when control point name contained an apostrophe.
* **[Mission Generation]** Fixed EWR group names so they contribute to Skynet again. * **[Mission Generation]** Fixed EWR group names so they contribute to Skynet again.
* **[Mission Generation]** Fixed duplicate name error when generating convoys and cargo ships when creating manual transfers after loading a game. * **[Mission Generation]** Fixed duplicate name error when generating convoys and cargo ships when creating manual transfers after loading a game.
* **[Mission Generation]** Fixed empty convoys not being disbanded when all units are killed/removed.
* **[UI]** Made non-interactive map elements less obstructive. * **[UI]** Made non-interactive map elements less obstructive.
* **[UI]** Added support for Neutral Dot difficulty label * **[UI]** Added support for Neutral Dot difficulty label
* **[UI]** Clear skies at night no longer described as "Sunny" by the weather widget. * **[UI]** Clear skies at night no longer described as "Sunny" by the weather widget.

View File

@ -6,7 +6,6 @@ from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from functools import singledispatchmethod from functools import singledispatchmethod
from typing import ( from typing import (
Dict,
Generic, Generic,
Iterator, Iterator,
List, List,
@ -72,10 +71,18 @@ class TransferOrder:
player: bool = field(init=False) player: bool = field(init=False)
#: The units being transferred. #: The units being transferred.
units: Dict[GroundUnitType, int] units: dict[GroundUnitType, int]
transport: Optional[Transport] = field(default=None) transport: Optional[Transport] = field(default=None)
def __str__(self) -> str:
"""Returns the text that should be displayed for the transfer."""
count = self.size
origin = self.origin.name
destination = self.destination.name
description = "Transfer" if self.player else "Enemy transfer"
return f"{description} of {count} units from {origin} to {destination}"
def __post_init__(self) -> None: def __post_init__(self) -> None:
self.position = self.origin self.position = self.origin
self.player = self.origin.is_friendly(to_player=True) self.player = self.origin.is_friendly(to_player=True)
@ -91,12 +98,12 @@ class TransferOrder:
def kill_unit(self, unit_type: GroundUnitType) -> None: def kill_unit(self, unit_type: GroundUnitType) -> None:
if unit_type not in self.units or not self.units[unit_type]: if unit_type not in self.units or not self.units[unit_type]:
raise KeyError(f"{self.destination} has no {unit_type} remaining") raise KeyError(f"{self} has no {unit_type} remaining")
self.units[unit_type] -= 1 self.units[unit_type] -= 1
@property @property
def size(self) -> int: def size(self) -> int:
return sum(c for c in self.units.values()) return sum(self.units.values())
def iter_units(self) -> Iterator[GroundUnitType]: def iter_units(self) -> Iterator[GroundUnitType]:
for unit_type, count in self.units.items(): for unit_type, count in self.units.items():
@ -105,7 +112,7 @@ class TransferOrder:
@property @property
def completed(self) -> bool: def completed(self) -> bool:
return self.destination == self.position or not self.units return self.destination == self.position or not self.size
def disband_at(self, location: ControlPoint) -> None: def disband_at(self, location: ControlPoint) -> None:
logging.info(f"Units halting at {location}.") logging.info(f"Units halting at {location}.")
@ -156,7 +163,7 @@ class Airlift(Transport):
self.flight = flight self.flight = flight
@property @property
def units(self) -> Dict[GroundUnitType, int]: def units(self) -> dict[GroundUnitType, int]:
return self.transfer.units return self.transfer.units
@property @property
@ -334,11 +341,11 @@ class MultiGroupTransport(MissionTarget, Transport):
@property @property
def size(self) -> int: def size(self) -> int:
return sum(sum(t.units.values()) for t in self.transfers) return sum(t.size for t in self.transfers)
@property @property
def units(self) -> dict[GroundUnitType, int]: def units(self) -> dict[GroundUnitType, int]:
units: Dict[GroundUnitType, int] = defaultdict(int) units: dict[GroundUnitType, int] = defaultdict(int)
for transfer in self.transfers: for transfer in self.transfers:
for unit_type, count in transfer.units.items(): for unit_type, count in transfer.units.items():
units[unit_type] += count units[unit_type] += count
@ -414,8 +421,8 @@ TransportType = TypeVar("TransportType", bound=MultiGroupTransport)
class TransportMap(Generic[TransportType]): class TransportMap(Generic[TransportType]):
def __init__(self) -> None: def __init__(self) -> None:
# Dict of origin -> destination -> transport. # Dict of origin -> destination -> transport.
self.transports: Dict[ self.transports: dict[
ControlPoint, Dict[ControlPoint, TransportType] ControlPoint, dict[ControlPoint, TransportType]
] = defaultdict(dict) ] = defaultdict(dict)
def create_transport( def create_transport(

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
import datetime import datetime
from typing import Any, Callable, Dict, Iterator, Optional, TypeVar from typing import Any, Callable, Iterator, Optional, TypeVar
from PySide2.QtCore import ( from PySide2.QtCore import (
QAbstractListModel, QAbstractListModel,
@ -51,7 +51,7 @@ class DeletableChildModelManager:
#: The type of model managed by this class. #: The type of model managed by this class.
ModelType = TypeVar("ModelType") ModelType = TypeVar("ModelType")
ModelDict = Dict[DataType, ModelType] ModelDict = dict[DataType, ModelType]
def __init__( def __init__(
self, self,
@ -334,11 +334,7 @@ class TransferModel(QAbstractListModel):
@staticmethod @staticmethod
def text_for_transfer(transfer: TransferOrder) -> str: def text_for_transfer(transfer: TransferOrder) -> str:
"""Returns the text that should be displayed for the transfer.""" """Returns the text that should be displayed for the transfer."""
count = sum(transfer.units.values()) return str(transfer)
origin = transfer.origin.name
destination = transfer.destination.name
description = "Transfer" if transfer.player else "Enemy transfer"
return f"{description} of {count} units from {origin} to {destination}"
@staticmethod @staticmethod
def icon_for_transfer(_transfer: TransferOrder) -> Optional[QIcon]: def icon_for_transfer(_transfer: TransferOrder) -> Optional[QIcon]: