Add debug command to dump aircraft priorities.

https://github.com/dcs-liberation/dcs_liberation/issues/2809
This commit is contained in:
Dan Albert 2023-04-26 20:03:07 -07:00 committed by Raffson
parent 016a9b5762
commit 9ebbe11d83
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
8 changed files with 69 additions and 16 deletions

View File

@ -183,7 +183,7 @@ class Campaign:
@classmethod
def iter_campaign_defs(cls) -> Iterator[Path]:
yield from cls.iter_campaigns_in_dir(
Path(persistency.base_path()) / "Retribution/Campaigns"
persistency.base_path() / "Retribution/Campaigns"
)
yield from cls.iter_campaigns_in_dir(Path("resources/campaigns"))

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import logging
from collections import defaultdict
from dataclasses import dataclass
from functools import cached_property
from functools import cache, cached_property
from pathlib import Path
from typing import Any, ClassVar, Dict, Iterator, Optional, TYPE_CHECKING, Type
@ -355,6 +355,15 @@ class AircraftType(UnitType[Type[FlyingType]]):
cls._load_all()
yield from cls._by_name.values()
@classmethod
@cache
def priority_list_for_task(cls, task: FlightType) -> list[AircraftType]:
capable = []
for aircraft in cls.iter_all():
if aircraft.capable_of(task):
capable.append(aircraft)
return list(reversed(sorted(capable, key=lambda a: a.task_priority(task))))
@staticmethod
def each_dcs_type() -> Iterator[Type[FlyingType]]:
yield from helicopter_map.values()

View File

@ -31,7 +31,7 @@ class FactionLoader:
@classmethod
def load_factions(cls: Type[FactionLoader]) -> Dict[str, Faction]:
user_faction_path = Path(persistency.base_path()) / "Retribution/Factions"
user_faction_path = persistency.base_path() / "Retribution/Factions"
files = cls.find_faction_files_in(
FACTION_DIRECTORY
) + cls.find_faction_files_in(user_faction_path)

View File

@ -63,7 +63,7 @@ class LayoutLoader:
"""This will load all pre-loaded layouts from a pickle file.
If pickle can not be loaded it will import and dump the layouts"""
# We use a pickle for performance reasons. Importing takes many seconds
file = Path(persistency.base_path()) / LAYOUT_DUMP
file = persistency.base_path() / LAYOUT_DUMP
if file.is_file():
# Load from pickle if existing
with file.open("rb") as f:
@ -106,7 +106,7 @@ class LayoutLoader:
self._dump_templates()
def _dump_templates(self) -> None:
file = Path(persistency.base_path()) / LAYOUT_DUMP
file = persistency.base_path() / LAYOUT_DUMP
dump = (VERSION, self._layouts)
with file.open("wb") as fdata:
pickle.dump(dump, fdata)

View File

@ -21,18 +21,18 @@ def setup(user_folder: str) -> None:
save_dir().mkdir(parents=True)
def base_path() -> str:
def base_path() -> Path:
global _dcs_saved_game_folder
assert _dcs_saved_game_folder
return _dcs_saved_game_folder
return Path(_dcs_saved_game_folder)
def settings_dir() -> Path:
return Path(base_path()) / "Retribution" / "Settings"
return base_path() / "Retribution" / "Settings"
def save_dir() -> Path:
return Path(base_path()) / "Retribution" / "Saves"
return base_path() / "Retribution" / "Saves"
def _temporary_save_file() -> str:
@ -44,7 +44,7 @@ def _autosave_path() -> str:
def mission_path_for(name: str) -> Path:
return Path(base_path()) / "Missions" / name
return base_path() / "Missions" / name
def load_game(path: str) -> Optional[Game]:

View File

@ -22,7 +22,7 @@ class SquadronDefLoader:
def squadron_directories() -> Iterator[Path]:
from game import persistency
yield Path(persistency.base_path()) / "Retribution/Squadrons"
yield persistency.base_path() / "Retribution/Squadrons"
yield Path("resources/squadrons")
def load(self) -> dict[AircraftType, list[SquadronDef]]:

View File

