diff --git a/EDPlayerJournal/BGS/Parsers/RedeemVoucherParser.cs b/EDPlayerJournal/BGS/Parsers/RedeemVoucherParser.cs new file mode 100644 index 0000000..31d35b5 --- /dev/null +++ b/EDPlayerJournal/BGS/Parsers/RedeemVoucherParser.cs @@ -0,0 +1,84 @@ +using EDPlayerJournal.Entries; + +namespace EDPlayerJournal.BGS.Parsers; + +internal class RedeemVoucherParser : ITransactionParserPart { + public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { + RedeemVoucherEntry? entry = e as RedeemVoucherEntry; + if (entry == null) { + throw new NotImplementedException(); + } + + if (context.CurrentSystem == null) { + transactions.AddIncomplete(new Vouchers(), + "Could not find out where the vouchers were redeemed", e + ); + return; + } + + List? current_factions = context.GetFactions(context.CurrentSystem); + if (current_factions == null) { + transactions.AddIncomplete(new Vouchers(), + "Current system factions are unknown, so vouchers were ineffective", e); + } + + foreach (string faction in entry.Factions) { + bool relevantBond = false; + string relevantFaction = faction; + + if (string.Compare(faction, Factions.PilotsFederationVouchers) == 0) { + // Target faction is pilots' federation, so we assume thargoid bonks + // Also assign this combat bond to the Pilots Federation + relevantFaction = Factions.PilotsFederation; + relevantBond = true; + } + + if (current_factions != null && !relevantBond) { + // If we have local factions, and it ain't thargoid bonds see if the bonds were + // useful in the current system + if (current_factions.Find(x => string.Compare(x.Name, faction, true) == 0) != null) { + relevantBond = true; + } else { + transactions.AddIncomplete(new Vouchers(), + string.Format("Vouchers for \"{0}\" had no effect in \"{1}\" since said " + + "faction is not present there", faction, context.CurrentSystem), e + ); + } + } + + if (!relevantBond) { + continue; + } + + var voucher = new Vouchers(entry) { + System = context.CurrentSystem, + Station = context.CurrentStation, + Faction = relevantFaction, + ControllingFaction = context.ControllingFaction, + IsLegacy = context.IsLegacy, + }; + + if (options.FilterDoubleRedeemVouchers) { + // To filter out doubly redeemed vouchers, find another redeem voucher + // event that happened in the same system, same total sum, and also the + // same faction. If there is one, filter this one out. + var doubledEntry = transactions + .OfType() + .Where(x => x.TotalSum == voucher.TotalSum && + x.System == voucher.System && + x.Faction == voucher.Faction) + .ToList() + ; + if (doubledEntry.Count > 0) { + transactions.AddIncomplete( + voucher, + string.Format("A doubled redeem voucher for {0} valued {1} was detected", + voucher.Faction, Credits.FormatMillions(voucher.TotalSum)), + e); + return; + } + } + transactions.Add(voucher); + } + } +} \ No newline at end of file diff --git a/EDPlayerJournal/BGS/TransactionParser.cs b/EDPlayerJournal/BGS/TransactionParser.cs index dced6ed..1577b18 100644 --- a/EDPlayerJournal/BGS/TransactionParser.cs +++ b/EDPlayerJournal/BGS/TransactionParser.cs @@ -28,6 +28,14 @@ public class TransactionParserOptions { /// Whether we should ignore things done for the fleet carrier faction. /// public bool IgnoreFleetCarrierFaction { get; set; } = true; + + /// + /// Filter out double redeem vouchers that happen when you redeem a specific + /// voucher, and then redeem the rest of your vouchers (say from a KWS) in + /// bulk. The bulk redeem will also list the first voucher redeem again in + /// its bulk list. + /// + public bool FilterDoubleRedeemVouchers { get; set; } = true; } public class TransactionList : List { @@ -422,63 +430,6 @@ internal class MissionFailedParser : ITransactionParserPart { } } -internal class RedeemVoucherParser : ITransactionParserPart { - public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { - RedeemVoucherEntry? entry = e as RedeemVoucherEntry; - if (entry == null) { - throw new NotImplementedException(); - } - - if (context.CurrentSystem == null) { - transactions.AddIncomplete(new Vouchers(), - "Could not find out where the vouchers were redeemed", e - ); - return; - } - - List? current_factions = context.GetFactions(context.CurrentSystem); - if (current_factions == null) { - transactions.AddIncomplete(new Vouchers(), - "Current system factions are unknown, so vouchers were ineffective", e); - } - - foreach (string faction in entry.Factions) { - bool relevantBond = false; - string relevantFaction = faction; - - if (string.Compare(faction, Factions.PilotsFederationVouchers) == 0) { - // Target faction is pilots' federation, so we assume thargoid bonks - // Also assign this combat bond to the Pilots Federation - relevantFaction = Factions.PilotsFederation; - relevantBond = true; - } - - if (current_factions != null && !relevantBond) { - // If we have local factions, and it ain't thargoid bonds see if the bonds were - // useful in the current system - if (current_factions.Find(x => string.Compare(x.Name, faction, true) == 0) != null) { - relevantBond = true; - } else { - transactions.AddIncomplete(new Vouchers(), - string.Format("Vouchers for \"{0}\" had no effect in \"{1}\" since said " + - "faction is not present there", faction, context.CurrentSystem), e - ); - } - } - - if (relevantBond) { - transactions.Add(new Vouchers(entry) { - System = context.CurrentSystem, - Station = context.CurrentStation, - Faction = relevantFaction, - ControllingFaction = context.ControllingFaction, - IsLegacy = context.IsLegacy, - }); - } - } - } -} - internal class SellMicroResourcesParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry; diff --git a/EDPlayerJournalTests/double-vouchers-2.txt b/EDPlayerJournalTests/double-vouchers-2.txt new file mode 100644 index 0000000..c30fc1c --- /dev/null +++ b/EDPlayerJournalTests/double-vouchers-2.txt @@ -0,0 +1,7 @@ +{"timestamp":"2024-04-27T13:27:08Z","event":"Fileheader","part":1,"language":"English/UK","Odyssey":true,"gameversion":"4.0.0.1803","build":"r301470/r0 "} +{"timestamp":"2024-04-27T13:27:34Z","event":"Commander","FID":"F9183790","Name":"Jeremaya"} +{"timestamp":"2024-04-27T15:06:31Z","event":"FSDJump","Taxi":false,"Multicrew":false,"StarSystem":"HIP 3318","SystemAddress":525890177387,"StarPos":[50.21875,-190.6875,37.5],"SystemAllegiance":"Empire","SystemEconomy":"$economy_Refinery;","SystemEconomy_Localised":"Refinery","SystemSecondEconomy":"$economy_Extraction;","SystemSecondEconomy_Localised":"Extraction","SystemGovernment":"$government_Patronage;","SystemGovernment_Localised":"Patronage","SystemSecurity":"$SYSTEM_SECURITY_high;","SystemSecurity_Localised":"High Security","Population":239484,"Body":"HIP 3318 A","BodyID":2,"BodyType":"Star","JumpDist":27.495,"FuelUsed":3.115176,"FuelLevel":13.228082,"Factions":[{"Name":"HIP 3318 Autocracy","FactionState":"None","Government":"Dictatorship","Influence":0.119192,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Chakho Gold Galactic Limited","FactionState":"None","Government":"Corporate","Influence":0.09798,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"HIP 3318 Interstellar","FactionState":"None","Government":"Corporate","Influence":0.075758,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"HIP 3318 Values Party","FactionState":"None","Government":"Democracy","Influence":0.032323,"Allegiance":"Independent","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Nationalists of HIP 3318","FactionState":"None","Government":"Dictatorship","Influence":0.035354,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Nova Paresa","FactionState":"Boom","Government":"Patronage","Influence":0.434343,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","SquadronFaction":true,"MyReputation":100.0,"PendingStates":[{"State":"Expansion","Trend":0}]},{"Name":"Empire Consulate Ltd","FactionState":"None","Government":"Patronage","Influence":0.20505,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":94.474998}],"SystemFaction":{"Name":"Nova Paresa","FactionState":"Boom"}} +{"timestamp":"2024-04-27T15:12:23Z","event":"ApproachSettlement","Name":"Koh Biological Installation","MarketID":3803792128,"StationFaction":{"Name":"Nova Paresa","FactionState":"Boom"},"StationGovernment":"$government_Patronage;","StationGovernment_Localised":"Patronage","StationAllegiance":"Empire","StationServices":["dock","autodock","commodities","contacts","exploration","missions","refuel","repair","engineer","missionsgenerated","flightcontroller","stationoperations","searchrescue","stationMenu"],"StationEconomy":"$economy_HighTech;","StationEconomy_Localised":"High Tech","StationEconomies":[{"Name":"$economy_HighTech;","Name_Localised":"High Tech","Proportion":1.0}],"SystemAddress":525890177387,"BodyID":26,"BodyName":"HIP 3318 D 3","Latitude":-0.893061,"Longitude":-62.928345} +{"timestamp":"2024-04-27T15:14:08Z","event":"Docked","StationName":"Koh Biological Installation","StationType":"OnFootSettlement","Taxi":false,"Multicrew":false,"StarSystem":"HIP 3318","SystemAddress":525890177387,"MarketID":3803792128,"StationFaction":{"Name":"Nova Paresa","FactionState":"Boom"},"StationGovernment":"$government_Patronage;","StationGovernment_Localised":"Patronage","StationAllegiance":"Empire","StationServices":["dock","autodock","commodities","contacts","exploration","missions","refuel","repair","engineer","missionsgenerated","flightcontroller","stationoperations","searchrescue","stationMenu"],"StationEconomy":"$economy_HighTech;","StationEconomy_Localised":"High Tech","StationEconomies":[{"Name":"$economy_HighTech;","Name_Localised":"High Tech","Proportion":1.0}],"DistFromStarLS":11972.63409,"LandingPads":{"Small":1,"Medium":0,"Large":1}} +{"timestamp":"2024-04-27T15:15:10Z","event":"RedeemVoucher","Type":"bounty","Amount":9449329,"Factions":[{"Faction":"Nova Paresa","Amount":9449329}]} +{"timestamp":"2024-04-27T15:15:51Z","event":"RedeemVoucher","Type":"bounty","Amount":18780130,"Factions":[{"Faction":"","Amount":224449},{"Faction":"","Amount":730880},{"Faction":"","Amount":1272764},{"Faction":"","Amount":580384},{"Faction":"","Amount":10180261},{"Faction":"","Amount":1413153},{"Faction":"","Amount":1365934},{"Faction":"","Amount":202193},{"Faction":"Nova Paresa","Amount":9449329},{"Faction":"","Amount":104412},{"Faction":"","Amount":2453443},{"Faction":"","Amount":252257}]} \ No newline at end of file