move journal handling to a library
This commit is contained in:
		
							parent
							
								
									1abeb7af93
								
							
						
					
					
						commit
						ee86365e27
					
				| @ -1,11 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Configuration; | ||||
| using System.Data; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using System.Windows; | ||||
| using NonaBGS.Journal; | ||||
| using System.Windows; | ||||
| 
 | ||||
| namespace NonaBGS | ||||
| { | ||||
|  | ||||
| @ -1,10 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Globalization; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class Cartographics : LogEntry { | ||||
|  | ||||
| @ -1,10 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
| namespace NonaBGS.BGS { | ||||
|     public class CombatZone { | ||||
|         private int level; | ||||
|     } | ||||
|  | ||||
| @ -1,10 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
| namespace NonaBGS.BGS { | ||||
|     public interface IDiscordLogGenerator { | ||||
|         string GenerateDiscordLog(Report report); | ||||
|     } | ||||
|  | ||||
| @ -1,9 +1,7 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class LogEntry : IComparable<LogEntry> { | ||||
|  | ||||
| @ -1,10 +1,5 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using System.Text; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class MissionCompleted : LogEntry { | ||||
|  | ||||
| @ -2,9 +2,7 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Globalization; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class NonaDiscordLog : IDiscordLogGenerator { | ||||
|  | ||||
| @ -1,11 +1,7 @@ | ||||
| using System; | ||||
| using System.ComponentModel; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Specialized; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class Report { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| using System.Linq; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class SellMicroResources : LogEntry { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| using System.Linq; | ||||
| using System.Globalization; | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| namespace NonaBGS.BGS { | ||||
|     public class Vouchers : LogEntry { | ||||
|  | ||||
| @ -1,18 +0,0 @@ | ||||
| using System.Globalization; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class Credits { | ||||
|         public static string FormatCredits(int amount) { | ||||
|             var format = CultureInfo.CurrentCulture.NumberFormat; | ||||
|             if ((amount % 1000000) == 0) { | ||||
|                 amount /= 1000000; | ||||
|                 return string.Format("{0}M CR", amount.ToString(format)); | ||||
|             } else if ((amount % 1000) == 0) { | ||||
|                 amount /= 1000; | ||||
|                 return string.Format("{0}K CR", amount.ToString(format)); | ||||
|             } | ||||
| 
 | ||||
|             return string.Format("{0} CR", amount.ToString(format)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class DockedEntry : Entry { | ||||
|         public string StationName { | ||||
|             get { return JSON.GetValue("StationName").ToString(); } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class EliteDangerous { | ||||
|         /// <summary> | ||||
|         /// The ingame universe is 1286 years in the future. This is needed to convert dates | ||||
|         /// and times to ingame dates and times | ||||
|         /// </summary> | ||||
|         public static readonly int YearOffset = 1286; | ||||
|     } | ||||
| } | ||||
| @ -1,95 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     /// <summary> | ||||
|     /// Base class for a single entry within the player journal. If no specific sub class is available | ||||
|     /// this class gives basic information, such as EventType or date when it happened. It also allows | ||||
|     /// base classes access to the underlying JSON object. Base classes should be named after the event | ||||
|     /// type that they map + Entry. So "FSDJump" event is handled by FSDJumpEntry. | ||||
|     /// </summary> | ||||
|     public class Entry { | ||||
|         private static readonly Dictionary<string, Type> classes = new Dictionary<string, Type> { | ||||
|             { Events.Docked, typeof(DockedEntry) }, | ||||
|             { Events.FSDJump, typeof(FSDJumpEntry) }, | ||||
|             { Events.MissionCompleted, typeof(MissionCompletedEntry) }, | ||||
|             { Events.MultiSellExplorationData, typeof(MultiSellExplorationDataEntry) }, | ||||
|             { Events.MarketSell, typeof(MarketSellEntry) }, | ||||
|             { Events.SellMicroResources, typeof(SellMicroResourcesEntry) }, | ||||
|             { Events.RedeemVoucher, typeof(RedeemVoucherEntry) }, | ||||
|         }; | ||||
| 
 | ||||
|         private string eventtype = null; | ||||
|         private string datetime = null; | ||||
|         private DateTime timestamp; | ||||
| 
 | ||||
|         private string jsonstr = null; | ||||
|         protected JObject json = null; | ||||
| 
 | ||||
|         public Entry() { | ||||
|         } | ||||
| 
 | ||||
|         public static Entry Parse(string journalline) { | ||||
|             var json = JObject.Parse(journalline); | ||||
|             return Parse(json); | ||||
|         } | ||||
| 
 | ||||
|         public static Entry Parse(JObject json) { | ||||
|             string event_name = json.GetValue("event").ToString(); | ||||
| 
 | ||||
|             classes.TryGetValue(event_name, out Type classhandler); | ||||
|             if (classhandler == null) { | ||||
|                 classhandler = typeof(Entry); | ||||
|             } | ||||
| 
 | ||||
|             var obj = (Entry)Activator.CreateInstance(classhandler); | ||||
|             obj.InternalInitialise(json); | ||||
|             obj.Initialise(); | ||||
|             return obj; | ||||
|         } | ||||
| 
 | ||||
|         private void InternalInitialise(JObject jobject) { | ||||
|             this.json = jobject; | ||||
|             this.jsonstr = json.ToString(formatting: Formatting.None); | ||||
| 
 | ||||
|             this.eventtype = json.GetValue("event").ToString(); | ||||
|             this.datetime = json.GetValue("timestamp").ToString(); | ||||
|             this.timestamp = DateTime.Parse(this.datetime); | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void Initialise() { | ||||
|         } | ||||
| 
 | ||||
|         public bool Is(string eventtype) { | ||||
|             if (eventtype == null || this.eventtype == null) { | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             return String.Equals(this.eventtype, eventtype, StringComparison.OrdinalIgnoreCase); | ||||
|         } | ||||
| 
 | ||||
|         public string Event { | ||||
|             get { return eventtype; } | ||||
|         } | ||||
| 
 | ||||
|         public DateTime Timestamp { | ||||
|             get { return timestamp; } | ||||
|         } | ||||
| 
 | ||||
|         public JObject JSON { | ||||
|             get { return this.json; } | ||||
|         } | ||||
| 
 | ||||
|         public override string ToString() { | ||||
|             if (json == null) { | ||||
|                 return ""; | ||||
|             } | ||||
|             return json.ToString(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class Events { | ||||
|         public static readonly string MissionCompleted = "MissionCompleted"; | ||||
|         public static readonly string Docked = "Docked"; | ||||
|         public static readonly string FSDJump = "FSDJump"; | ||||
|         public static readonly string MultiSellExplorationData = "MultiSellExplorationData"; | ||||
|         public static readonly string MarketSell = "MarketSell"; | ||||
|         public static readonly string SellMicroResources = "SellMicroResources"; | ||||
|         public static readonly string RedeemVoucher = "RedeemVoucher"; | ||||
|     } | ||||
| } | ||||
| @ -1,23 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using Newtonsoft.Json.Linq; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class FSDJumpEntry : Entry { | ||||
|         private string starsystem = null; | ||||
|         private string systemfaction = null; | ||||
|         protected override void Initialise() { | ||||
|             starsystem = JSON.Value<string>("StarSystem"); | ||||
|             var faction = JSON.Value<JObject>("SystemFaction"); | ||||
|             if (faction != null) { | ||||
|                 systemfaction = faction.Value<string>("Name"); | ||||
|             } | ||||
|         } | ||||
|         public string StarSystem => starsystem; | ||||
| 
 | ||||
|         public string SystemFaction => systemfaction; | ||||
|     } | ||||
| } | ||||
| @ -1,11 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class JournalException : Exception { | ||||
|         public JournalException(string message) : base(message) { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,119 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
| using System.IO; | ||||
| using System.Globalization; | ||||
| 
 | ||||
| namespace NonaBGS.Journal | ||||
| { | ||||
|     public class JournalFile : IComparable<JournalFile> | ||||
|     { | ||||
|         private string fullpath = null; | ||||
|         private string part = null; | ||||
|         private int intpart = 0; | ||||
|         private DateTime datetime; | ||||
|         private DateTime normalised; | ||||
|         private List<Entry> entries = new List<Entry>(); | ||||
| 
 | ||||
|         private static Regex fileregex = new Regex("Journal\\.(\\d+)\\.(\\d+)\\.log"); | ||||
|         private static string iso8601 = "yyyyMMddTHHmmss"; | ||||
|         private static string iso8601_notime = "yyyyMMdd"; | ||||
| 
 | ||||
|         public static bool VerifyFile(string path) { | ||||
|             string filename = Path.GetFileName(path); | ||||
| 
 | ||||
|             var matches = fileregex.Matches(filename); | ||||
|             return matches.Count != 0; | ||||
|         } | ||||
| 
 | ||||
|         private void SetFilename(string path) { | ||||
|             string filename = Path.GetFileName(path); | ||||
|             if (!File.Exists(path) || filename == null) { | ||||
|                 throw new JournalException(string.Format("Invalid journal file: {0}", filename)); | ||||
|             } | ||||
| 
 | ||||
|             var matches = fileregex.Matches(filename); | ||||
|             if (matches.Count < 1) { | ||||
|                 throw new JournalException(string.Format("Invalid journal file: {0}", filename)); | ||||
|             } | ||||
| 
 | ||||
|             this.fullpath = path; | ||||
|             this.part = matches[0].Groups[2].ToString(); | ||||
|             this.intpart = int.Parse(part); | ||||
|             // The ISO is not quite correct on journal filenames, so build | ||||
|             // a proper ISO 8601 date time stamp out of it. | ||||
|             var date = new StringBuilder(); | ||||
|             date.Append("20"); // Add the missing century in front. | ||||
|             date.Append(matches[0].Groups[1].ToString()); | ||||
|             date.Insert(8, "T"); // Add the "T" separating date and time | ||||
|             this.datetime = DateTime.ParseExact(date.ToString(), iso8601, CultureInfo.InvariantCulture); | ||||
|             this.normalised = DateTime.Parse(this.datetime.ToShortDateString()); | ||||
|         } | ||||
| 
 | ||||
|         public int CompareTo(JournalFile other) { | ||||
|             if (datetime == null || other.datetime == null) { | ||||
|                 return 0; | ||||
|             } | ||||
|             var comp = DateTime.Compare(datetime, other.datetime); | ||||
|             if (comp == 0) { | ||||
|                 /* If we have the exact same datetime we compare by parts. | ||||
|                  */ | ||||
|                 return intpart - other.intpart; | ||||
|             } else { | ||||
|                 return comp; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public JournalFile(string path) { | ||||
|             SetFilename(path); | ||||
|         } | ||||
| 
 | ||||
|         public DateTime Timestamp { | ||||
|             get { return datetime; } | ||||
|         } | ||||
| 
 | ||||
|         public DateTime NormalisedTimestamp { | ||||
|             get { return normalised; } | ||||
|         } | ||||
| 
 | ||||
|         public int Part { | ||||
|             get { return intpart; } | ||||
|         } | ||||
| 
 | ||||
|         public IEnumerable<Entry> Entries { | ||||
|             get {  | ||||
|                 if (entries == null || entries.Count == 0) { | ||||
|                     try { | ||||
|                         LoadEntries(); | ||||
|                     } catch (IOException) { | ||||
|                         entries = new List<Entry>(); | ||||
|                     } | ||||
|                 } | ||||
|                 return entries;  | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void LoadEntries() { | ||||
|             List<string> lines = new List<string>(); | ||||
| 
 | ||||
|             /* This needs to be done this way, otherwise, if the game is still running the journal files cannot | ||||
|              * be accessed. And it is very much convenient to generate logs while the game is still running. | ||||
|              */ | ||||
|             using (var fs = new FileStream(this.fullpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { | ||||
|                 using (var sr = new StreamReader(fs, Encoding.UTF8)) { | ||||
|                     string line = null; | ||||
|                     while ((line = sr.ReadLine()) != null) { | ||||
|                         lines.Add(line); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             entries.Clear(); | ||||
|             foreach(var line in lines) { | ||||
|                 Entry entry = Entry.Parse(line); | ||||
|                 entries.Add(entry); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,87 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using NonaBGS.Journal; | ||||
| using System.IO; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class JournalStream { | ||||
|         private PlayerJournal journal = null; | ||||
|         private FileSystemWatcher watcher = null; | ||||
| 
 | ||||
|         private Dictionary<string, StreamReader> streams = new Dictionary<string, StreamReader>(); | ||||
| 
 | ||||
|         public delegate void NewJournalEntryDelegate(Entry entry); | ||||
| 
 | ||||
|         public event NewJournalEntryDelegate NewJournalEntry; | ||||
| 
 | ||||
|         public PlayerJournal Journal { | ||||
|             get => journal; | ||||
|             set => journal = value; | ||||
|         } | ||||
| 
 | ||||
|         public JournalStream() { | ||||
|         } | ||||
| 
 | ||||
|         public JournalStream(PlayerJournal journal) { | ||||
|             this.journal = journal; | ||||
|             Open(); | ||||
|         } | ||||
| 
 | ||||
|         public void Open() { | ||||
|             if (watcher != null) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             watcher = new FileSystemWatcher(journal.Location); | ||||
| 
 | ||||
|             watcher.NotifyFilter = NotifyFilters.FileName | | ||||
|                 NotifyFilters.LastWrite | | ||||
|                 NotifyFilters.Size; | ||||
| 
 | ||||
|             watcher.Changed += Watcher_Changed; | ||||
|             watcher.Created += Watcher_Created; | ||||
| 
 | ||||
|             watcher.Filter = "*.log"; | ||||
|             watcher.EnableRaisingEvents = true; | ||||
|         } | ||||
| 
 | ||||
|         public void Close() { | ||||
|             if (watcher != null) { | ||||
|                 watcher.EnableRaisingEvents = false; | ||||
|             } | ||||
|             watcher = null; | ||||
|             streams.Clear(); | ||||
|         } | ||||
| 
 | ||||
|         private void Watcher_Created(object sender, FileSystemEventArgs e) { | ||||
|             if (!streams.ContainsKey(e.FullPath) && JournalFile.VerifyFile(e.FullPath)) { | ||||
|                 streams[e.FullPath] = new StreamReader(e.FullPath); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void Watcher_Changed(object sender, FileSystemEventArgs e) { | ||||
|             if (!streams.ContainsKey(e.FullPath) && JournalFile.VerifyFile(e.FullPath)) { | ||||
|                 var filestream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); | ||||
|                 streams[e.FullPath] = new StreamReader(filestream); | ||||
|             } | ||||
| 
 | ||||
|             var stream = streams[e.FullPath]; | ||||
|             if (stream == null) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             string line; | ||||
| 
 | ||||
|             while ((line = stream.ReadLine()) != null) { | ||||
|                 try { | ||||
|                     Entry entry = Entry.Parse(line); | ||||
|                     NewJournalEntry?.Invoke(entry); | ||||
|                 } catch (Exception) { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class MarketSellEntry : Entry { | ||||
|         private int totalsale = 0; | ||||
| 
 | ||||
|         protected override void Initialise() { | ||||
|             totalsale = JSON.Value<int>("TotalSale"); | ||||
|         } | ||||
| 
 | ||||
|         public int TotalSale => totalsale; | ||||
|     } | ||||
| } | ||||
| @ -1,162 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class MissionCompletedEntry : Entry { | ||||
|         private Dictionary<string, string> influences = new Dictionary<string, string>(); | ||||
|         private string readable_name = null; | ||||
|         private bool readable_name_generated = false; | ||||
|         private string name = null; | ||||
|         private string commodity = null; | ||||
|         private int count = 0; | ||||
|         private int donated = 0; | ||||
| 
 | ||||
|         /* TODO: make this a file at some point for easier editing. | ||||
|          */ | ||||
|         private static readonly Dictionary<string, string> humanreadable = new Dictionary<string, string> { | ||||
|             { "Mission_AltruismCredits_name", "Donate Credits" }, | ||||
|             { "Mission_AltruismCredits_Bust_name", "Donate Credits (Bust)" }, | ||||
|             { "Mission_Collect_name", "Provide" }, | ||||
|             { "Mission_Collect_Bust_name", "Provide (Bust)" }, | ||||
|             { "Mission_Collect_CivilLiberty_name", "Provide (Civil Liberty)" }, | ||||
|             { "Mission_Collect_Famine_name", "Provide (Famine)" }, | ||||
|             { "Mission_Courier_Democracy_name", "Courier (Democracy)" }, | ||||
|             { "Mission_Courier_Elections_name", "Courier (Elections)" }, | ||||
|             { "Mission_Courier_Famine_name", "Courier (Famine)" }, | ||||
|             { "Mission_Courier_Lockdown_name", "Courier (Lockdown)" }, | ||||
|             { "Mission_Courier_name", "Courier" }, | ||||
|             { "Mission_Courier_RankEmp_name", "Courier (Empire)" }, | ||||
|             { "Mission_Delivery_Boom_name", "Delivery (Boom)" }, | ||||
|             { "Mission_Delivery_Retreat_name", "Delivery (Retreat)" }, | ||||
|             { "Mission_Delivery_name", "Delivery" }, | ||||
|             { "Mission_Delivery_Agriculture_name", "Delivery (Agriculture)" }, | ||||
|             { "Mission_Delivery_RankEmp_name", "Delivery (Imperial Rank)" }, | ||||
|             { "Mission_HackMegaship_name", "Hack Megaship" }, | ||||
|             { "Mission_Hack_BLOPS_Boom_name", "Hack Megaship (Black Ops)" }, | ||||
|             { "Mission_MassacreWing_name", "Massacre (Wing)" }, | ||||
|             { "Mission_Massacre_RankEmp_name", "Massacre (Imperial Navy)" }, | ||||
|             { "Mission_OnFoot_Collect_MB_name", "On Foot Collection" }, | ||||
|             { "Mission_OnFoot_Onslaught_MB_name", "On Foot Onslaught" }, | ||||
|             { "Mission_OnFoot_Onslaught_Offline_MB_name", "On Foot Onslaught (Offline)" }, | ||||
|             { "Mission_OnFoot_RebootRestore_MB_name", "On Foot Reboot/Restore" }, | ||||
|             { "Mission_OnFoot_Reboot_MB_name", "On Foot Reboot" }, | ||||
|             { "Mission_OnFoot_Salvage_MB_name", "On Foot Salvage" }, | ||||
|             { "Mission_Rescue_Planet_name", "Planet Rescue" }, | ||||
|             { "Mission_Salvage_name", "Salvage" }, | ||||
|             { "MISSION_Salvage_CivilUnrest_name", "Salvage (Civil Unrest)" }, | ||||
|             { "MISSION_Salvage_Illegal_name", "Salvage (Illegal)" }, | ||||
|             { "MISSION_Salvage_Retreat_name", "Salvage (Retreat)" }, | ||||
|             { "MISSION_Salvage_Expansion_name", "Salvage (Expansion)" }, | ||||
|             { "Mission_Salvage_RankEmp_name", "Salvage (Imperial Navy)" }, | ||||
|             { "MISSION_Scan_name", "Scan" }, | ||||
|         }; | ||||
| 
 | ||||
|         protected override void Initialise() { | ||||
|             MakeHumanReadableName(); | ||||
|             name = JSON.Value<string>("Name"); | ||||
|             if (JSON.ContainsKey("Commodity_Localised")) { | ||||
|                 commodity = JSON.Value<string>("Commodity_Localised"); | ||||
|             } | ||||
|             if (JSON.ContainsKey("Count")) { | ||||
|                 count = JSON.Value<int>("Count"); | ||||
|             } | ||||
|             if (JSON.ContainsKey("Donated")) { | ||||
|                 donated = JSON.Value<int>("Donated"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public string Name => name; | ||||
|         public string Commodity => commodity; | ||||
|         public int Count => count; | ||||
| 
 | ||||
|         private void MakeHumanReadableName() { | ||||
|             if (readable_name != null && readable_name.Length > 0) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (Name == null) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             StringBuilder builder; | ||||
| 
 | ||||
|             if (humanreadable.ContainsKey(Name)) { | ||||
|                 builder = new StringBuilder(humanreadable[Name]); | ||||
|                 readable_name_generated = false; | ||||
|             } else { | ||||
|                 builder = new StringBuilder(Name); | ||||
|                 builder.Replace("Mission_", ""); | ||||
|                 builder.Replace("_name", ""); | ||||
|                 builder.Replace("_MB", ""); | ||||
|                 builder.Replace('_', ' '); | ||||
|                 builder.Replace("Illegal", " (Illegal)"); | ||||
|                 builder.Replace("OnFoot", "On Foot"); | ||||
|                 builder.Replace(" BS", ""); | ||||
|                 builder.Replace("HackMegaship", "Hack Megaship"); | ||||
|                 builder.Replace("Boom", ""); | ||||
|                 builder.Replace("RebootRestore", "Reboot/Restore"); | ||||
|                 builder.Replace("CivilLiberty", ""); | ||||
|                 readable_name_generated = true; | ||||
|             } | ||||
| 
 | ||||
|             if (count > 0 && commodity != null) { | ||||
|                 builder.AppendFormat(" ({0} {1})", count, commodity); | ||||
|             } | ||||
| 
 | ||||
|             if (donated > 0) { | ||||
|                 builder.AppendFormat(" ({0})", Credits.FormatCredits(donated)); | ||||
|             } | ||||
| 
 | ||||
|             readable_name = builder.ToString().Trim(); | ||||
|         } | ||||
| 
 | ||||
|         public string HumanReadableName { | ||||
|             get { | ||||
|                 MakeHumanReadableName(); | ||||
|                 return readable_name; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool HumanReadableNameWasGenerated { | ||||
|             get { | ||||
|                 MakeHumanReadableName(); | ||||
|                 return readable_name_generated; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public string GetInfluenceForFaction(string faction) { | ||||
|             if (influences.ContainsKey(faction)) { | ||||
|                 return influences[faction]; | ||||
|             } | ||||
| 
 | ||||
|             var effects = JSON.Value<JArray>("FactionEffects"); | ||||
|             foreach (var effect in effects.Children<JObject>()) { | ||||
|                 if (effect.GetValue("Faction").ToString() != faction) { | ||||
|                     continue; | ||||
|                 } | ||||
|                      | ||||
|                 var influence = effect.Value<JArray>("Influence"); | ||||
|                 if (influence == null || influence.Count == 0) { | ||||
|                     // No influence reward, happens on courier missions sometimes. | ||||
|                     // There is always one point of rep, even if the mission won't state it | ||||
|                     influences.Add(faction, "+"); | ||||
|                 } | ||||
|                  | ||||
|                 foreach (var infl in influence.Children<JObject>()) { | ||||
|                     infl.TryGetValue("Influence", out JToken result); | ||||
|                     if (result != null && result.Type == JTokenType.String) { | ||||
|                         influences.Add(faction, result.ToString()); | ||||
|                         return result.ToString(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return ""; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class MultiSellExplorationDataEntry : Entry { | ||||
|         private int totalearnings = 0; | ||||
| 
 | ||||
|         protected override void Initialise() { | ||||
|             totalearnings = JSON.Value<int>("TotalEarnings"); | ||||
|         } | ||||
| 
 | ||||
|         public int TotalEarnings => totalearnings; | ||||
|     } | ||||
| } | ||||
| @ -1,58 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class PlayerJournal { | ||||
|         public static string DefaultPath = "%UserProfile%\\Saved Games\\Frontier Developments\\Elite Dangerous"; | ||||
| 
 | ||||
|         private List<JournalFile> journalfiles = new List<JournalFile>(); | ||||
|         private string basepath = null; | ||||
| 
 | ||||
|         public string Location => basepath; | ||||
| 
 | ||||
|         public PlayerJournal() { | ||||
|             Initialise(DefaultPath); | ||||
|         } | ||||
| 
 | ||||
|         public PlayerJournal(string path) { | ||||
|             Initialise(path); | ||||
|         } | ||||
| 
 | ||||
|         private void Initialise(string path) { | ||||
|             basepath = Environment.ExpandEnvironmentVariables(path); | ||||
|         } | ||||
| 
 | ||||
|         public List<JournalFile> Files { | ||||
|             get { return journalfiles; } | ||||
|         } | ||||
| 
 | ||||
|         public void Open() { | ||||
|             if (!Directory.Exists(basepath)) { | ||||
|                 throw new JournalException("Invalid base path, path could not be found"); | ||||
|             } | ||||
|             this.ScanFiles(); | ||||
|         } | ||||
| 
 | ||||
|         public void ScanFiles() {  | ||||
|             var files = Directory.EnumerateFiles(basepath); | ||||
| 
 | ||||
|             journalfiles.Clear(); | ||||
| 
 | ||||
|             foreach (var file in files) { | ||||
|                 string full = Path.Combine(basepath, file); | ||||
|                 try { | ||||
|                     JournalFile journalfile = new JournalFile(full); | ||||
|                     journalfiles.Add(journalfile); | ||||
|                 } catch (JournalException) { | ||||
|                     /* invalid journal file, or one of the other json files in there */ | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             journalfiles.Sort(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,19 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class RedeemVoucherEntry : Entry { | ||||
|         private int amount = 0; | ||||
|         private string type = null; | ||||
|         protected override void Initialise() { | ||||
|             amount = JSON.Value<int>("Amount"); | ||||
|             type = JSON.Value<string>("Type"); | ||||
|         } | ||||
| 
 | ||||
|         public int Amount => amount; | ||||
|         public string Type => type; | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace NonaBGS.Journal { | ||||
|     public class SellMicroResourcesEntry : Entry { | ||||
|         private int price; | ||||
| 
 | ||||
|         protected override void Initialise() { | ||||
|             price = JSON.Value<int>("Price"); | ||||
|         } | ||||
| 
 | ||||
|         public int Price => price; | ||||
|     } | ||||
| } | ||||
| @ -5,7 +5,8 @@ using System.Windows.Controls; | ||||
| using System.Windows.Input; | ||||
| using Ookii.Dialogs.Wpf; | ||||
| 
 | ||||
| using NonaBGS.Journal; | ||||
| using EDJournal; | ||||
| 
 | ||||
| using NonaBGS.BGS; | ||||
| using NonaBGS.Util; | ||||
| using NonaBGS.EDDB; | ||||
|  | ||||
| @ -41,6 +41,9 @@ | ||||
|     <Reference Include="AutoCompleteTextBox, Version=1.1.1.0, Culture=neutral, processorArchitecture=MSIL"> | ||||
|       <HintPath>packages\AutoCompleteTextBox.1.1.1\lib\net472\AutoCompleteTextBox.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="EDJournal"> | ||||
|       <HintPath>..\edjournal\bin\Debug\netcoreapp3.1\EDJournal.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||||
|       <HintPath>packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||
|     </Reference> | ||||
| @ -75,13 +78,6 @@ | ||||
|     <Compile Include="BGS\SellMicroResources.cs" /> | ||||
|     <Compile Include="EDDB\PopulatedSystems.cs" /> | ||||
|     <Compile Include="EDDB\Stations.cs" /> | ||||
|     <Compile Include="Journal\Credits.cs" /> | ||||
|     <Compile Include="Journal\EliteDangerous.cs" /> | ||||
|     <Compile Include="Journal\JournalStream.cs" /> | ||||
|     <Compile Include="Journal\MarketSellEntry.cs" /> | ||||
|     <Compile Include="Journal\MultiSellExplorationDataEntry.cs" /> | ||||
|     <Compile Include="Journal\RedeemVoucherEntry.cs" /> | ||||
|     <Compile Include="Journal\SellMicroResourcesEntry.cs" /> | ||||
|     <Compile Include="UI\StationSuggestionProvider.cs" /> | ||||
|     <Compile Include="UI\SystemSuggestionProvider.cs" /> | ||||
|     <Compile Include="Util\AppConfig.cs" /> | ||||
| @ -104,15 +100,7 @@ | ||||
|     <Compile Include="BGS\CombatZone.cs" /> | ||||
|     <Compile Include="BGS\LogEntry.cs" /> | ||||
|     <Compile Include="BGS\MissionCompleted.cs" /> | ||||
|     <Compile Include="Journal\DockedEntry.cs" /> | ||||
|     <Compile Include="Journal\Entry.cs" /> | ||||
|     <Compile Include="BGS\Objective.cs" /> | ||||
|     <Compile Include="Journal\Events.cs" /> | ||||
|     <Compile Include="Journal\FSDJumpEntry.cs" /> | ||||
|     <Compile Include="Journal\JournalException.cs" /> | ||||
|     <Compile Include="Journal\JournalFile.cs" /> | ||||
|     <Compile Include="Journal\MissionCompletedEntry.cs" /> | ||||
|     <Compile Include="Journal\PlayerJournal.cs" /> | ||||
|     <Compile Include="MainWindow.xaml.cs"> | ||||
|       <DependentUpon>MainWindow.xaml</DependentUpon> | ||||
|       <SubType>Code</SubType> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user