diff --git a/EDPlayerJournal/BGS/TransactionParser.cs b/EDPlayerJournal/BGS/TransactionParser.cs
index 91101d7..a5466d8 100644
--- a/EDPlayerJournal/BGS/TransactionParser.cs
+++ b/EDPlayerJournal/BGS/TransactionParser.cs
@@ -16,242 +16,12 @@ public class TransactionParserOptions {
public bool IgnoreInfluenceSupport { get; set; } = false;
}
-internal class TransactionParserContext {
- public string? CurrentSystem { get; set; }
- public ulong? CurrentSystemAddress { get; set; }
- public string? CurrentStation { get; set; }
- public string? ControllingFaction { get; set; }
-
- public bool IsOnFoot { get; set; } = false;
-
- public string? LastRecordedAwardingFaction { get; set; }
-
- public ulong? HighestCombatBond { get; set; }
-
- public bool HaveSeenCapShip { get; set; } = false;
- public bool HaveSeenCaptain { get; set; } = false;
- public bool HaveSeenSpecOps { get; set; } = false;
- public bool HaveSeenCorrespondent { get; set; } = false;
-
- ///
- /// Returns true if the current session is legacy
- ///
- public bool IsLegacy { get; set; } = false;
-
- ///
- /// How many on foot kills were done.
- ///
- public ulong OnFootKills { get; set; } = 0;
-
- ///
- /// How many ship kills were done.
- ///
- public ulong ShipKills { get; set; } = 0;
-
- ///
- /// Thargoid scouts killed
- ///
- public ulong ThargoidScoutKills { get; set; } = 0;
-
- ///
- /// Thargoid interceptor kills
- ///
- public ulong ThargoidInterceptorKills { get; set; } = 0;
-
- ///
- /// Whether we have seen an AX warzone NPC talk to us with ReceiveText
- ///
- public bool HaveSeenAXWarzoneNPC { get; set; } = false;
-
- ///
- /// A list of accepted missions index by their mission ID
- ///
- public Dictionary AcceptedMissions { get; } = new();
- public Dictionary AcceptedMissionLocation { get; } = new();
- ///
- /// A way to lookup a system by its system id
- ///
- public Dictionary SystemsByID { get; } = new();
- ///
- /// A list of factions present in the given star system
- ///
- public Dictionary> SystemFactions { get; } = new();
- ///
- /// To which faction a given named NPC belonged to.
- ///
- public Dictionary NPCFaction { get; } = new();
- ///
- /// Buy costs for a given commodity
- ///
- public Dictionary BuyCost = new();
-
- public void DiscernCombatZone(TransactionList transactions, Entry e) {
- string? grade = CombatZones.DifficultyLow;
- string cztype;
- ulong highest = HighestCombatBond ?? 0;
- string? faction = LastRecordedAwardingFaction;
-
- if (HighestCombatBond == null &&
- LastRecordedAwardingFaction == null &&
- HaveSeenAXWarzoneNPC == false) {
- return;
- }
-
- if (OnFootKills > 0 || IsOnFoot == true) {
- cztype = CombatZones.GroundCombatZone;
- // High on foot combat zones have enforcers that bring 80k a pop
- if (highest >= 60000) {
- grade = CombatZones.DifficultyHigh;
- } else if (highest >= 30000) {
- // In medium conflict zones, the enforcers are worth 30k
- grade = CombatZones.DifficultyMedium;
- } else {
- grade = CombatZones.DifficultyLow;
- }
- } else if (ShipKills > 0 && !IsOnFoot) {
- // Ship combat zones can be identified by the amount of kills
- if (ShipKills > 20) {
- grade = CombatZones.DifficultyHigh;
- } else if (ShipKills > 10) {
- grade = CombatZones.DifficultyMedium;
- }
-
- // Cap ship, means a high conflict zone
- if (HaveSeenCapShip) {
- grade = CombatZones.DifficultyHigh;
- } else {
- int warzoneNpcs = new List() { HaveSeenCaptain, HaveSeenCorrespondent, HaveSeenSpecOps }
- .Where(x => x == true)
- .Count()
- ;
-
- if (warzoneNpcs >= 1 && grade == CombatZones.DifficultyLow) {
- grade = CombatZones.DifficultyMedium;
- }
- }
- cztype = CombatZones.ShipCombatZone;
- } else if ((ThargoidScoutKills > 0 && ThargoidInterceptorKills > 0) ||
- HaveSeenAXWarzoneNPC == true) {
- // Could be a thargoid combat zones if interceptors and scouts are there
- cztype = CombatZones.AXCombatZone;
- // Still unknown
- grade = null;
- } else {
- transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type", e);
- return;
- }
-
- CombatZone zone = new CombatZone() {
- System = CurrentSystem,
- Faction = faction,
- IsLegacy = IsLegacy,
- Grade = grade,
- Type = cztype,
- // Sad truth is, if HaveSeenXXX is false, we just don't know for certain
- CapitalShip = HaveSeenCapShip ? true : null,
- SpecOps = HaveSeenSpecOps ? true : null,
- Correspondent = HaveSeenCorrespondent ? true : null,
- Captain = HaveSeenCaptain ? true : null,
- };
- zone.Entries.Add(e);
- transactions.Add(zone);
- }
-
- public void RecordCombatBond(FactionKillBondEntry e) {
- if (HighestCombatBond == null || e.Reward > HighestCombatBond) {
- HighestCombatBond = e.Reward;
- }
-
- LastRecordedAwardingFaction = e.AwardingFaction;
-
- if (IsOnFoot) {
- ++OnFootKills;
- } else {
- ++ShipKills;
- }
- }
-
- public void ResetCombatZone() {
- HighestCombatBond = null;
- HaveSeenCapShip = false;
- HaveSeenCaptain = false;
- HaveSeenCorrespondent = false;
- HaveSeenSpecOps = false;
- LastRecordedAwardingFaction = null;
- OnFootKills = 0;
- ShipKills = 0;
- ThargoidInterceptorKills = 0;
- ThargoidScoutKills = 0;
- HaveSeenAXWarzoneNPC = false;
- }
-
- public void BoughtCargo(string? cargo, long? cost) {
- if (cargo == null || cost == null) {
- return;
- }
-
- BuyCost[cargo] = cost.Value;
- }
-
- public List? GetFactions(string? system) {
- if (system == null || !SystemFactions.ContainsKey(system)) {
- return null;
- }
-
- return SystemFactions[system];
- }
-
- public void MissionAccepted(MissionAcceptedEntry? entry) {
- if (entry == null) {
- return;
- }
-
- MissionAccepted(entry.Mission);
- }
-
- public void MissionAccepted(Mission? mission) {
- if (CurrentSystem == null || CurrentSystemAddress == null) {
- throw new Exception("Mission accepted without knowing where.");
- }
-
- if (mission == null) {
- throw new Exception("Mission is null");
- }
-
- AcceptedMissions.TryAdd(mission.MissionID, mission);
-
- Location location = new() {
- StarSystem = CurrentSystem,
- SystemAddress = CurrentSystemAddress.Value,
- Station = (CurrentStation ?? ""),
- };
-
- AcceptedMissionLocation.TryAdd(mission.MissionID, location);
- }
-}
-
public class TransactionList : List {
public void AddIncomplete(Transaction underlying, string reason, Entry entry) {
Add(new IncompleteTransaction(underlying, reason, entry));
}
}
-internal interface TransactionParserPart{
- ///
- /// Parse a given entry of the entry type specified when declaring to implement this
- /// interface. You must add your transaction to the passed list in case you did have
- /// enough information to parse one or more. You may update the parser context
- /// with new information in case the entry yielded new information.
- /// Throw an exception if there was an error or a malformed entry. If you have an
- /// incomplete entry, i.e. not enough information to complete one, add an
- /// IncompleteTransaction to the list
- ///
- /// The entry to parse
- /// Parsing context that may contain useful information
- /// List of parsed transactions
- public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions);
-}
-
///
/// The location parser only updates the context with useful information, and does not
/// by itself generate any transactions. Location is the best information gatherer here
diff --git a/EDPlayerJournal/BGS/TransactionParserContext.cs b/EDPlayerJournal/BGS/TransactionParserContext.cs
new file mode 100644
index 0000000..6c8c0f6
--- /dev/null
+++ b/EDPlayerJournal/BGS/TransactionParserContext.cs
@@ -0,0 +1,246 @@
+using EDPlayerJournal.Entries;
+
+namespace EDPlayerJournal.BGS;
+
+internal class TransactionParserContext {
+ ///
+ /// Name of the current system the player is in.
+ ///
+ public string? CurrentSystem { get; set; }
+
+ ///
+ /// 64 bit address of the current system.
+ ///
+ public ulong? CurrentSystemAddress { get; set; }
+
+ ///
+ /// Controlling faction of the current system.
+ ///
+ public string? ControllingFaction { get; set; }
+
+ ///
+ /// Name of the current station the player is docked at.
+ ///
+ public string? CurrentStation { get; set; }
+
+ ///
+ /// Faction that owns the current station.
+ ///
+ public string? StationOwner { get; set; }
+
+ ///
+ /// Whether the player is currently on foot, or in an SRV/ship.
+ ///
+ public bool IsOnFoot { get; set; } = false;
+
+ ///
+ /// Last faction that awarded the player with combat bonds.
+ ///
+ public string? LastRecordedAwardingFaction { get; set; }
+
+ ///
+ /// Highest combat bond seen so far.
+ ///
+ public ulong? HighestCombatBond { get; set; }
+
+ public bool HaveSeenCapShip { get; set; } = false;
+ public bool HaveSeenCaptain { get; set; } = false;
+ public bool HaveSeenSpecOps { get; set; } = false;
+ public bool HaveSeenCorrespondent { get; set; } = false;
+
+ ///
+ /// Returns true if the current session is legacy
+ ///
+ public bool IsLegacy { get; set; } = false;
+
+ ///
+ /// How many on foot kills were done.
+ ///
+ public ulong OnFootKills { get; set; } = 0;
+
+ ///
+ /// How many ship kills were done.
+ ///
+ public ulong ShipKills { get; set; } = 0;
+
+ ///
+ /// Thargoid scouts killed
+ ///
+ public ulong ThargoidScoutKills { get; set; } = 0;
+
+ ///
+ /// Thargoid interceptor kills
+ ///
+ public ulong ThargoidInterceptorKills { get; set; } = 0;
+
+ ///
+ /// Whether we have seen an AX warzone NPC talk to us with ReceiveText
+ ///
+ public bool HaveSeenAXWarzoneNPC { get; set; } = false;
+
+ ///
+ /// A list of accepted missions index by their mission ID
+ ///
+ public Dictionary AcceptedMissions { get; } = new();
+ public Dictionary AcceptedMissionLocation { get; } = new();
+ ///
+ /// A way to lookup a system by its system id
+ ///
+ public Dictionary SystemsByID { get; } = new();
+ ///
+ /// A list of factions present in the given star system
+ ///
+ public Dictionary> SystemFactions { get; } = new();
+ ///
+ /// To which faction a given named NPC belonged to.
+ ///
+ public Dictionary NPCFaction { get; } = new();
+ ///
+ /// Buy costs for a given commodity
+ ///
+ public Dictionary BuyCost = new();
+
+ public void DiscernCombatZone(TransactionList transactions, Entry e) {
+ string? grade = CombatZones.DifficultyLow;
+ string cztype;
+ ulong highest = HighestCombatBond ?? 0;
+ string? faction = LastRecordedAwardingFaction;
+
+ if (HighestCombatBond == null &&
+ LastRecordedAwardingFaction == null &&
+ HaveSeenAXWarzoneNPC == false) {
+ return;
+ }
+
+ if (OnFootKills > 0 || IsOnFoot == true) {
+ cztype = CombatZones.GroundCombatZone;
+ // High on foot combat zones have enforcers that bring 80k a pop
+ if (highest >= 60000) {
+ grade = CombatZones.DifficultyHigh;
+ } else if (highest >= 30000) {
+ // In medium conflict zones, the enforcers are worth 30k
+ grade = CombatZones.DifficultyMedium;
+ } else {
+ grade = CombatZones.DifficultyLow;
+ }
+ } else if (ShipKills > 0 && !IsOnFoot) {
+ // Ship combat zones can be identified by the amount of kills
+ if (ShipKills > 20) {
+ grade = CombatZones.DifficultyHigh;
+ } else if (ShipKills > 10) {
+ grade = CombatZones.DifficultyMedium;
+ }
+
+ // Cap ship, means a high conflict zone
+ if (HaveSeenCapShip) {
+ grade = CombatZones.DifficultyHigh;
+ } else {
+ int warzoneNpcs = new List() { HaveSeenCaptain, HaveSeenCorrespondent, HaveSeenSpecOps }
+ .Where(x => x == true)
+ .Count()
+ ;
+
+ if (warzoneNpcs >= 1 && grade == CombatZones.DifficultyLow) {
+ grade = CombatZones.DifficultyMedium;
+ }
+ }
+ cztype = CombatZones.ShipCombatZone;
+ } else if ((ThargoidScoutKills > 0 && ThargoidInterceptorKills > 0) ||
+ HaveSeenAXWarzoneNPC == true) {
+ // Could be a thargoid combat zones if interceptors and scouts are there
+ cztype = CombatZones.AXCombatZone;
+ // Still unknown
+ grade = null;
+ } else {
+ transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type", e);
+ return;
+ }
+
+ CombatZone zone = new CombatZone() {
+ System = CurrentSystem,
+ Faction = faction,
+ IsLegacy = IsLegacy,
+ Grade = grade,
+ Type = cztype,
+ // Sad truth is, if HaveSeenXXX is false, we just don't know for certain
+ CapitalShip = HaveSeenCapShip ? true : null,
+ SpecOps = HaveSeenSpecOps ? true : null,
+ Correspondent = HaveSeenCorrespondent ? true : null,
+ Captain = HaveSeenCaptain ? true : null,
+ };
+ zone.Entries.Add(e);
+ transactions.Add(zone);
+ }
+
+ public void RecordCombatBond(FactionKillBondEntry e) {
+ if (HighestCombatBond == null || e.Reward > HighestCombatBond) {
+ HighestCombatBond = e.Reward;
+ }
+
+ LastRecordedAwardingFaction = e.AwardingFaction;
+
+ if (IsOnFoot) {
+ ++OnFootKills;
+ } else {
+ ++ShipKills;
+ }
+ }
+
+ public void ResetCombatZone() {
+ HighestCombatBond = null;
+ HaveSeenCapShip = false;
+ HaveSeenCaptain = false;
+ HaveSeenCorrespondent = false;
+ HaveSeenSpecOps = false;
+ LastRecordedAwardingFaction = null;
+ OnFootKills = 0;
+ ShipKills = 0;
+ ThargoidInterceptorKills = 0;
+ ThargoidScoutKills = 0;
+ HaveSeenAXWarzoneNPC = false;
+ }
+
+ public void BoughtCargo(string? cargo, long? cost) {
+ if (cargo == null || cost == null) {
+ return;
+ }
+
+ BuyCost[cargo] = cost.Value;
+ }
+
+ public List? GetFactions(string? system) {
+ if (system == null || !SystemFactions.ContainsKey(system)) {
+ return null;
+ }
+
+ return SystemFactions[system];
+ }
+
+ public void MissionAccepted(MissionAcceptedEntry? entry) {
+ if (entry == null) {
+ return;
+ }
+
+ MissionAccepted(entry.Mission);
+ }
+
+ public void MissionAccepted(Mission? mission) {
+ if (CurrentSystem == null || CurrentSystemAddress == null) {
+ throw new Exception("Mission accepted without knowing where.");
+ }
+
+ if (mission == null) {
+ throw new Exception("Mission is null");
+ }
+
+ AcceptedMissions.TryAdd(mission.MissionID, mission);
+
+ Location location = new() {
+ StarSystem = CurrentSystem,
+ SystemAddress = CurrentSystemAddress.Value,
+ Station = (CurrentStation ?? ""),
+ };
+
+ AcceptedMissionLocation.TryAdd(mission.MissionID, location);
+ }
+}
diff --git a/EDPlayerJournal/BGS/TransactionParserPart.cs b/EDPlayerJournal/BGS/TransactionParserPart.cs
new file mode 100644
index 0000000..00ebecf
--- /dev/null
+++ b/EDPlayerJournal/BGS/TransactionParserPart.cs
@@ -0,0 +1,19 @@
+using EDPlayerJournal.Entries;
+
+namespace EDPlayerJournal.BGS;
+
+internal interface TransactionParserPart {
+ ///
+ /// Parse a given entry of the entry type specified when declaring to implement this
+ /// interface. You must add your transaction to the passed list in case you did have
+ /// enough information to parse one or more. You may update the parser context
+ /// with new information in case the entry yielded new information.
+ /// Throw an exception if there was an error or a malformed entry. If you have an
+ /// incomplete entry, i.e. not enough information to complete one, add an
+ /// IncompleteTransaction to the list
+ ///
+ /// The entry to parse
+ /// Parsing context that may contain useful information
+ /// List of parsed transactions
+ public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions);
+}