Skip to content

Commit

Permalink
Add S&R BGS tracking. Closes #194.
Browse files Browse the repository at this point in the history
  • Loading branch information
aussig committed Apr 6, 2024
1 parent b903455 commit c66adad
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 19 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Independent language for Discord posts. You can separately set the language that is used for Discord posts, in case the Discord server has a different preferred language to the one you run EDMC in.
* Added logo to main window and all window icons
* Added options to only post your BGS activity, only your TW activity or both (defaults to both), for CMDRs who want to selectively post a single type of activity.
* Now track and report Search and Rescue (SandR) hand-ins for the BGS, tallied against the controlling faction at the station handed in.

### Changes:

Expand All @@ -21,6 +22,10 @@
* Was incorrectly reporting BGS activity in TW systems.
* Was incorrectly reporting TW search and rescue collection in non-TW systems.

### API Changes ([vx.x](https://studio-ws.apicur.io/sharing/xxxxxxxx)):

* `/activities` endpoint: Search and Rescue handins now included at `systems/[system]/factions/[faction]/sandr`, containing `damagedpods`, `occupiedpods`, `thargoidpods`, `blackboxes`, `wreckagecomponents`, `personaleffects`, `politicalprisoners` and `hostages` as properties.


## v3.6.0 - 2024-03-23

Expand Down
86 changes: 67 additions & 19 deletions bgstally/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ def trade_sold(self, journal_entry:dict, state:State):
# Handle SandR tissue samples first
cargo_type:str = journal_entry.get('Type', "").lower()
if 'thargoidtissuesample' in cargo_type or 'thargoidscouttissuesample' in cargo_type:
self._sandr_handin('t', journal_entry.get('Count', 0), True)
self._tw_sandr_handin('t', journal_entry.get('Count', 0), True)
# Fall through to BGS tracking for standard trade sale

