From e471d50d939f445bd08f25dc2a1a5756f7964eb3 Mon Sep 17 00:00:00 2001 From: Magnus Wolffelt Date: Thu, 19 Aug 2021 12:24:37 +0200 Subject: [PATCH] Add A-10C presets support, with tests --- dcs/a10c_presets.py | 88 ++++++++++++++++++++++++++++++++++++++ dcs/mission.py | 23 ++++++++++ tests/test_a10c_presets.py | 29 +++++++++++++ tests/test_mission.py | 22 ++++++++++ 4 files changed, 162 insertions(+) create mode 100644 dcs/a10c_presets.py create mode 100644 tests/test_a10c_presets.py diff --git a/dcs/a10c_presets.py b/dcs/a10c_presets.py new file mode 100644 index 00000000..ef9d7771 --- /dev/null +++ b/dcs/a10c_presets.py @@ -0,0 +1,88 @@ +import dcs.lua as lua + + +class A10CPresets: + def __init__(self): + self.presets: dict[int, int] = { + 1: 305000000, + 2: 264000000, + 3: 265000000, + 4: 256000000, + 5: 254000000, + 6: 250000000, + 7: 270000000, + 8: 257000000, + 9: 255000000, + 10: 262000000, + 11: 259000000, + 12: 268000000, + 13: 269000000, + 14: 260000000, + 15: 263000000, + 16: 261000000, + 17: 267000000, + 18: 251000000, + 19: 253000000, + 20: 266000000, + } + + def load_dict(self, data): + presets = data.get("settings", {}).get("presets", {}) + for chan, freq in presets.items(): + self.presets[chan] = freq + + def set_preset(self, channel: int, frequency: float): + freq_as_int = round(frequency * 10 ** 6) + self.presets[channel] = freq_as_int + + def get_preset(self, channel: int) -> float: + frequency = self.presets[channel] + # TODO: Check if floating point precision is a problem + freq_as_float = frequency / (10 ** 6) + return freq_as_float + + def __str__(self): + d = { + # TODO: dials if needed? + "presets": self.presets, + } + return lua.dumps(d, "settings", 1) + + +# Example data from UHF_RADIO/SETTINGS.lua in a miz file: + +# -- These values overwrites the default settings for the A-10C, including hotstarts. +# -- To enable the server wide dials settings, remove the -- +# settings= +# { +# --["dials"]= +# { +# ["mode_dial"]=0, -- 0=OFF, 1=MAIN, 2=BOTH, 3=ADF +# ["manual_frequency"]=305000000, -- Overwrites the value set in the ME. Default=251000000 +# ["selection_dial"]=0, -- 1=MNL, 2=PRESET, 3=GRD +# ["channel_dial"]=0, -- See the presets below. 0=preset 1, 1=preset 2, etc +# }, +# ["presets"]= +# { +# [1]=305000000, +# [2]=264000000, +# [3]=265000000, +# [4]=256000000, +# [5]=254000000, +# [6]=250000000, +# [7]=270000000, +# [8]=257000000, +# [9]=255000000, +# [10]=262000000, +# [11]=259000000, +# [12]=268000000, +# [13]=269000000, +# [14]=260000000, +# [15]=263000000, +# [16]=261000000, +# [17]=267000000, +# [18]=251000000, +# [19]=253000000, +# [20]=266000000, +# }, +# } diff --git a/dcs/mission.py b/dcs/mission.py index 37d44820..af97dc4d 100644 --- a/dcs/mission.py +++ b/dcs/mission.py @@ -2,6 +2,7 @@ The mission module is the entry point to all pydcs functions. """ import copy + import os import sys import tempfile @@ -41,6 +42,7 @@ from dcs.helicopters import HelicopterType from dcs.planes import PlaneType from dcs.status_message import StatusMessage, MessageType, MessageSeverity +from dcs.a10c_presets import A10CPresets class StartType(Enum): @@ -129,6 +131,7 @@ def __init__(self, terrain: Optional[Terrain] = None) -> None: self.init_script = None self.options = Options() self.warehouses = Warehouses(self.terrain) + self.a10c_presets = None self.goals = Goals() blue = Coalition("blue") blue.add_country(countries.Australia()) @@ -254,6 +257,11 @@ def loaddict(fname: str, mizfile: zipfile.ZipFile, reserved_files: List[str]) -> mapresource_dict = loaddict('l10n/DEFAULT/mapResource', miz, reserved_files) self.map_resource.load_from_dict(mapresource_dict, miz) + if 'UHF_RADIO/SETTINGS.lua' in miz.namelist(): + a10c_presets_dict = loaddict('UHF_RADIO/SETTINGS.lua', miz, reserved_files) + self.a10c_presets = A10CPresets() + self.a10c_presets.load_dict(a10c_presets_dict) + self.map_resource.load_binary_files(miz, reserved_files) imp_mission = mission_dict["mission"] @@ -461,6 +469,16 @@ def add_picture_blue(self, filepath: str) -> ResourceKey: self.pictureFileNameB.append(reskey) return reskey + def set_10c_preset(self, channel: int, frequency: float): + if self.a10c_presets is None: + self.a10c_presets = A10CPresets() + self.a10c_presets.set_preset(channel, frequency) + + def get_10c_preset(self, channel: int) -> float: + if self.a10c_presets: + return self.a10c_presets.get_preset(channel) + return None + def next_group_id(self): """Get the next free group id @@ -1923,6 +1941,7 @@ def save(self, filename=None): options = str(self.options) warehouses = str(self.warehouses) mission = str(self) + a10c_presets = str(self.a10c_presets) if self.a10c_presets else None with zipfile.ZipFile(filename, 'w', compression=zipfile.ZIP_DEFLATED) as zipf: # options @@ -1931,6 +1950,10 @@ def save(self, filename=None): # warehouses zipf.writestr('warehouses', warehouses) + # a10c presets + if a10c_presets: + zipf.writestr('UHF_RADIO/SETTINGS.lua', a10c_presets) + # translation files dicttext = lua.dumps(self.translation.dict('DEFAULT'), "dictionary", 1) zipf.writestr('l10n/DEFAULT/dictionary', dicttext) diff --git a/tests/test_a10c_presets.py b/tests/test_a10c_presets.py new file mode 100644 index 00000000..02b0c549 --- /dev/null +++ b/tests/test_a10c_presets.py @@ -0,0 +1,29 @@ +import unittest + +from dcs.a10c_presets import A10CPresets + + +class A10CPresetTests(unittest.TestCase): + def test_set_preset(self) -> None: + a10c_presets = A10CPresets() + + self.assertEqual(a10c_presets.presets[1], 305000000) + self.assertEqual(a10c_presets.presets[20], 266000000) + + a10c_presets.set_preset(1, 306.55) + self.assertEqual(a10c_presets.presets[1], 306550000) + + a10c_presets.set_preset(20, 256.10) + self.assertEqual(a10c_presets.presets[20], 256100000) + + def test_get_preset(self) -> None: + a10c_presets = A10CPresets() + + self.assertEqual(a10c_presets.get_preset(1), 305.0) + + a10c_presets.set_preset(1, 306.55) + self.assertEqual(a10c_presets.get_preset(1), 306.55) + + a10c_presets.set_preset(20, 256.10) + self.assertEqual(a10c_presets.get_preset(20), 256.10) + diff --git a/tests/test_mission.py b/tests/test_mission.py index 169b92d5..8139e08f 100644 --- a/tests/test_mission.py +++ b/tests/test_mission.py @@ -734,3 +734,25 @@ def test_mission_save_pictureFileName(self): self.assertEqual(m2.pictureFileNameB[0], reskey_b.key) self.assertEqual(len(m2.pictureFileNameR), 1) self.assertEqual(m2.pictureFileNameR[0], reskey_r.key) + + def test_set_10c_presets(self): + m = dcs.mission.Mission() + m.load_file('tests/loadtest.miz') + self.assertIsNone(m.a10c_presets) + + m.set_10c_preset(1, 251.0) + m.set_10c_preset(2, 252.0) + m.set_10c_preset(20, 253.0) + + save_path = os.path.join('missions', 'a10c_presets_loadtest.miz') + m.save(save_path) + print('-' * 10, "Saved", save_path) + # reload mission + m = dcs.mission.Mission() + msgs = m.load_file(save_path) + self.assertEqual(0, len(msgs)) + + self.assertIsNotNone(m.a10c_presets) + self.assertEqual(m.get_10c_preset(1), 251.0) + self.assertEqual(m.get_10c_preset(2), 252.0) + self.assertEqual(m.get_10c_preset(20), 253.0) \ No newline at end of file