diff --git a/EDPlayerJournal/BGS/MissionFailed.cs b/EDPlayerJournal/BGS/MissionFailed.cs index a9bb672..922c656 100644 --- a/EDPlayerJournal/BGS/MissionFailed.cs +++ b/EDPlayerJournal/BGS/MissionFailed.cs @@ -9,8 +9,11 @@ public class MissionFailed : Transaction { public MissionFailed() { } public MissionFailed(MissionAcceptedEntry accepted) { + if (accepted.Mission == null) { + throw new Exception("Mission cannot be null"); + } Accepted = accepted; - Faction = accepted.Faction; + Faction = accepted.Mission.Faction; } public override int CompareTo(Transaction? other) { diff --git a/EDPlayerJournal/BGS/Report.cs b/EDPlayerJournal/BGS/Report.cs index d321f42..6017e20 100644 --- a/EDPlayerJournal/BGS/Report.cs +++ b/EDPlayerJournal/BGS/Report.cs @@ -401,7 +401,11 @@ public class Report { continue; } - ulong id = accepted.MissionID; + if (accepted.Mission == null) { + continue; + } + + ulong id = accepted.Mission.MissionID; if (!acceptedMissions.ContainsKey(id)) { acceptedMissions[id] = accepted; @@ -429,23 +433,27 @@ public class Report { continue; } + if (accepted.Mission == null) { + continue; + } + if (!acceptedSystems.TryGetValue(failed.MissionID, out accepted_address)) { OnLog?.Invoke(string.Format( - "Unable to figure out in which system mission \"{0}\" was accepted.", accepted.Name + "Unable to figure out in which system mission \"{0}\" was accepted.", accepted.Mission.Name )); continue; } if (!systems.TryGetValue(accepted_address, out accepted_system)) { OnLog?.Invoke(string.Format( - "Unable to figure out in which system mission \"{0}\" was accepted.", accepted.Name + "Unable to figure out in which system mission \"{0}\" was accepted.", accepted.Mission.Name )); continue; } if (!acceptedStations.TryGetValue(failed.MissionID, out accepted_station)) { OnLog?.Invoke(string.Format( - "Unable to figure out in which station mission \"{0}\" was accepted.", accepted.Name + "Unable to figure out in which station mission \"{0}\" was accepted.", accepted.Mission.Name )); continue; } @@ -454,7 +462,7 @@ public class Report { Failed = failed, System = accepted_system, Station = accepted_station, - Faction = accepted.Faction, + Faction = accepted.Mission.Faction, SystemAddress = accepted_address, }); diff --git a/EDPlayerJournal/BGS/TransactionParser.cs b/EDPlayerJournal/BGS/TransactionParser.cs index bf8effc..d93450c 100644 --- a/EDPlayerJournal/BGS/TransactionParser.cs +++ b/EDPlayerJournal/BGS/TransactionParser.cs @@ -53,7 +53,11 @@ internal class TransactionParserContext { throw new Exception("Mission accepted without knowing where."); } - AcceptedMissions.TryAdd(accepted.MissionID, accepted); + if (accepted.Mission == null) { + throw new Exception("Mission is null"); + } + + AcceptedMissions.TryAdd(accepted.Mission.MissionID, accepted); Location location = new() { StarSystem = CurrentSystem, @@ -61,7 +65,7 @@ internal class TransactionParserContext { Station = (CurrentStation ?? ""), }; - AcceptedMissionLocation.TryAdd(accepted.MissionID, location); + AcceptedMissionLocation.TryAdd(accepted.Mission.MissionID, location); } } @@ -408,7 +412,7 @@ internal class MissionFailedParser : TransactionParserPart { transactions.Add(new MissionFailed() { Accepted = accepted, - Faction = accepted.Faction, + Faction = accepted.Mission?.Faction, Failed = entry, Station = accepted_location.Station, System = accepted_location.StarSystem, diff --git a/EDPlayerJournal/EDPlayerJournal.csproj b/EDPlayerJournal/EDPlayerJournal.csproj index 0078fba..ac784af 100644 --- a/EDPlayerJournal/EDPlayerJournal.csproj +++ b/EDPlayerJournal/EDPlayerJournal.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/EDPlayerJournal/Entries/Entry.cs b/EDPlayerJournal/Entries/Entry.cs index 36e27bd..e3c1c42 100644 --- a/EDPlayerJournal/Entries/Entry.cs +++ b/EDPlayerJournal/Entries/Entry.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using System.Runtime.InteropServices; namespace EDPlayerJournal.Entries; @@ -55,11 +56,14 @@ public class Entry { } public static Entry? Parse(string journalline) { - var json = JObject.Parse(journalline); - if (json == null) { - return null; + using (JsonReader reader = new JsonTextReader(new StringReader(journalline))) { + reader.DateParseHandling = DateParseHandling.None; + var json = JObject.Load(reader); + if (json == null) { + return null; + } + return Parse(json); } - return Parse(json); } public static Entry? Parse(JObject json) { diff --git a/EDPlayerJournal/Entries/MissionAcceptedEntry.cs b/EDPlayerJournal/Entries/MissionAcceptedEntry.cs index 1b44174..d27e1ec 100644 --- a/EDPlayerJournal/Entries/MissionAcceptedEntry.cs +++ b/EDPlayerJournal/Entries/MissionAcceptedEntry.cs @@ -1,22 +1,9 @@ namespace EDPlayerJournal.Entries; + public class MissionAcceptedEntry : Entry { - public string? Faction { get; set; } - public string? TargetFaction { get; set; } - public string? Name { get; set; } - public string? LocalisedName { get; set; } - public string? LocalisedTargetType { get; set; } - public int KillCount { get; set; } - public ulong MissionID { get; set; } - public long Reward { get; set; } + public Mission? Mission { get; set; } protected override void Initialise() { - Faction = JSON.Value("Faction"); - TargetFaction = JSON.Value("TargetFaction"); - Name = JSON.Value("Name"); - LocalisedName = JSON.Value("LocalisedName"); - LocalisedTargetType = JSON.Value("TargetType_Localised"); - KillCount = JSON.Value("KillCount") ?? 0; - MissionID = JSON.Value("MissionID") ?? 0; - Reward = JSON.Value("Reward") ?? 0; + Mission = Mission.FromMissionAccepted(JSON); } } diff --git a/EDPlayerJournal/Mission.cs b/EDPlayerJournal/Mission.cs new file mode 100644 index 0000000..f74ea98 --- /dev/null +++ b/EDPlayerJournal/Mission.cs @@ -0,0 +1,189 @@ +using Newtonsoft.Json.Linq; + +namespace EDPlayerJournal; + +public class Mission : IComparable { + public ulong MissionID { get; set; } = 0; + + /// + /// Name of the mission, in machine readable format. + /// + public string? Name { get; set; } + + /// + /// Localised, human readable mission name. + /// + public string? LocalisedName { get; set; } + + /// + /// Target of the mission. Optional. + /// + public string? Target { get; set; } + + /// + /// Target of the mission as a localised human readable string. + /// + public string? TargetLocalised { get; set; } + + /// + /// Target system of the mission + /// + public string? DestinationSystem { get; set; } + + /// + /// Destination station. + /// + public string? DestinationStation { get; set; } + + /// + /// Destination settlement + /// + public string? DestinationSettlement { get; set; } + + /// + /// In case of redirection, these values denote the new system. + /// + public string? NewDestinationSystem { get; set; } + + /// + /// In case of redirection, these values denote the new station. + /// + public string? NewDestinationStation { get; set; } + + /// + /// Faction offering the mission. + /// + public string? Faction { get; set; } + + /// + /// Target faction (for example for courier missions). + /// + public string? TargetFaction { get; set; } + + /// + /// Whether the mission is a wing message. + /// + public bool Wing { get; set; } = false; + + /// + /// Expiry date for the mission. + /// + public string? Expiry { get; set; } + + /// + /// Influence reward offered. This is for accepting missions only, see the + /// mission effects for actual effects once the mission is complete. + /// + public string? Influence { get; set; } + + /// + /// Reputation reward offered. + /// + public string? Reputation { get; set; } + + /// + /// Number of kills required for massacre missions. + /// + public ulong? KillCount { get; set; } + + /// + /// Monatery reward offered for the mission. Optional, as donate missions don't give + /// a monatery reward. + /// + public ulong? Reward { get; set; } + + /// + /// Amount donated for donation missions, optional. If this is null, then + /// the mission was not a donation mission. + /// + public ulong? Donation { get; set; } + + /// + /// Actual amount donated. + /// + public ulong? Donated { get; set; } + + /// + /// Commodity delivered, or donated. Optional, if this is null, then no + /// commodity was donated or delivered. + /// + public string? Commodity { get; set; } + + /// + /// Amount of the commodity donated or delivered. Optional. + /// + public ulong? Count { get; set; } + + /// + /// How many passengers are being transported. + /// + public ulong? PassengerCount { get; set; } + + /// + /// If the passengers are VIPs. + /// + public bool? PassengerVIPs { get; set; } + + /// + /// If the passengers are wanted. + /// + public bool? PassengerWanted { get; set; } + + /// + /// What sort of passengers are being transported. + /// + public string? PassengerType { get; set; } + + public int CompareTo(Mission? other) { + if (other == null) { + return 1; + } + + return MissionID.CompareTo(other.MissionID); + } + + private static Mission FromJSON(JObject o) { + Mission mission = new Mission(); + + mission.MissionID = o.Value("MissionID") ?? 0; + + mission.Reputation = o.Value("Reputation"); + mission.Influence = o.Value("Influence"); + + mission.DestinationSystem = o.Value("DestinationSystem"); + mission.DestinationSettlement = o.Value("DestinationSettlement"); + mission.DestinationStation = o.Value("DestinationStation"); + + mission.NewDestinationSystem = o.Value("NewDestinationSystem"); + mission.NewDestinationStation = o.Value("NewDestinationSystem"); + + mission.Reward = o.Value("Reward"); + + mission.Target = o.Value("Target"); + mission.TargetLocalised = o.Value("Target_Localised"); + + mission.Expiry = o.Value("Expiry")?.ToString(); + mission.Wing = o.Value("Wing") ?? false; + + mission.Name = o.Value("Name"); + mission.LocalisedName = o.Value("LocalisedName"); + + mission.Faction = o.Value("Faction"); + + mission.Donation = o.Value("Donation"); + mission.Donated = o.Value("Donated"); + + mission.PassengerCount = o.Value("PassengerCount"); + mission.PassengerVIPs = o.Value("PassengerVIPs"); + mission.PassengerWanted = o.Value("PassengerWanted"); + mission.PassengerType = o.Value("PassengerType"); + + mission.KillCount = o.Value("KillCount"); + + return mission; + } + + public static Mission FromMissionAccepted(JObject o) { + return FromJSON(o); + } +} diff --git a/EDPlayerJournalTests/EDPlayerJournalTests.csproj b/EDPlayerJournalTests/EDPlayerJournalTests.csproj index a357822..2f36a27 100644 --- a/EDPlayerJournalTests/EDPlayerJournalTests.csproj +++ b/EDPlayerJournalTests/EDPlayerJournalTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 enable enable diff --git a/EDPlayerJournalTests/MissionTest.cs b/EDPlayerJournalTests/MissionTest.cs new file mode 100644 index 0000000..5ff35e6 --- /dev/null +++ b/EDPlayerJournalTests/MissionTest.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using EDPlayerJournal.Entries; + +namespace EDPlayerJournalTests; + +[TestClass] +public class MissionTest { + + [TestMethod] + public void TestMissionAccepted() { + string altruism = /*lang=json,strict*/ """{ "timestamp":"2022-11-23T08:05:54Z", "event":"MissionAccepted", "Faction":"HIP 6182 Federal Inc", "Name":"Mission_AltruismCredits", "LocalisedName":"Donate 1,000,000 Cr to the cause", "Donation":"1000000", "Expiry":"2022-11-23T11:50:52Z", "Wing":false, "Influence":"++", "Reputation":"++", "MissionID":901601358 }"""; + + Entry? entry = Entry.Parse(altruism); + + Assert.IsNotNull(entry); + Assert.IsInstanceOfType(entry, typeof(MissionAcceptedEntry)); + + MissionAcceptedEntry? accepted = entry as MissionAcceptedEntry; + + Assert.IsNotNull(accepted); + Assert.IsNotNull(accepted.Mission); + + Assert.AreEqual(accepted.Mission.MissionID, (ulong)901601358); + Assert.AreEqual(accepted.Mission.Faction, "HIP 6182 Federal Inc"); + Assert.AreEqual(accepted.Mission.Name, "Mission_AltruismCredits"); + Assert.AreEqual(accepted.Mission.LocalisedName, "Donate 1,000,000 Cr to the cause"); + Assert.AreEqual(accepted.Mission.Donation, (ulong)1000000); + Assert.AreEqual(accepted.Mission.Expiry, "2022-11-23T11:50:52Z"); + Assert.AreEqual(accepted.Mission.Wing, false); + Assert.AreEqual(accepted.Mission.Reputation, "++"); + Assert.AreEqual(accepted.Mission.Influence, "++"); + } +}