faction = current_system['Factions'].get(state.station_faction)
Expand Down Expand Up @@ -857,7 +857,7 @@ def cargo(self, journal_entry: dict):
Handle Cargo status
"""
if journal_entry.get('Vessel') == "Ship" and journal_entry.get('Count', 0) == 0:
self._sandr_clear_all_scooped()
self._tw_sandr_clear_all_scooped()


def collect_cargo(self, journal_entry: dict, state: State):
Expand Down Expand Up @@ -898,33 +898,56 @@ def eject_cargo(self, journal_entry: dict):

if key is None: return

self._sandr_handin(key, journal_entry.get('Count', 0), False)
self._tw_sandr_handin(key, journal_entry.get('Count', 0), False)


def search_and_rescue(self, journal_entry: dict, state: State):
"""
Handle search and rescue hand-in
Handle search and rescue hand-in.
"""
key:str = None
count:int = int(journal_entry.get('Count', 0))
current_system: dict = self.systems.get(state.current_system_id)
if not current_system: return
count: int = int(journal_entry.get('Count', 0))
if count == 0: return

key: str = None
tw: bool = False

# There is no tissue sample tracking here as those are treated a commodities
match journal_entry.get('Name', "").lower():
case 'damagedescapepod': key = 'dp'
case 'occupiedcryopod': key = 'op'
case 'thargoidpod': key = 'tp'
case 'usscargoblackbox': key = 'bb'
# There is no TW tissue sample tracking here as those are treated a commodities
case 'damagedescapepod': key = 'dp'; tw = True
case 'occupiedcryopod': key = 'op'; tw = True
case 'thargoidpod': key = 'tp'; tw = True
case 'usscargoblackbox': key = 'bb'; tw = True
case 'wreckagecomponents': key = 'wc'
case 'personaleffects': key = 'pe'
case 'politicalprisoner': key = 'pp'
case 'hostage': key = 'h'

if key is None or count == 0: return
if key is None: return

self._sandr_handin(key, count, True)
# Handle BGS S&R
# This is counted for the controlling faction at the station handed in. Note that if the S&R items originated in a TW
# system, they will be counted for both BGS and TW

faction = current_system['Factions'].get(state.station_faction)
if faction:
self.dirty = True
self.bgstally.ui.show_system_report(current_system['SystemAddress'])

faction['SandR'][key] += count
self.recalculate_zero_activity()

# Handle TW S&R
if not tw: return
self._tw_sandr_handin(key, count, True)


def player_resurrected(self):
"""
Clear down any logged S&R cargo on resurrect
"""
self._sandr_clear_all_scooped()
self._tw_sandr_clear_all_scooped()


def recalculate_zero_activity(self):
Expand Down Expand Up @@ -1032,6 +1055,7 @@ def _get_new_faction_data(self, faction_name, faction_state):
'TradeSell': [{'items': 0, 'value': 0, 'profit': 0}, {'items': 0, 'value': 0, 'profit': 0}, {'items': 0, 'value': 0, 'profit': 0}, {'items': 0, 'value': 0, 'profit': 0}],
'CombatBonds': 0, 'MissionFailed': 0, 'Murdered': 0, 'GroundMurdered': 0,
'SpaceCZ': {}, 'GroundCZ': {}, 'GroundCZSettlements': {}, 'Scenarios': 0,
'SandR': {'dp': 0, 'op': 0, 'tp': 0, 'bb': 0, 'wc': 0, 'pe': 0, 'pp': 0, 'h': 0},
'TWStations': {}}


Expand Down Expand Up @@ -1144,6 +1168,8 @@ def _update_faction_data(self, faction_data: Dict, faction_state: str = None):
faction_data['MissionPoints'] = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, 'm': int(faction_data.get('MissionPoints', 0))}
if not type(faction_data.get('MissionPointsSecondary', 0)) == dict:
faction_data['MissionPointsSecondary'] = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, 'm': int(faction_data.get('MissionPointsSecondary', 0))}
# From < 4.0.0 to 4.0.0
if not 'SandR' in faction_data: faction_data['SandR'] = {'dp': 0, 'op': 0, 'tp': 0, 'bb': 0, 'wc': 0, 'pe': 0, 'pp': 0, 'h': 0}


def _is_faction_data_zero(self, faction_data: Dict):
Expand All @@ -1163,15 +1189,16 @@ def _is_faction_data_zero(self, faction_data: Dict):
(faction_data['GroundCZ'] == {} or (int(faction_data['GroundCZ'].get('l', 0)) == 0 and int(faction_data['GroundCZ'].get('m', 0)) == 0 and int(faction_data['GroundCZ'].get('h', 0)) == 0)) and \
faction_data['GroundCZSettlements'] == {} and \
int(faction_data['Scenarios']) == 0 and \
sum(faction_data.get('SandR', {}).values()) == 0 and \
faction_data['TWStations'] == {}


def _sandr_handin(self, key:str, count:int, tally:bool):
def _tw_sandr_handin(self, key:str, count:int, tally:bool):
"""
Tally a search and rescue handin. These can originate from SearchAndRescue or TradeSell events
Tally a TW search and rescue handin. These can originate from SearchAndRescue or TradeSell events
"""

# S&R can be handed in in any system, but the effect counts for the system the items were collected in. However,
# This can be handed in in any system, but the effect counts for the system the items were collected in. However,
# we have no way of knowing exactly which items were handed in, so just iterate through all our known systems
# looking for previously scooped cargo of the correct type.

Expand All @@ -1191,9 +1218,9 @@ def _sandr_handin(self, key:str, count:int, tally:bool):
# where it originally came from


def _sandr_clear_all_scooped(self):
def _tw_sandr_clear_all_scooped(self):
"""
Clear down all search and rescue scooped cargo
Clear down all TW search and rescue scooped cargo
"""
for system in self.systems.values():
system['TWSandR']['dp']['scooped'] = 0
Expand Down Expand Up @@ -1226,6 +1253,7 @@ def _generate_faction_text(self, faction: dict, discord: bool):
activity_text += magenta(__("Fails"), fp=fp) + " " + green(faction['MissionFailed'], fp=fp) + " " if faction['MissionFailed'] != 0 else "" # LANG: Discord heading, abbreviation for failed missions
activity_text += self._build_cz_text(faction.get('SpaceCZ', {}), __("SpaceCZs"), discord) # LANG: Discord heading, abbreviation for space conflict zones
activity_text += self._build_cz_text(faction.get('GroundCZ', {}), __("GroundCZs"), discord) # LANG: Discord heading, abbreviation for ground conflict zones
activity_text += self._build_sandr_text(faction.get('SandR', {}), discord)

faction_name = self._process_faction_name(faction['Faction'])
faction_text = f"{color_wrap(faction_name, 'yellow', None, 'bold', fp=fp)} {activity_text}\n" if activity_text != "" else ""
Expand Down Expand Up @@ -1509,6 +1537,26 @@ def _build_tw_vessels_text(self, tw_data: dict, discord: bool) -> str:
return text


def _build_sandr_text(self, sandr_data: dict, discord: bool) -> str:
"""Create a summary of BGS search and rescue activity
Args:
sandr_data (dict): dict containing an entry for each type of SandR handin
discord (bool): True if this text is destined for Discord
Returns:
str: The activity summary text
"""
if sandr_data == {}: return ""
# Force plain text if we are not posting to Discord
fp:bool = not discord

value: int = int(sum(sandr_data.values()))
if value == 0: return ""

return white(__("SandR"), fp=fp) + " " + green(value, fp=fp) + " " # LANG: Discord heading, abbreviation for search and rescue


def _process_faction_name(self, faction_name):
"""
Shorten the faction name if the user has chosen to
Expand Down
12 changes: 12 additions & 0 deletions bgstally/apimanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ def _build_api_activity(self, activity:Activity, cmdr:str):
}
}