@ -1,11 +1,13 @@
import argparse
import logging
import ntpath
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import Optional
import yaml
from PySide2 import QtWidgets
from PySide2.QtCore import Qt
from PySide2.QtGui import QPixmap
@ -13,10 +15,12 @@ from PySide2.QtWidgets import QApplication, QCheckBox, QSplashScreen
from dcs.payloads import PayloadDirectories
from game import Game, VERSION, logging_config, persistency
from game.ato import FlightType
from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET
from game.data.weapons import Pylon, Weapon, WeaponGroup
from game.dcs.aircrafttype import AircraftType
from game.factions import FACTIONS
from game.persistency import base_path
from game.profiling import logged_duration
from game.server import EventStream, Server
from game.settings import Settings
@ -69,12 +73,12 @@ def inject_mod_payloads(mod_path: Path) -> None:
PayloadDirectories.set_preferred(payloads)
def on_game_load(game: Game | None) -> None:
def on_game_load(game: Optional[Game]) -> None:
EventStream.drain()
EventStream.put_nowait(GameUpdateEvents().game_loaded(game))
def run_ui(game: Game | None, ui_flags: UiFlags) -> None:
def run_ui(game: Optional[Game], ui_flags: UiFlags) -> None:
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" # Potential fix for 4K screens
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
@ -107,7 +111,7 @@ def run_ui(game: Game | None, ui_flags: UiFlags) -> None:
)
)
inject_custom_payloads(Path(persistency.base_path()))
inject_custom_payloads(persistency.base_path())
# Splash screen setup
pixmap = QPixmap("./resources/ui/splash_screen.png")
@ -260,6 +264,8 @@ def parse_args() -> argparse.Namespace:
lint_weapons = subparsers.add_parser("lint-weapons")
lint_weapons.add_argument("aircraft", help="Name of the aircraft variant to lint.")
subparsers.add_parser("dump-task-priorities")
return parser.parse_args()
@ -289,7 +295,7 @@ def create_game(
# Without this, it is not possible to use next turn (or anything that needs to check
# for loadouts) without saving the generated campaign and reloading it the normal
# way.
inject_custom_payloads(Path(persistency.base_path()))
inject_custom_payloads(persistency.base_path())
campaign = Campaign.from_file(campaign_path)
theater = campaign.load_theater(advanced_iads)
generator = GameGenerator(
@ -364,6 +370,41 @@ def lint_weapon_data_for_aircraft(aircraft: AircraftType) -> None:
logging.warning(f'{weapon.clsid} "{weapon.name}" has no weapon data')
def fix_pycharm_debugger_if_needed() -> None:
"""Applies workaround for a pycharm debugger bug.
https://youtrack.jetbrains.com/issue/PY-53232/Debugger-doesnt-work-when-pyproj-is-imported
"""
# sys.gettrace() will return something whenever *some* debugger is being used. The
# pdb module will be loaded if that debugger is the built-in python debugger.
if sys.gettrace() is not None and "pdb" not in sys.modules:
logging.debug(
"Applying workaround for https://youtrack.jetbrains.com/issue/PY-53232/Debugger-doesnt-work-when-pyproj-is-imported"
)
ntpath.sep = "\\"
def dump_task_priorities() -> None:
first_start = liberation_install.init()
if first_start:
sys.exit(
"Cannot dump task priorities without configuring DCS Liberation. Start the"
"UI for the first run configuration."
)
data: dict[str, dict[str, int]] = {}
for task in FlightType:
data[task.value] = {
a.name: a.task_priority(task)
for a in AircraftType.priority_list_for_task(task)
}
debug_path = base_path() / "Debug" / "priorities.yaml"
debug_path.parent.mkdir(parents=True, exist_ok=True)
with debug_path.open("w", encoding="utf-8") as output:
yaml.dump(data, output, sort_keys=False, allow_unicode=True)
def main():
logging_config.init_logging(VERSION)
@ -401,6 +442,9 @@ def main():
if args.subcommand == "lint-weapons":
lint_weapon_data_for_aircraft(AircraftType.named(args.aircraft))
return
if args.subcommand == "dump-task-priorities":
dump_task_priorities()
return
with Server().run_in_thread():
run_ui(game, UiFlags(args.dev, args.show_sim_speed_controls))

View File

@ -122,7 +122,7 @@ def main() -> None:
"the first run configuration."
)
inject_custom_payloads(Path(persistency.base_path()))
inject_custom_payloads(persistency.base_path())
if args.aircraft_id is None:
show_all_aircraft(args.task)