From 1776340b4d6cf1645682e454332bdef3be0be216 Mon Sep 17 00:00:00 2001 From: aussig Date: Sun, 9 Jul 2023 15:53:05 +0100 Subject: [PATCH 1/7] Allow tracking in zero-pop systems. Important for TW kill logging. Closes #123. --- CHANGELOG.md | 7 +++++++ bgstally/activity.py | 40 +++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9647a55..d0179f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## vx.x.x-xx - xxxx-xx-xx + +### Bug Fixes: + +* TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. + + ## v3.1.0-a3 - 2023-06-23 ### Bug Fixes: diff --git a/bgstally/activity.py b/bgstally/activity.py index 2941f01..a0fa5b8 100644 --- a/bgstally/activity.py +++ b/bgstally/activity.py @@ -181,9 +181,6 @@ def system_entered(self, journal_entry: Dict, state: State): """ The user has entered a system """ - try: test = journal_entry['Factions'] - except KeyError: return - self.dirty = True current_system = None @@ -200,28 +197,29 @@ def system_entered(self, journal_entry: Dict, state: State): self._update_system_data(current_system) - for faction in journal_entry['Factions']: - if faction['Name'] == "Pilots' Federation Local Branch": continue + if 'Factions' in journal_entry: + for faction in journal_entry['Factions']: + if faction['Name'] == "Pilots' Federation Local Branch": continue - # Ignore conflict states in FactionState as we can't trust they always come in pairs. We deal with conflicts separately below. - faction_state = faction['FactionState'] if faction['FactionState'] not in STATES_WAR and faction['FactionState'] not in STATES_ELECTION else "None" + # Ignore conflict states in FactionState as we can't trust they always come in pairs. We deal with conflicts separately below. + faction_state = faction['FactionState'] if faction['FactionState'] not in STATES_WAR and faction['FactionState'] not in STATES_ELECTION else "None" - if faction['Name'] in current_system['Factions']: - # We have this faction, ensure it's up to date with latest state - faction_data = current_system['Factions'][faction['Name']] - self._update_faction_data(faction_data, faction_state) - else: - # We do not have this faction, create a new clean entry - current_system['Factions'][faction['Name']] = self._get_new_faction_data(faction['Name'], faction_state) + if faction['Name'] in current_system['Factions']: + # We have this faction, ensure it's up to date with latest state + faction_data = current_system['Factions'][faction['Name']] + self._update_faction_data(faction_data, faction_state) + else: + # We do not have this faction, create a new clean entry + current_system['Factions'][faction['Name']] = self._get_new_faction_data(faction['Name'], faction_state) - # Set war states for pairs of factions in War / Civil War / Elections - for conflict in journal_entry.get('Conflicts', []): - if conflict['Status'] != "active": continue + # Set war states for pairs of factions in War / Civil War / Elections + for conflict in journal_entry.get('Conflicts', []): + if conflict['Status'] != "active": continue - if conflict['Faction1']['Name'] in current_system['Factions'] and conflict['Faction2']['Name'] in current_system['Factions']: - conflict_state = "War" if conflict['WarType'] == "war" else "CivilWar" if conflict['WarType'] == "civilwar" else "Election" if conflict['WarType'] == "election" else "None" - current_system['Factions'][conflict['Faction1']['Name']]['FactionState'] = conflict_state - current_system['Factions'][conflict['Faction2']['Name']]['FactionState'] = conflict_state + if conflict['Faction1']['Name'] in current_system['Factions'] and conflict['Faction2']['Name'] in current_system['Factions']: + conflict_state = "War" if conflict['WarType'] == "war" else "CivilWar" if conflict['WarType'] == "civilwar" else "Election" if conflict['WarType'] == "election" else "None" + current_system['Factions'][conflict['Faction1']['Name']]['FactionState'] = conflict_state + current_system['Factions'][conflict['Faction2']['Name']]['FactionState'] = conflict_state self.recalculate_zero_activity() state.current_system_id = str(current_system['SystemAddress']) From 1bab595ba4e1a64904e6d04569847fe8fc7b0439 Mon Sep 17 00:00:00 2001 From: aussig Date: Sun, 9 Jul 2023 15:55:10 +0100 Subject: [PATCH 2/7] Now clear S&R delivered items on new tick. Fixes #122. --- CHANGELOG.md | 1 + bgstally/activity.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0179f3..3a0cb12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes: * TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. +* TW search and rescue hand-ins were being carried forward to the next tick for systems where items had been both scooped and delivered - escape pods, black boxes and tissue samples. Delivered items are now cleared on a new tick. ## v3.1.0-a3 - 2023-06-23 diff --git a/bgstally/activity.py b/bgstally/activity.py index a0fa5b8..807ef36 100644 --- a/bgstally/activity.py +++ b/bgstally/activity.py @@ -167,7 +167,9 @@ def clear_activity(self, mission_log: MissionLog): for faction_name, faction_data in system['Factions'].items(): system['Factions'][faction_name] = self._get_new_faction_data(faction_name, faction_data['FactionState']) system['TWKills'] = self._get_new_tw_kills_data() - # Note: system['TWSandR'] data is carried forward + # Note: system['TWSandR'] scooped data is carried forward, delivered data is cleared + for d in system['TWSandR'].values(): + d['delivered'] = 0 else: # Delete the whole system del self.systems[system_address] From a52912c5259c645b06cd83faab454d7c7a178619 Mon Sep 17 00:00:00 2001 From: aussig Date: Mon, 10 Jul 2023 17:50:11 +0100 Subject: [PATCH 3/7] Track Revenant kills. Closes #117. --- CHANGELOG.md | 4 ++++ bgstally/activity.py | 4 ++-- bgstally/apimanager.py | 13 +++++++------ bgstally/windows/activity.py | 11 ++++++++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0cb12..7d52e84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## vx.x.x-xx - xxxx-xx-xx +### New Features: + +* Thargoid War Revenant kills are now tracked. + ### Bug Fixes: * TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. diff --git a/bgstally/activity.py b/bgstally/activity.py index 807ef36..abdcf9f 100644 --- a/bgstally/activity.py +++ b/bgstally/activity.py @@ -70,7 +70,7 @@ CZ_GROUND_LOW_CB_MAX = 5000 CZ_GROUND_MED_CB_MAX = 38000 -TW_CBS = {65000: 's', 75000: 's', 6500000: 'c', 20000000: 'b', 25000000: 'o', 34000000: 'm', 50000000: 'h'} +TW_CBS = {25000: 'r', 65000: 's', 75000: 's', 6500000: 'c', 20000000: 'b', 25000000: 'o', 34000000: 'm', 50000000: 'h'} class Activity: @@ -733,7 +733,7 @@ def _get_new_tw_kills_data(self): """ Get a new data structure for storing Thargoid War Kills """ - return {'s': 0, 'c': 0, 'b': 0, 'm': 0, 'h': 0, 'o': 0} + return {'r': 0, 's': 0, 'c': 0, 'b': 0, 'm': 0, 'h': 0, 'o': 0} def _get_new_tw_sandr_data(self): diff --git a/bgstally/apimanager.py b/bgstally/apimanager.py index db88daf..60dfe50 100644 --- a/bgstally/apimanager.py +++ b/bgstally/apimanager.py @@ -201,12 +201,13 @@ def _build_api_activity(self, activity:Activity, cmdr:str): if sum(system.get('TWKills', {}).values()) > 0: api_system['twkills'] = { - 'basilisk': system['TWKills']['b'], - 'cyclops': system['TWKills']['c'], - 'hydra': system['TWKills']['h'], - 'medusa': system['TWKills']['m'], - 'orthrus': system['TWKills']['o'], - 'scout': system['TWKills']['s'] + 'revenant': system['TWKills'].get('r', 0), + 'basilisk': system['TWKills'].get('b', 0), + 'cyclops': system['TWKills'].get('c', 0), + 'hydra': system['TWKills'].get('h', 0), + 'medusa': system['TWKills'].get('m', 0), + 'orthrus': system['TWKills'].get('o', 0), + 'scout': system['TWKills'].get('s', 0) } if sum(int(d['delivered']) for d in system.get('TWSandR', {}).values()) > 0: diff --git a/bgstally/windows/activity.py b/bgstally/windows/activity.py index 3596118..b766a5d 100644 --- a/bgstally/windows/activity.py +++ b/bgstally/windows/activity.py @@ -652,9 +652,14 @@ def _generate_tw_system_discord_text(self, system:Dict): if kills > 0 or sandr > 0: system_discord_text += f"🍀 System activity\n" if kills > 0: - system_discord_text += f" 💀 (kills): {red('S')} x {green(system['TWKills']['s'])}, {red('C')} x {green(system['TWKills']['c'])}, " \ - + f"{red('B')} x {green(system['TWKills']['b'])}, {red('M')} x {green(system['TWKills']['m'])}, " \ - + f"{red('H')} x {green(system['TWKills']['h'])}, {red('O')} x {green(system['TWKills']['o'])} \n" + system_discord_text += f" 💀 (kills): " \ + + f"{red('R')} x {green(system['TWKills'].get('r', 0))}, " \ + + f"{red('S')} x {green(system['TWKills'].get('s', 0))}, " \ + + f"{red('C')} x {green(system['TWKills'].get('c', 0))}, " \ + + f"{red('B')} x {green(system['TWKills'].get('b', 0))}, " \ + + f"{red('M')} x {green(system['TWKills'].get('m', 0))}, " \ + + f"{red('H')} x {green(system['TWKills'].get('h', 0))}, " \ + + f"{red('O')} x {green(system['TWKills'].get('o', 0))} \n" if sandr > 0: system_discord_text += " " pods:int = system['TWSandR']['dp']['delivered'] + system['TWSandR']['op']['delivered'] From 2c66d82414664c479f417cd6815da159a14bb671 Mon Sep 17 00:00:00 2001 From: aussig Date: Mon, 10 Jul 2023 18:21:06 +0100 Subject: [PATCH 4/7] Clear StationFaction when undocked. Closes #119. --- CHANGELOG.md | 4 ++++ bgstally/bgstally.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0cb12..5fc0fda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ * TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. * TW search and rescue hand-ins were being carried forward to the next tick for systems where items had been both scooped and delivered - escape pods, black boxes and tissue samples. Delivered items are now cleared on a new tick. +### API Changes ([v1.1](https://studio-ws.apicur.io/sharing/281a84ad-dca9-42da-a08b-84e4b9af1b7e)): + +* `/events` endpoint: `StationFaction` is now an empty string "" when undocked. + ## v3.1.0-a3 - 2023-06-23 diff --git a/bgstally/bgstally.py b/bgstally/bgstally.py index ca16ac9..ecdcb67 100644 --- a/bgstally/bgstally.py +++ b/bgstally/bgstally.py @@ -197,6 +197,10 @@ def journal_entry(self, cmdr, is_beta, system, station, entry, state): self.target_log.ship_targeted(entry, system) dirty = True + case 'Undocked': + self.state.station_faction = "" + self.state.station_type = "" + if dirty: self.save_data() self.api_manager.send_activity(activity, cmdr) From d39706d8a3e85e00adb47822f6e30e121e52de96 Mon Sep 17 00:00:00 2001 From: aussig Date: Tue, 18 Jul 2023 17:57:45 +0100 Subject: [PATCH 5/7] Harden all file loading and json parsing. Fixes #124. --- CHANGELOG.md | 1 + bgstally/activity.py | 9 ++++++--- bgstally/apimanager.py | 14 +++++++++----- bgstally/fleetcarrier.py | 7 +++++-- bgstally/missionlog.py | 18 ++++++++++++------ bgstally/targetlog.py | 7 +++++-- 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e068661..ec2d259 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. * TW search and rescue hand-ins were being carried forward to the next tick for systems where items had been both scooped and delivered - escape pods, black boxes and tissue samples. Delivered items are now cleared on a new tick. +* Harden all file loading to protect against corrupted data on disk. ### API Changes ([v1.1](https://studio-ws.apicur.io/sharing/281a84ad-dca9-42da-a08b-84e4b9af1b7e)): diff --git a/bgstally/activity.py b/bgstally/activity.py index abdcf9f..c98c168 100644 --- a/bgstally/activity.py +++ b/bgstally/activity.py @@ -124,9 +124,12 @@ def load(self, filepath: str): """ Load an activity file """ - with open(filepath) as activityfile: - self._from_dict(json.load(activityfile)) - self.recalculate_zero_activity() + try: + with open(filepath) as activityfile: + self._from_dict(json.load(activityfile)) + self.recalculate_zero_activity() + except Exception as e: + Debug.logger.info(f"Unable to load {filepath}") def save(self, filepath: str): diff --git a/bgstally/apimanager.py b/bgstally/apimanager.py index 60dfe50..18b4669 100644 --- a/bgstally/apimanager.py +++ b/bgstally/apimanager.py @@ -5,6 +5,7 @@ from bgstally.activity import Activity from bgstally.api import API from bgstally.constants import DATETIME_FORMAT_JOURNAL, FOLDER_DATA +from bgstally.debug import Debug FILENAME = "apis.json" @@ -34,11 +35,14 @@ def load(self): """ file:str = path.join(self.bgstally.plugin_dir, FOLDER_DATA, FILENAME) if path.exists(file): - with open(file) as json_file: - apis_json:list = json.load(json_file) - - for api_json in apis_json: - self.apis.append(API(self.bgstally, api_json)) + try: + with open(file) as json_file: + apis_json:list = json.load(json_file) + + for api_json in apis_json: + self.apis.append(API(self.bgstally, api_json)) + except Exception as e: + Debug.logger.info(f"Unable to load {file}") def save(self): diff --git a/bgstally/fleetcarrier.py b/bgstally/fleetcarrier.py index 35a3f1b..af3c2c0 100644 --- a/bgstally/fleetcarrier.py +++ b/bgstally/fleetcarrier.py @@ -28,8 +28,11 @@ def load(self): """ file = path.join(self.bgstally.plugin_dir, FOLDER_DATA, FILENAME) if path.exists(file): - with open(file) as json_file: - self._from_dict(json.load(json_file)) + try: + with open(file) as json_file: + self._from_dict(json.load(json_file)) + except Exception as e: + Debug.logger.info(f"Unable to load {file}") def save(self): diff --git a/bgstally/missionlog.py b/bgstally/missionlog.py index 4b3b70e..28acc2d 100644 --- a/bgstally/missionlog.py +++ b/bgstally/missionlog.py @@ -28,16 +28,22 @@ def load(self): # New location file = path.join(self.bgstally.plugin_dir, FOLDER_DATA, FILENAME) if path.exists(file): - with open(file) as json_file: - self.missionlog = json.load(json_file) - return + try: + with open(file) as json_file: + self.missionlog = json.load(json_file) + return + except Exception as e: + Debug.logger.info(f"Unable to load {file}") # Legacy location file = path.join(self.bgstally.plugin_dir, FILENAME_LEGACY) if path.exists(file): - with open(file) as json_file: - self.missionlog = json.load(json_file) - remove(file) + try: + with open(file) as json_file: + self.missionlog = json.load(json_file) + remove(file) + except Exception as e: + Debug.logger.info(f"Unable to load and remove {file}") def save(self): diff --git a/bgstally/targetlog.py b/bgstally/targetlog.py index e019915..5814de8 100644 --- a/bgstally/targetlog.py +++ b/bgstally/targetlog.py @@ -37,8 +37,11 @@ def load(self): """ file = os.path.join(self.bgstally.plugin_dir, FOLDER_DATA, FILENAME) if os.path.exists(file): - with open(file) as json_file: - self.targetlog = json.load(json_file) + try: + with open(file) as json_file: + self.targetlog = json.load(json_file) + except Exception as e: + Debug.logger.info(f"Unable to load {file}") def save(self): From 58a44477a789bf75cbb752148c27e2c473fd1e8a Mon Sep 17 00:00:00 2001 From: aussig Date: Tue, 18 Jul 2023 18:37:03 +0100 Subject: [PATCH 6/7] Change exploration data tally to use the greater of `TotalEarnings` and `BaseValue` + `Bonus`. Fixes #125. --- CHANGELOG.md | 7 ++++++- bgstally/activity.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec2d259..3710944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,16 @@ * Thargoid War Revenant kills are now tracked. +### Changes: + +* Exploration data tallying now takes into account not just the `TotalEarnings` logged but also the `BaseValue` and `Bonus`. The larger value is used if these differ. Note this is now the same logic that EDDiscovery uses. + ### Bug Fixes: * TW kills were not being logged to the correct system if it was a zero-population system. This was because historically BGST only dealt with BGS logging, so ignored zero-pop systems. We now create tracking entries for these systems. * TW search and rescue hand-ins were being carried forward to the next tick for systems where items had been both scooped and delivered - escape pods, black boxes and tissue samples. Delivered items are now cleared on a new tick. -* Harden all file loading to protect against corrupted data on disk. +* Harden all file loading and JSON parsing to protect against corrupted data on disk. + ### API Changes ([v1.1](https://studio-ws.apicur.io/sharing/281a84ad-dca9-42da-a08b-84e4b9af1b7e)): diff --git a/bgstally/activity.py b/bgstally/activity.py index c98c168..494762a 100644 --- a/bgstally/activity.py +++ b/bgstally/activity.py @@ -364,7 +364,12 @@ def exploration_data_sold(self, journal_entry: Dict, state: State): faction = current_system['Factions'].get(state.station_faction) if faction: - faction['CartData'] += journal_entry['TotalEarnings'] + base_value:int = journal_entry.get('BaseValue', 0) + bonus:int = journal_entry.get('Bonus', 0) + total_earnings:int = journal_entry.get('TotalEarnings', 0) + if total_earnings < base_value + bonus: total_earnings = base_value + bonus + + faction['CartData'] += total_earnings self.recalculate_zero_activity() From 0cc2a0877548fde62e50c0c945d621c11e7983b6 Mon Sep 17 00:00:00 2001 From: aussig Date: Tue, 18 Jul 2023 19:04:02 +0100 Subject: [PATCH 7/7] Update version number for release. --- CHANGELOG.md | 2 +- load.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3710944..dcb4d0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## vx.x.x-xx - xxxx-xx-xx +## v3.1.0-b1 - 2023-07-18 ### New Features: diff --git a/load.py b/load.py index dea5902..d39f037 100644 --- a/load.py +++ b/load.py @@ -9,7 +9,7 @@ import semantic_version PLUGIN_NAME = "BGS-Tally" -PLUGIN_VERSION = semantic_version.Version.coerce("3.1.0-a3") +PLUGIN_VERSION = semantic_version.Version.coerce("3.1.0-b1") # Initialise the main plugin class this:BGSTally = BGSTally(PLUGIN_NAME, PLUGIN_VERSION)