diff --git a/EDPlayerJournal/BGS/TransactionParser.cs b/EDPlayerJournal/BGS/TransactionParser.cs index 3efd67c..f7220d2 100644 --- a/EDPlayerJournal/BGS/TransactionParser.cs +++ b/EDPlayerJournal/BGS/TransactionParser.cs @@ -1,6 +1,7 @@ using EDPlayerJournal.Entries; using System.Collections.Generic; using System.Reflection.Metadata.Ecma335; +using System.Transactions; namespace EDPlayerJournal.BGS; @@ -10,6 +11,22 @@ internal class TransactionParserContext { 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; } + + /// + /// 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; + /// /// A list of accepted missions index by their mission ID /// @@ -32,6 +49,67 @@ internal class TransactionParserContext { /// public Dictionary BuyCost = new(); + public void DiscernCombatZone(TransactionList transactions) { + string grade = "Low"; + string cztype; + ulong? highest = HighestCombatBond; + + if (highest == null || LastRecordedAwardingFaction == null) { + return; + } + + if (OnFootKills > 0) { + cztype = "OnFoot"; + // High on foot combat zones have enforcers that bring 80k a pop + if (highest >= 80000) { + grade = "High"; + } else if (highest >= 4000) { + grade = "Medium"; + } + } else if (ShipKills > 0) { + // Ship combat zones can be identified by the amount of kills + if (ShipKills > 20) { + grade = "High"; + } else if (ShipKills > 10) { + grade = "Medium"; + } + cztype = "Ship"; + } else { + transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type"); + return; + } + + CombatZone zone = new CombatZone() { + System = CurrentSystem, + Faction = LastRecordedAwardingFaction, + Grade = grade, + Type = cztype, + Amount = 1, + }; + 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; + LastRecordedAwardingFaction = null; + OnFootKills = 0; + ShipKills = 0; + } + public void BoughtCargo(string? cargo, long? cost) { if (cargo == null || cost == null) { return; @@ -610,7 +688,36 @@ internal class FactionKillBondParser : TransactionParserPart { Faction = Factions.PilotsFederation, Station = context.CurrentStation, }); + + // We are done + return; } + + context.RecordCombatBond(entry); + } +} + +internal class EmbarkDisembarkParser : TransactionParserPart { + public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { + if (e.Is(Events.Embark)) { + context.IsOnFoot = false; + } else if (e.Is(Events.Disembark)) { + context.IsOnFoot = true; + } + } +} + +internal class SupercruiseEntryParser : TransactionParserPart { + public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { + context.DiscernCombatZone(transactions); + context.ResetCombatZone(); + } +} + +internal class ShutdownParser : TransactionParserPart { + public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { + context.DiscernCombatZone(transactions); + context.ResetCombatZone(); } } @@ -618,7 +725,9 @@ public class TransactionParser { private static Dictionary ParserParts { get; } = new() { { Events.CommitCrime, new CommitCrimeParser() }, + { Events.Disembark, new EmbarkDisembarkParser() }, { Events.Docked, new DockedParser() }, + { Events.Embark, new EmbarkDisembarkParser() }, { Events.FactionKillBond, new FactionKillBondParser() }, { Events.FSDJump, new FSDJumpParser() }, { Events.Location, new LocationParser() }, @@ -634,6 +743,8 @@ public class TransactionParser { { Events.SellMicroResources, new SellMicroResourcesParser() }, { Events.SellOrganicData, new SellOrganicDataParser() }, { Events.ShipTargeted, new ShipTargetedParser() }, + { Events.Shutdown, new ShutdownParser() }, + { Events.SupercruiseEntry, new SupercruiseEntryParser() }, }; public List? Parse(IEnumerable entries) { diff --git a/EDPlayerJournal/Entries/DisembarkEntry.cs b/EDPlayerJournal/Entries/DisembarkEntry.cs new file mode 100644 index 0000000..e07b70a --- /dev/null +++ b/EDPlayerJournal/Entries/DisembarkEntry.cs @@ -0,0 +1,66 @@ +namespace EDPlayerJournal.Entries; + +public class DisembarkEntry : Entry { + /// + /// Disembarked into an SRV? + /// + public bool SRV { get; set; } = false; + + /// + /// Taxi? + /// + public bool Taxi { get; set; } = false; + + /// + /// Multicrew or not. + /// + public bool Multicrew { get; set; } = false; + + /// + /// Player's ship ID + /// + public ulong? ID { get; set; } + + /// + /// Star system + /// + public string? StarSystem { get; set; } + + /// + /// System address + /// + public ulong? SystemAddress { get; set; } + + /// + /// Body, name e.g. HIP 6182 B 2 a + /// + public string? Body { get; set; } + + /// + /// Body ID + /// + public ulong? BodyID { get; set; } + + /// + /// Disembarked on a station? + /// + public bool OnStation { get; set; } = false; + + /// + /// Disembarked on a planet? + /// + public bool OnPlanet { get; set; } = false; + + protected override void Initialise() { + SRV = JSON.Value("SRV") ?? false; + Taxi = JSON.Value("Taxi") ?? false; + Multicrew = JSON.Value("Multicrew") ?? false; + ID = JSON.Value("ID"); + StarSystem = JSON.Value("StarSystem"); + SystemAddress = JSON.Value("SystemAddress"); + Body = JSON.Value("Body"); + BodyID = JSON.Value("BodyID"); + OnStation = JSON.Value("OnStation") ?? false; + OnPlanet = JSON.Value("OnPlanet") ?? false; + } +} diff --git a/EDPlayerJournal/Entries/EmbarkEntry.cs b/EDPlayerJournal/Entries/EmbarkEntry.cs new file mode 100644 index 0000000..462ac2b --- /dev/null +++ b/EDPlayerJournal/Entries/EmbarkEntry.cs @@ -0,0 +1,66 @@ +namespace EDPlayerJournal.Entries; + +public class EmbarkEntry : Entry { + /// + /// Disembarked into an SRV? + /// + public bool SRV { get; set; } = false; + + /// + /// Taxi? + /// + public bool Taxi { get; set; } = false; + + /// + /// Multicrew or not. + /// + public bool Multicrew { get; set; } = false; + + /// + /// Player's ship ID + /// + public ulong? ID { get; set; } + + /// + /// Star system + /// + public string? StarSystem { get; set; } + + /// + /// System address + /// + public ulong? SystemAddress { get; set; } + + /// + /// Body, name e.g. HIP 6182 B 2 a + /// + public string? Body { get; set; } + + /// + /// Body ID + /// + public ulong? BodyID { get; set; } + + /// + /// Disembarked on a station? + /// + public bool OnStation { get; set; } = false; + + /// + /// Disembarked on a planet? + /// + public bool OnPlanet { get; set; } = false; + + protected override void Initialise() { + SRV = JSON.Value("SRV") ?? false; + Taxi = JSON.Value("Taxi") ?? false; + Multicrew = JSON.Value("Multicrew") ?? false; + ID = JSON.Value("ID"); + StarSystem = JSON.Value("StarSystem"); + SystemAddress = JSON.Value("SystemAddress"); + Body = JSON.Value("Body"); + BodyID = JSON.Value("BodyID"); + OnStation = JSON.Value("OnStation") ?? false; + OnPlanet = JSON.Value("OnPlanet") ?? false; + } +} diff --git a/EDPlayerJournal/Entries/Entry.cs b/EDPlayerJournal/Entries/Entry.cs index c9b5659..6ce35f4 100644 --- a/EDPlayerJournal/Entries/Entry.cs +++ b/EDPlayerJournal/Entries/Entry.cs @@ -16,9 +16,11 @@ public class Entry { { Events.Commander, typeof(CommanderEntry) }, { Events.CommitCrime, typeof(CommitCrimeEntry) }, { Events.Died, typeof(DiedEntry) }, + { Events.Disembark, typeof(DisembarkEntry) }, { Events.Docked, typeof(DockedEntry) }, - { Events.FileHeader, typeof(FileHeaderEntry) }, + { Events.Embark, typeof(EmbarkEntry) }, { Events.FactionKillBond, typeof(FactionKillBondEntry) }, + { Events.FileHeader, typeof(FileHeaderEntry) }, { Events.FSDJump, typeof(FSDJumpEntry) }, { Events.HullDamage, typeof(HullDamageEntry) }, { Events.LoadGame, typeof(LoadGameEntry) }, @@ -39,6 +41,8 @@ public class Entry { { Events.SellOrganicData, typeof(SellOrganicDataEntry) }, { Events.ShieldState, typeof(ShieldStateEntry) }, { Events.ShipTargeted, typeof(ShipTargetedEntry) }, + { Events.SupercruiseEntry, typeof(SupercruiseEntryEntry) }, + { Events.SupercruiseExit, typeof(SupercruiseExitEntry) }, { Events.UnderAttack, typeof(UnderAttackEntry) }, }; diff --git a/EDPlayerJournal/Entries/Events.cs b/EDPlayerJournal/Entries/Events.cs index 288a0d5..a555b0b 100644 --- a/EDPlayerJournal/Entries/Events.cs +++ b/EDPlayerJournal/Entries/Events.cs @@ -5,7 +5,9 @@ public class Events { public static readonly string Commander = "Commander"; public static readonly string CommitCrime = "CommitCrime"; public static readonly string Died = "Died"; + public static readonly string Disembark = "Disembark"; public static readonly string Docked = "Docked"; + public static readonly string Embark = "Embark"; public static readonly string FactionKillBond = "FactionKillBond"; public static readonly string FighterDestroyed = "FighterDestroyed"; public static readonly string FileHeader = "Fileheader"; @@ -29,5 +31,8 @@ public class Events { public static readonly string SellOrganicData = "SellOrganicData"; public static readonly string ShieldState = "ShieldState"; public static readonly string ShipTargeted = "ShipTargeted"; + public static readonly string Shutdown = "Shutdown"; + public static readonly string SupercruiseEntry = "SupercruiseEntry"; + public static readonly string SupercruiseExit = "SupercruiseExit"; public static readonly string UnderAttack = "UnderAttack"; } diff --git a/EDPlayerJournal/Entries/SupercruiseEntry.cs b/EDPlayerJournal/Entries/SupercruiseEntry.cs new file mode 100644 index 0000000..f7ec714 --- /dev/null +++ b/EDPlayerJournal/Entries/SupercruiseEntry.cs @@ -0,0 +1,30 @@ +namespace EDPlayerJournal.Entries; + +public class SupercruiseEntryEntry : Entry { + /// + /// Taxi? + /// + public bool Taxi { get; set; } = false; + + /// + /// Multicrew or not. + /// + public bool Multicrew { get; set; } = false; + + /// + /// Star system + /// + public string? StarSystem { get; set; } + + /// + /// System address + /// + public ulong? SystemAddress { get; set; } + + protected override void Initialise() { + Taxi = JSON.Value("Taxi") ?? false; + Multicrew = JSON.Value("Multicrew") ?? false; + StarSystem = JSON.Value("StarSystem"); + SystemAddress = JSON.Value("SystemAddress"); + } +} diff --git a/EDPlayerJournal/Entries/SupercruiseExitEntry.cs b/EDPlayerJournal/Entries/SupercruiseExitEntry.cs new file mode 100644 index 0000000..50ac4a5 --- /dev/null +++ b/EDPlayerJournal/Entries/SupercruiseExitEntry.cs @@ -0,0 +1,48 @@ +namespace EDPlayerJournal.Entries; + +public class SupercruiseExitEntry : Entry { + /// + /// Taxi? + /// + public bool Taxi { get; set; } = false; + + /// + /// Multicrew or not. + /// + public bool Multicrew { get; set; } = false; + + /// + /// Star system + /// + public string? StarSystem { get; set; } + + /// + /// System address + /// + public ulong? SystemAddress { get; set; } + + /// + /// Body, name e.g. HIP 6182 B 2 a + /// + public string? Body { get; set; } + + /// + /// Body ID + /// + public ulong? BodyID { get; set; } + + /// + /// Body type (star, planet etc.) + /// + public string? BodyType { get; set; } + + protected override void Initialise() { + Taxi = JSON.Value("Taxi") ?? false; + Multicrew = JSON.Value("Multicrew") ?? false; + StarSystem = JSON.Value("StarSystem"); + SystemAddress = JSON.Value("SystemAddress"); + Body = JSON.Value("Body"); + BodyType = JSON.Value("BodyType"); + BodyID = JSON.Value("BodyID"); + } +}