EliteBGS/BGS/Report.cs

211 lines
8.8 KiB
C#
Raw Normal View History

2021-07-09 11:03:30 +02:00
using System;
using System.Collections.Generic;
using System.Linq;
2021-08-25 16:36:57 +02:00
using EDJournal;
2021-07-09 11:03:30 +02:00
2021-11-10 21:24:39 +01:00
namespace EliteBGS.BGS {
2021-07-09 11:03:30 +02:00
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);
2021-07-09 11:03:30 +02:00
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.MissionFailed) ||
e.Is(Events.MissionAccepted) ||
2021-07-09 11:03:30 +02:00
e.Is(Events.Docked) ||
e.Is(Events.FSDJump) ||
e.Is(Events.Location) ||
2021-07-09 11:03:30 +02:00
e.Is(Events.MultiSellExplorationData) ||
e.Is(Events.SellMicroResources) ||
e.Is(Events.RedeemVoucher) ||
e.Is(Events.FactionKillBond) ||
e.Is(Events.MarketSell)
2021-07-09 11:03:30 +02:00
;
}
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
;
Dictionary<int, MissionAcceptedEntry> acceptedMissions = new Dictionary<int, MissionAcceptedEntry>();
2021-07-09 11:03:30 +02:00
string current_system = null;
string current_station = null;
string controlling_faction = null;
2021-09-30 13:28:52 +02:00
objectives.ForEach(x => x.Clear());
2021-07-09 11:03:30 +02:00
foreach (var e in relevant) {
LogEntry entry = null;
bool collate = false;
2021-07-09 11:03:30 +02:00
if (e.Is(Events.Docked)) {
2021-11-17 21:01:35 +01:00
DockedEntry docked = e as DockedEntry;
2021-07-09 11:03:30 +02:00
/* gleem the current station from this message
*/
2021-11-17 21:01:35 +01:00
current_station = docked.StationName;
current_system = docked.StarSystem;
controlling_faction = docked.StationFaction;
2021-07-09 11:03:30 +02:00
} else if (e.Is(Events.FSDJump)) {
/* Gleem current system and controlling faction from this message.
*/
2021-07-09 11:03:30 +02:00
current_system = (e as FSDJumpEntry).StarSystem;
controlling_faction = (e as FSDJumpEntry).SystemFaction;
} else if (e.Is(Events.Location)) {
/* Get current system, faction name and station from Location message
*/
LocationEntry location = e as LocationEntry;
current_system = location.StarSystem;
if (!string.IsNullOrEmpty(location.SystemFaction)) {
controlling_faction = location.SystemFaction;
}
if (!string.IsNullOrEmpty(location.StationName)) {
current_station = location.StationName;
}
2021-07-09 11:03:30 +02:00
} else if (e.Is(Events.MissionCompleted)) {
var completed = e as MissionCompletedEntry;
2021-11-17 21:01:35 +01:00
entry = new MissionCompleted(completed) {
System = current_system,
Station = current_station
};
2021-07-09 11:03:30 +02:00
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.
*/
2021-07-09 11:03:30 +02:00
OnLog?.Invoke("Human readable name for mission \"" +
completed.Name +
"\" was generated, please report this.");
}
} else if (e.Is(Events.MissionAccepted)) {
MissionAcceptedEntry accepted = e as MissionAcceptedEntry;
acceptedMissions[accepted.MissionID] = accepted;
} else if (e.Is(Events.MissionFailed)) {
var failed = e as MissionFailedEntry;
2022-01-06 16:15:13 +01:00
MissionAcceptedEntry accepted = null;
if (!acceptedMissions.TryGetValue(failed.MissionID, out accepted)) {
2022-01-09 13:11:53 +01:00
OnLog?.Invoke("A mission failed which wasn't accepted in the given time frame. " +
"Please adjust start date to when the mission was accepted to include it in the list.");
continue;
}
entry = new MissionFailed(accepted) { Failed = failed, System = current_system };
if (failed.HumanReadableName == null) {
OnLog?.Invoke("Human readable name for mission \"" +
failed.Name +
"\" was not recognised");
}
2021-07-09 11:03:30 +02:00
} else if (e.Is(Events.MultiSellExplorationData)) {
/* For multi-sell-exploraton-data only the controlling faction of the station sold to matters.
*/
2021-07-09 11:03:30 +02:00
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.
*/
2021-07-09 11:03:30 +02:00
entry = new Vouchers();
entry.Entries.Add(e);
entry.System = current_system;
entry.Station = current_station;
2021-10-07 20:38:38 +02:00
entry.Faction = (e as RedeemVoucherEntry).Factions.FirstOrDefault() ?? "";
entry.ControllingFaction = controlling_faction;
collate = true;
2021-07-09 11:03:30 +02:00
} else if (e.Is(Events.SellMicroResources)) {
entry = new SellMicroResources() {
Faction = controlling_faction,
Station = current_station,
System = current_system
};
entry.Entries.Add(e);
} else if (e.Is(Events.MarketSell)) {
entry = new SellCargo() {
Faction = controlling_faction,
Station = current_station,
System = current_system
};
2021-07-09 11:03:30 +02:00
entry.Entries.Add(e);
}
if (entry == null) {
continue;
}
/* Find all objectives that generally match.
*/
2021-07-09 11:03:30 +02:00
var matches = objectives
.Where(x => x.Matches(entry) > 0)
.OrderBy(x => x.Matches(entry))
;
Objective objective = null;
if (matches != null && matches.Count() > 0) {
/* Then select the one that matches the most.
*/
objective = matches
.OrderBy(x => x.Matches(entry))
.Reverse()
.First()
;
} else {
/* create a new objective if we don't have one */
objective = new Objective() {
Station = entry.Station,
Faction = entry.Faction,
System = entry.System,
};
objectives.Add(objective);
}
LogEntry existing = null;
2021-09-30 13:32:31 +02:00
existing = objective.LogEntries.Find(x => {
2021-11-10 21:24:39 +01:00
try {
return x.CompareTo(entry) == 0;
} catch (NotImplementedException) {
return false;
}
});
2021-09-30 13:32:31 +02:00
if (collate && existing != null) {
existing.Entries.Add(e);
} else if (!collate || existing == null) {
2021-07-09 11:03:30 +02:00
objective.LogEntries.Add(entry);
}
}
}
public void Scan(PlayerJournal journal) {
Scan(journal, DateTime.Now, DateTime.Now);
}
}
}