mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Clean up mission result handling.
This commit is contained in:
parent
74291271e3
commit
b728fcc2d6
@ -8,6 +8,7 @@ import threading
|
|||||||
import time
|
import time
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
from pathlib import Path
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
@ -35,6 +36,7 @@ from game.ato.flight import Flight
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
|
from game.sim import MissionSimulation
|
||||||
|
|
||||||
DEBRIEFING_LOG_EXTENSION = "log"
|
DEBRIEFING_LOG_EXTENSION = "log"
|
||||||
|
|
||||||
@ -361,13 +363,14 @@ class PollDebriefingFileThread(threading.Thread):
|
|||||||
regularly for the stopped() condition."""
|
regularly for the stopped() condition."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, callback: Callable[[Debriefing], None], game: Game, unit_map: UnitMap
|
self,
|
||||||
|
callback: Callable[[Debriefing], None],
|
||||||
|
mission_simulation: MissionSimulation,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._stop_event = threading.Event()
|
self._stop_event = threading.Event()
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.game = game
|
self.mission_sim = mission_simulation
|
||||||
self.unit_map = unit_map
|
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
self._stop_event.set()
|
self._stop_event.set()
|
||||||
@ -386,10 +389,9 @@ class PollDebriefingFileThread(threading.Thread):
|
|||||||
os.path.isfile("state.json")
|
os.path.isfile("state.json")
|
||||||
and os.path.getmtime("state.json") > last_modified
|
and os.path.getmtime("state.json") > last_modified
|
||||||
):
|
):
|
||||||
with open("state.json", "r", encoding="utf-8") as json_file:
|
self.callback(
|
||||||
json_data = json.load(json_file)
|
self.mission_sim.debrief_current_state(Path("state.json"))
|
||||||
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
)
|
||||||
self.callback(debriefing)
|
|
||||||
break
|
break
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
logging.exception(
|
logging.exception(
|
||||||
@ -400,8 +402,8 @@ class PollDebriefingFileThread(threading.Thread):
|
|||||||
|
|
||||||
|
|
||||||
def wait_for_debriefing(
|
def wait_for_debriefing(
|
||||||
callback: Callable[[Debriefing], None], game: Game, unit_map: UnitMap
|
callback: Callable[[Debriefing], None], mission_simulation: MissionSimulation
|
||||||
) -> PollDebriefingFileThread:
|
) -> PollDebriefingFileThread:
|
||||||
thread = PollDebriefingFileThread(callback, game, unit_map)
|
thread = PollDebriefingFileThread(callback, mission_simulation)
|
||||||
thread.start()
|
thread.start()
|
||||||
return thread
|
return thread
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
from .event import *
|
|
||||||
from .frontlineattack import *
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from .event import Event
|
|
||||||
|
|
||||||
|
|
||||||
class AirWarEvent(Event):
|
|
||||||
"""Event handler for the air battle"""
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return "AirWar"
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
from .event import Event
|
|
||||||
|
|
||||||
|
|
||||||
class FrontlineAttackEvent(Event):
|
|
||||||
"""
|
|
||||||
An event centered on a FrontLine Conflict.
|
|
||||||
Currently the same as its parent, but here for legacy compatibility as well as to allow for
|
|
||||||
future unique Event handling
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return "Frontline attack"
|
|
||||||
52
game/game.py
52
game/game.py
@ -6,9 +6,9 @@ import math
|
|||||||
from collections import Iterator
|
from collections import Iterator
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, List, Type, Union, cast, TYPE_CHECKING
|
from typing import Any, List, TYPE_CHECKING, Type, Union, cast
|
||||||
|
|
||||||
from dcs.countries import Switzerland, UnitedNationsPeacekeepers, USAFAggressors
|
from dcs.countries import Switzerland, USAFAggressors, UnitedNationsPeacekeepers
|
||||||
from dcs.country import Country
|
from dcs.country import Country
|
||||||
from dcs.mapping import Point
|
from dcs.mapping import Point
|
||||||
from dcs.task import CAP, CAS, PinpointStrike
|
from dcs.task import CAP, CAS, PinpointStrike
|
||||||
@ -19,19 +19,16 @@ from game.models.game_stats import GameStats
|
|||||||
from game.plugins import LuaPluginManager
|
from game.plugins import LuaPluginManager
|
||||||
from gen import naming
|
from gen import naming
|
||||||
from gen.flights.closestairfields import ObjectiveDistanceCache
|
from gen.flights.closestairfields import ObjectiveDistanceCache
|
||||||
from .ato.flighttype import FlightType
|
|
||||||
from gen.ground_forces.ai_ground_planner import GroundPlanner
|
from gen.ground_forces.ai_ground_planner import GroundPlanner
|
||||||
from . import persistency
|
from . import persistency
|
||||||
|
from .ato.flighttype import FlightType
|
||||||
from .campaignloader import CampaignAirWingConfig
|
from .campaignloader import CampaignAirWingConfig
|
||||||
from .coalition import Coalition
|
from .coalition import Coalition
|
||||||
from .debriefing import Debriefing
|
|
||||||
from .event.event import Event
|
|
||||||
from .event.frontlineattack import FrontlineAttackEvent
|
|
||||||
from .factions.faction import Faction
|
from .factions.faction import Faction
|
||||||
from .infos.information import Information
|
from .infos.information import Information
|
||||||
from .profiling import logged_duration
|
from .profiling import logged_duration
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .theater import ConflictTheater, ControlPoint
|
from .theater import ConflictTheater
|
||||||
from .theater.bullseye import Bullseye
|
from .theater.bullseye import Bullseye
|
||||||
from .theater.transitnetwork import TransitNetwork, TransitNetworkBuilder
|
from .theater.transitnetwork import TransitNetwork, TransitNetworkBuilder
|
||||||
from .weather import Conditions, TimeOfDay
|
from .weather import Conditions, TimeOfDay
|
||||||
@ -44,7 +41,6 @@ if TYPE_CHECKING:
|
|||||||
from .navmesh import NavMesh
|
from .navmesh import NavMesh
|
||||||
from .squadrons import AirWing
|
from .squadrons import AirWing
|
||||||
from .threatzones import ThreatZones
|
from .threatzones import ThreatZones
|
||||||
from .unitmap import UnitMap
|
|
||||||
|
|
||||||
COMMISION_UNIT_VARIETY = 4
|
COMMISION_UNIT_VARIETY = 4
|
||||||
COMMISION_LIMITS_SCALE = 1.5
|
COMMISION_LIMITS_SCALE = 1.5
|
||||||
@ -99,7 +95,6 @@ class Game:
|
|||||||
enemy_budget: float,
|
enemy_budget: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.events: List[Event] = []
|
|
||||||
self.theater = theater
|
self.theater = theater
|
||||||
self.turn = 0
|
self.turn = 0
|
||||||
# NB: This is the *start* date. It is never updated.
|
# NB: This is the *start* date. It is never updated.
|
||||||
@ -183,20 +178,6 @@ class Game:
|
|||||||
def bullseye_for(self, player: bool) -> Bullseye:
|
def bullseye_for(self, player: bool) -> Bullseye:
|
||||||
return self.coalition_for(player).bullseye
|
return self.coalition_for(player).bullseye
|
||||||
|
|
||||||
def _generate_player_event(
|
|
||||||
self, event_class: Type[Event], player_cp: ControlPoint, enemy_cp: ControlPoint
|
|
||||||
) -> None:
|
|
||||||
self.events.append(
|
|
||||||
event_class(
|
|
||||||
self,
|
|
||||||
player_cp,
|
|
||||||
enemy_cp,
|
|
||||||
enemy_cp.position,
|
|
||||||
self.blue.faction.name,
|
|
||||||
self.red.faction.name,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def neutral_country(self) -> Type[Country]:
|
def neutral_country(self) -> Type[Country]:
|
||||||
"""Return the best fitting country that can be used as neutral faction in the generated mission"""
|
"""Return the best fitting country that can be used as neutral faction in the generated mission"""
|
||||||
@ -208,14 +189,6 @@ class Game:
|
|||||||
else:
|
else:
|
||||||
return USAFAggressors
|
return USAFAggressors
|
||||||
|
|
||||||
def _generate_events(self) -> None:
|
|
||||||
for front_line in self.theater.conflicts():
|
|
||||||
self._generate_player_event(
|
|
||||||
FrontlineAttackEvent,
|
|
||||||
front_line.blue_cp,
|
|
||||||
front_line.red_cp,
|
|
||||||
)
|
|
||||||
|
|
||||||
def coalition_for(self, player: bool) -> Coalition:
|
def coalition_for(self, player: bool) -> Coalition:
|
||||||
if player:
|
if player:
|
||||||
return self.blue
|
return self.blue
|
||||||
@ -224,21 +197,6 @@ class Game:
|
|||||||
def adjust_budget(self, amount: float, player: bool) -> None:
|
def adjust_budget(self, amount: float, player: bool) -> None:
|
||||||
self.coalition_for(player).adjust_budget(amount)
|
self.coalition_for(player).adjust_budget(amount)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def initiate_event(event: Event) -> UnitMap:
|
|
||||||
# assert event in self.events
|
|
||||||
logging.info("Generating {} (regular)".format(event))
|
|
||||||
return event.generate()
|
|
||||||
|
|
||||||
def finish_event(self, event: Event, debriefing: Debriefing) -> None:
|
|
||||||
logging.info("Finishing event {}".format(event))
|
|
||||||
event.commit(debriefing)
|
|
||||||
|
|
||||||
if event in self.events:
|
|
||||||
self.events.remove(event)
|
|
||||||
else:
|
|
||||||
logging.info("finish_event: event not in the events!")
|
|
||||||
|
|
||||||
def on_load(self, game_still_initializing: bool = False) -> None:
|
def on_load(self, game_still_initializing: bool = False) -> None:
|
||||||
if not hasattr(self, "name_generator"):
|
if not hasattr(self, "name_generator"):
|
||||||
self.name_generator = naming.namegen
|
self.name_generator = naming.namegen
|
||||||
@ -378,8 +336,6 @@ class Game:
|
|||||||
for_red: True if opfor should be re-initialized.
|
for_red: True if opfor should be re-initialized.
|
||||||
for_blue: True if the player coalition should be re-initialized.
|
for_blue: True if the player coalition should be re-initialized.
|
||||||
"""
|
"""
|
||||||
self.events = []
|
|
||||||
self._generate_events()
|
|
||||||
self.set_bullseye()
|
self.set_bullseye()
|
||||||
|
|
||||||
# Update statistics
|
# Update statistics
|
||||||
|
|||||||
1
game/sim/__init__.py
Normal file
1
game/sim/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .missionsimulation import MissionSimulation
|
||||||
@ -1,18 +1,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import List, TYPE_CHECKING, Type
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from dcs.mapping import Point
|
|
||||||
from dcs.task import Task
|
|
||||||
|
|
||||||
from game import persistency
|
|
||||||
from game.debriefing import Debriefing
|
from game.debriefing import Debriefing
|
||||||
from game.theater import ControlPoint
|
from game.theater import ControlPoint
|
||||||
from gen.ground_forces.combat_stance import CombatStance
|
from gen.ground_forces.combat_stance import CombatStance
|
||||||
from ..ato.airtaaskingorder import AirTaskingOrder
|
from ..ato.airtaaskingorder import AirTaskingOrder
|
||||||
from ..missiongenerator import MissionGenerator
|
|
||||||
from ..unitmap import UnitMap
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..game import Game
|
from ..game import Game
|
||||||
@ -23,44 +17,24 @@ DEFEAT_INFLUENCE = 0.3
|
|||||||
STRONG_DEFEAT_INFLUENCE = 0.5
|
STRONG_DEFEAT_INFLUENCE = 0.5
|
||||||
|
|
||||||
|
|
||||||
class Event:
|
class MissionResultsProcessor:
|
||||||
silent = False
|
def __init__(self, game: Game) -> None:
|
||||||
informational = False
|
|
||||||
|
|
||||||
game = None # type: Game
|
|
||||||
location = None # type: Point
|
|
||||||
from_cp = None # type: ControlPoint
|
|
||||||
to_cp = None # type: ControlPoint
|
|
||||||
difficulty = 1 # type: int
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
game: Game,
|
|
||||||
from_cp: ControlPoint,
|
|
||||||
target_cp: ControlPoint,
|
|
||||||
location: Point,
|
|
||||||
attacker_name: str,
|
|
||||||
defender_name: str,
|
|
||||||
) -> None:
|
|
||||||
self.game = game
|
self.game = game
|
||||||
self.from_cp = from_cp
|
|
||||||
self.to_cp = target_cp
|
|
||||||
self.location = location
|
|
||||||
self.attacker_name = attacker_name
|
|
||||||
self.defender_name = defender_name
|
|
||||||
|
|
||||||
@property
|
def commit(self, debriefing: Debriefing) -> None:
|
||||||
def is_player_attacking(self) -> bool:
|
logging.info("Committing mission results")
|
||||||
return self.attacker_name == self.game.blue.faction.name
|
self.commit_air_losses(debriefing)
|
||||||
|
self.commit_pilot_experience()
|
||||||
@property
|
self.commit_front_line_losses(debriefing)
|
||||||
def tasks(self) -> List[Type[Task]]:
|
self.commit_convoy_losses(debriefing)
|
||||||
return []
|
self.commit_cargo_ship_losses(debriefing)
|
||||||
|
self.commit_airlift_losses(debriefing)
|
||||||
def generate(self) -> UnitMap:
|
self.commit_ground_object_losses(debriefing)
|
||||||
return MissionGenerator(self.game).generate_miz(
|
self.commit_building_losses(debriefing)
|
||||||
persistency.mission_path_for("liberation_nextturn.miz")
|
self.commit_damaged_runways(debriefing)
|
||||||
)
|
self.commit_captures(debriefing)
|
||||||
|
self.commit_front_line_battle_impact(debriefing)
|
||||||
|
self.record_carcasses(debriefing)
|
||||||
|
|
||||||
def commit_air_losses(self, debriefing: Debriefing) -> None:
|
def commit_air_losses(self, debriefing: Debriefing) -> None:
|
||||||
for loss in debriefing.air_losses.losses:
|
for loss in debriefing.air_losses.losses:
|
||||||
@ -200,27 +174,11 @@ class Event:
|
|||||||
except Exception:
|
except Exception:
|
||||||
logging.exception(f"Could not process base capture {captured}")
|
logging.exception(f"Could not process base capture {captured}")
|
||||||
|
|
||||||
def commit(self, debriefing: Debriefing) -> None:
|
def record_carcasses(self, debriefing: Debriefing) -> None:
|
||||||
logging.info("Committing mission results")
|
|
||||||
|
|
||||||
self.commit_air_losses(debriefing)
|
|
||||||
self.commit_pilot_experience()
|
|
||||||
self.commit_front_line_losses(debriefing)
|
|
||||||
self.commit_convoy_losses(debriefing)
|
|
||||||
self.commit_cargo_ship_losses(debriefing)
|
|
||||||
self.commit_airlift_losses(debriefing)
|
|
||||||
self.commit_ground_object_losses(debriefing)
|
|
||||||
self.commit_building_losses(debriefing)
|
|
||||||
self.commit_damaged_runways(debriefing)
|
|
||||||
self.commit_captures(debriefing)
|
|
||||||
|
|
||||||
# Destroyed units carcass
|
|
||||||
# -------------------------
|
|
||||||
for destroyed_unit in debriefing.state_data.destroyed_statics:
|
for destroyed_unit in debriefing.state_data.destroyed_statics:
|
||||||
self.game.add_destroyed_units(destroyed_unit)
|
self.game.add_destroyed_units(destroyed_unit)
|
||||||
|
|
||||||
# -----------------------------------
|
def commit_front_line_battle_impact(self, debriefing: Debriefing) -> None:
|
||||||
# Compute damage to bases
|
|
||||||
for cp in self.game.theater.player_points():
|
for cp in self.game.theater.player_points():
|
||||||
enemy_cps = [e for e in cp.connected_points if not e.captured]
|
enemy_cps = [e for e in cp.connected_points if not e.captured]
|
||||||
for enemy_cp in enemy_cps:
|
for enemy_cp in enemy_cps:
|
||||||
49
game/sim/missionsimulation.py
Normal file
49
game/sim/missionsimulation.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
from game.debriefing import Debriefing
|
||||||
|
from game.missiongenerator import MissionGenerator
|
||||||
|
from game.sim.missionresultsprocessor import MissionResultsProcessor
|
||||||
|
from game.unitmap import UnitMap
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from game import Game
|
||||||
|
|
||||||
|
|
||||||
|
class MissionSimulation:
|
||||||
|
def __init__(self, game: Game) -> None:
|
||||||
|
self.game = game
|
||||||
|
self.unit_map: Optional[UnitMap] = None
|
||||||
|
|
||||||
|
def generate_miz(self, output: Path) -> None:
|
||||||
|
self.unit_map = MissionGenerator(self.game).generate_miz(output)
|
||||||
|
|
||||||
|
def debrief_current_state(
|
||||||
|
self, state_path: Path, force_end: bool = False
|
||||||
|
) -> Debriefing:
|
||||||
|
if self.unit_map is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Simulation has no unit map. Results processing began before a mission "
|
||||||
|
"was generated."
|
||||||
|
)
|
||||||
|
|
||||||
|
with state_path.open("r", encoding="utf-8") as state_file:
|
||||||
|
data = json.load(state_file)
|
||||||
|
if force_end:
|
||||||
|
data["mission_ended"] = True
|
||||||
|
return Debriefing(data, self.game, self.unit_map)
|
||||||
|
|
||||||
|
def process_results(self, debriefing: Debriefing) -> None:
|
||||||
|
if self.unit_map is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Simulation has no unit map. Results processing began before a mission "
|
||||||
|
"was generated."
|
||||||
|
)
|
||||||
|
|
||||||
|
MissionResultsProcessor(self.game).commit(debriefing)
|
||||||
|
|
||||||
|
def finish(self) -> None:
|
||||||
|
self.unit_map = None
|
||||||
@ -10,11 +10,11 @@ from PySide2.QtWidgets import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
from game import Game
|
from game import Game, persistency
|
||||||
from game.event.airwar import AirWarEvent
|
|
||||||
from game.profiling import logged_duration
|
|
||||||
from game.utils import meters
|
|
||||||
from game.ato.package import Package
|
from game.ato.package import Package
|
||||||
|
from game.profiling import logged_duration
|
||||||
|
from game.sim import MissionSimulation
|
||||||
|
from game.utils import meters
|
||||||
from gen.flights.traveltime import TotEstimator
|
from gen.flights.traveltime import TotEstimator
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
||||||
@ -276,18 +276,11 @@ class QTopPanel(QFrame):
|
|||||||
if negative_starts:
|
if negative_starts:
|
||||||
if not self.confirm_negative_start_time(negative_starts):
|
if not self.confirm_negative_start_time(negative_starts):
|
||||||
return
|
return
|
||||||
closest_cps = self.game.theater.closest_opposing_control_points()
|
|
||||||
game_event = AirWarEvent(
|
|
||||||
self.game,
|
|
||||||
closest_cps[0],
|
|
||||||
closest_cps[1],
|
|
||||||
self.game.theater.controlpoints[0].position,
|
|
||||||
self.game.blue.faction.name,
|
|
||||||
self.game.red.faction.name,
|
|
||||||
)
|
|
||||||
|
|
||||||
unit_map = self.game.initiate_event(game_event)
|
sim = MissionSimulation(self.game)
|
||||||
waiting = QWaitingForMissionResultWindow(game_event, self.game, unit_map, self)
|
sim.generate_miz(persistency.mission_path_for("liberation_nextturn.miz"))
|
||||||
|
|
||||||
|
waiting = QWaitingForMissionResultWindow(self.game, sim, self)
|
||||||
waiting.exec_()
|
waiting.exec_()
|
||||||
|
|
||||||
def budget_update(self, game: Game):
|
def budget_update(self, game: Game):
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from typing import Optional
|
|||||||
from PySide2.QtCore import QObject, Signal
|
from PySide2.QtCore import QObject, Signal
|
||||||
|
|
||||||
from game import Game
|
from game import Game
|
||||||
from game.event import Debriefing
|
from game.debriefing import Debriefing
|
||||||
|
|
||||||
|
|
||||||
class GameUpdateSignal(QObject):
|
class GameUpdateSignal(QObject):
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Sized, Optional
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from PySide2 import QtCore
|
from PySide2 import QtCore
|
||||||
from PySide2.QtCore import QObject, Qt, Signal
|
from PySide2.QtCore import QObject, Signal
|
||||||
from PySide2.QtGui import QIcon, QMovie, QPixmap, QWindow
|
from PySide2.QtGui import QIcon, QMovie, QPixmap
|
||||||
from PySide2.QtWidgets import (
|
from PySide2.QtWidgets import (
|
||||||
QDialog,
|
QDialog,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
@ -14,18 +15,17 @@ from PySide2.QtWidgets import (
|
|||||||
QGroupBox,
|
QGroupBox,
|
||||||
QHBoxLayout,
|
QHBoxLayout,
|
||||||
QLabel,
|
QLabel,
|
||||||
QMessageBox,
|
|
||||||
QPushButton,
|
QPushButton,
|
||||||
QTextBrowser,
|
QTextBrowser,
|
||||||
QWidget,
|
QWidget,
|
||||||
)
|
)
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
|
|
||||||
|
from game import Game
|
||||||
from game.debriefing import Debriefing, wait_for_debriefing
|
from game.debriefing import Debriefing, wait_for_debriefing
|
||||||
from game.game import Event, Game, logging
|
|
||||||
from game.persistency import base_path
|
from game.persistency import base_path
|
||||||
from game.profiling import logged_duration
|
from game.profiling import logged_duration
|
||||||
from game.unitmap import UnitMap
|
from game.sim import MissionSimulation
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
|
|
||||||
|
|
||||||
@ -52,16 +52,14 @@ DebriefingFileWrittenSignal()
|
|||||||
class QWaitingForMissionResultWindow(QDialog):
|
class QWaitingForMissionResultWindow(QDialog):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
gameEvent: Event,
|
|
||||||
game: Game,
|
game: Game,
|
||||||
unit_map: UnitMap,
|
mission_simulation: MissionSimulation,
|
||||||
parent: Optional[QWidget] = None,
|
parent: Optional[QWidget] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
super(QWaitingForMissionResultWindow, self).__init__(parent=parent)
|
super(QWaitingForMissionResultWindow, self).__init__(parent=parent)
|
||||||
self.setWindowModality(QtCore.Qt.WindowModal)
|
self.setWindowModality(QtCore.Qt.WindowModal)
|
||||||
self.gameEvent = gameEvent
|
|
||||||
self.game = game
|
self.game = game
|
||||||
self.unit_map = unit_map
|
self.mission_sim = mission_simulation
|
||||||
self.setWindowTitle("Waiting for mission completion.")
|
self.setWindowTitle("Waiting for mission completion.")
|
||||||
self.setWindowIcon(QIcon("./resources/icon.png"))
|
self.setWindowIcon(QIcon("./resources/icon.png"))
|
||||||
self.setMinimumHeight(570)
|
self.setMinimumHeight(570)
|
||||||
@ -71,9 +69,7 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
self.updateLayout
|
self.updateLayout
|
||||||
)
|
)
|
||||||
self.wait_thread = wait_for_debriefing(
|
self.wait_thread = wait_for_debriefing(
|
||||||
lambda debriefing: self.on_debriefing_update(debriefing),
|
lambda debriefing: self.on_debriefing_update(debriefing), self.mission_sim
|
||||||
self.game,
|
|
||||||
self.unit_map,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def initUi(self):
|
def initUi(self):
|
||||||
@ -209,12 +205,12 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Got an error while sending debriefing")
|
logging.exception("Got an error while sending debriefing")
|
||||||
self.wait_thread = wait_for_debriefing(
|
self.wait_thread = wait_for_debriefing(
|
||||||
lambda d: self.on_debriefing_update(d), self.game, self.unit_map
|
lambda d: self.on_debriefing_update(d), self.mission_sim
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_debriefing(self):
|
def process_debriefing(self):
|
||||||
with logged_duration("Turn processing"):
|
with logged_duration("Turn processing"):
|
||||||
self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing)
|
self.mission_sim.process_results(self.debriefing)
|
||||||
self.game.pass_turn()
|
self.game.pass_turn()
|
||||||
|
|
||||||
GameUpdateSignal.get_instance().sendDebriefing(self.debriefing)
|
GameUpdateSignal.get_instance().sendDebriefing(self.debriefing)
|
||||||
@ -233,20 +229,7 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
file = QFileDialog.getOpenFileName(
|
file = QFileDialog.getOpenFileName(
|
||||||
self, "Select game file to open", filter="json(*.json)", dir="."
|
self, "Select game file to open", filter="json(*.json)", dir="."
|
||||||
)
|
)
|
||||||
print(file)
|
logging.debug("Processing manually submitted %s", file[0])
|
||||||
try:
|
self.on_debriefing_update(
|
||||||
with open(file[0], "r", encoding="utf-8") as json_file:
|
self.mission_sim.debrief_current_state(Path(file[0], force_end=True))
|
||||||
json_data = json.load(json_file)
|
)
|
||||||
json_data["mission_ended"] = True
|
|
||||||
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
|
||||||
self.on_debriefing_update(debriefing)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(e)
|
|
||||||
msg = QMessageBox()
|
|
||||||
msg.setIcon(QMessageBox.Information)
|
|
||||||
msg.setText("Invalid file : " + file[0])
|
|
||||||
msg.setWindowTitle("Invalid file.")
|
|
||||||
msg.setStandardButtons(QMessageBox.Ok)
|
|
||||||
msg.setWindowFlags(Qt.WindowStaysOnTopHint)
|
|
||||||
msg.exec_()
|
|
||||||
return
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user