EliteBGS/BGS/Report.cs

153 lines
5.8 KiB
C#

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;
namespace NonaBGS.BGS {
public class Report {
private List<Objective> objectives = new List<Objective>();
public delegate void OnLogDelegate(string log);
public event OnLogDelegate OnLog;
public List<Objective> Objectives {
get { return objectives; }
set { objectives = value; }
}
public bool AddObjective(Objective objective) {
var found = objectives.Find(x => x.CompareTo(objective) == 0);
bool added = false;
if (found == null) {
objectives.Add(objective);
added = true;
}
return added;
}
private bool IsRelevant(Entry e) {
return e.Is(Events.MissionCompleted) ||
e.Is(Events.Docked) ||
e.Is(Events.FSDJump) ||
e.Is(Events.MultiSellExplorationData) ||
e.Is(Events.SellMicroResources) ||
e.Is(Events.RedeemVoucher)
;
}
public void Scan(PlayerJournal journal, DateTime start, DateTime end) {
var entries = from file in journal.Files
where file.NormalisedTimestamp >= start && file.NormalisedTimestamp <= end
select file.Entries
;
var relevant = from log in entries.SelectMany(array => array)
where IsRelevant(log)
select log
;
string current_system = null;
string current_station = null;
string controlling_faction = null;
this.objectives.ForEach(x => x.LogEntries.Clear());
foreach (var e in relevant) {
LogEntry entry = null;
bool collate = false;
if (e.Is(Events.Docked)) {
/* gleem the current station from this message
*/
current_station = (e as DockedEntry).StationName;
} else if (e.Is(Events.FSDJump)) {
/* Gleem current system and controlling faction from this message.
*/
current_system = (e as FSDJumpEntry).StarSystem;
controlling_faction = (e as FSDJumpEntry).SystemFaction;
} else if (e.Is(Events.MissionCompleted)) {
var completed = e as MissionCompletedEntry;
entry = new MissionCompleted(completed, current_system, current_station);
if (completed.HumanReadableNameWasGenerated) {
/* If the human readable name was generated, we send a log message. Because the
* generated names all sort of suck, we should have more human readable names in
* in the lookup dictionary.
*/
OnLog?.Invoke("Human readable name for mission \"" +
completed.Name +
"\" was generated, please report this.");
}
} else if (e.Is(Events.MultiSellExplorationData)) {
/* For multi-sell-exploraton-data only the controlling faction of the station sold to matters.
*/
entry = new Cartographics(e as MultiSellExplorationDataEntry, current_system, current_station);
entry.Faction = controlling_faction;
} else if (e.Is(Events.RedeemVoucher)) {
/* Same for selling combat vouchers. Only the current controlling faction matters here.
*/
entry = new Vouchers();
entry.Entries.Add(e);
entry.System = current_system;
entry.Station = current_station;
entry.Faction = controlling_faction;
collate = true;
} else if (e.Is(Events.SellMicroResources)) {
entry = new SellMicroResources(current_system, current_station);
entry.Entries.Add(e);
}
if (entry == null) {
continue;
}
/* Find all objectives that generally match.
*/
var matches = objectives
.Where(x => x.Matches(entry) > 0)
.OrderBy(x => x.Matches(entry))
;
if (matches == null || matches.Count() <= 0) {
continue;
}
/* Then select the one that matches the most.
*/
var objective = matches
.OrderBy(x => x.Matches(entry))
.Reverse()
.First()
;
if (objective == null) {
continue;
}
LogEntry existing = null;
try {
existing = objective.LogEntries.Find(x => x.CompareTo(entry) == 0);
} catch (NotImplementedException) {
// Equivalent to not having found anything
existing = null;
}
if (collate && existing != null) {
existing.Entries.Add(e);
} else if (!collate || existing == null) {
objective.LogEntries.Add(entry);
}
}
}
public void Scan(PlayerJournal journal) {
Scan(journal, DateTime.Now, DateTime.Now);
}
}
}