if sum(faction.get('SandR', {}).values()) > 0:
api_faction['sandr'] = {
'damagedpods': get_by_path(faction, ['SandR', 'dp'], 0),
'occupiedpods': get_by_path(faction, ['SandR', 'op'], 0),
'thargoidpods': get_by_path(faction, ['SandR', 'tp'], 0),
'blackboxes': get_by_path(faction, ['SandR', 'bb'], 0),
'wreckagecomponents': get_by_path(faction, ['SandR', 'wc'], 0),
'personaleffects': get_by_path(faction, ['SandR', 'pe'], 0),
'politicalprisoners': get_by_path(faction, ['SandR', 'pp'], 0),
'hostages': get_by_path(faction, ['SandR', 'h'], 0)
}

if faction.get('GroundCZ', {}) != {}:
api_faction['czground'] = {
'low': faction['GroundCZ'].get('l', 0),
Expand Down
2 changes: 2 additions & 0 deletions bgstally/windows/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ def show(self, activity: Activity):
ttk.Label(frame_table, text=_("Ground"), font=FONT_HEADING_2).grid(row=1, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title
ttk.Label(frame_table, text=_("Ship"), font=FONT_HEADING_2).grid(row=1, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title
ttk.Label(frame_table, text=_("Scens"), font=FONT_HEADING_2).grid(row=0, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title, abbreviation for scenarios
ttk.Label(frame_table, text=_("SandR"), font=FONT_HEADING_2).grid(row=0, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title, abbreviation for search and rescue
ttk.Label(frame_table, text=_("SpaceCZs"), font=FONT_HEADING_2, anchor=tk.CENTER).grid(row=0, column=col, columnspan=3, padx=2) # LANG: Activity window column title, abbreviation for space conflict zones
ttk.Label(frame_table, text="L", font=FONT_HEADING_2).grid(row=1, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title, abbreviation for low
ttk.Label(frame_table, text="M", font=FONT_HEADING_2).grid(row=1, column=col, padx=2, pady=2); col += 1 # LANG: Activity window column title, abbreviation for medium
Expand Down Expand Up @@ -251,6 +252,7 @@ def show(self, activity: Activity):
ScenariosVar = tk.IntVar(value=faction['Scenarios'])
ttk.Spinbox(frame_table, from_=0, to=999, width=3, textvariable=ScenariosVar).grid(row=x + header_rows, column=col, sticky=tk.N, padx=2, pady=2); col += 1
ScenariosVar.trace('w', partial(self._scenarios_change, TabParent, tab_index, ScenariosVar, EnableAllCheckbutton, DiscordText, activity, system, faction, x))
ttk.Label(frame_table, text=sum(faction.get('SandR', {}).values())).grid(row=x + header_rows, column=col, sticky=tk.N); col += 1

if (faction['FactionState'] in STATES_WAR):
CZSpaceLVar = tk.StringVar(value=faction['SpaceCZ'].get('l', '0'))
Expand Down

0 comments on commit c66adad

Please sign in to comment.