416 lines
13 KiB
C#
416 lines
13 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using Ookii.Dialogs.Wpf;
|
|
using EDPlayerJournal;
|
|
using EDPlayerJournal.BGS;
|
|
using EDPlayerJournal.Entries;
|
|
using EliteBGS.BGS;
|
|
using EliteBGS.Util;
|
|
using System.Globalization;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Controls.Primitives;
|
|
|
|
namespace EliteBGS;
|
|
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
public partial class MainWindow : Window {
|
|
private PlayerJournal journal;
|
|
private Report report;
|
|
|
|
public Config Config { get; set; } = new Config();
|
|
|
|
private LoadEntriesWindow loadentries = null;
|
|
|
|
private static readonly List<DiscordLogGenerator> logtypes = new List<DiscordLogGenerator>() {
|
|
new NonaDiscordLog(),
|
|
new GenericDiscordLog(),
|
|
new OneLineDiscordLog(),
|
|
};
|
|
|
|
public MainWindow() {
|
|
InitializeComponent();
|
|
|
|
try {
|
|
Config.LoadGlobal();
|
|
} catch (Exception) {
|
|
/* ignored */
|
|
}
|
|
|
|
foreach (DiscordLogGenerator type in logtypes) {
|
|
LogType.Items.Add(type);
|
|
}
|
|
|
|
string lastused = Config.Global.LastUsedDiscordTemplate;
|
|
int lastindex = logtypes.FindIndex(x => x.ToString() == lastused);
|
|
if (lastindex > -1) {
|
|
LogType.SelectedIndex = lastindex;
|
|
} else {
|
|
LogType.SelectedIndex = 0;
|
|
}
|
|
|
|
journal = new PlayerJournal(Config.Global.JournalLocation);
|
|
|
|
// Set both to now
|
|
InitialiseTime();
|
|
|
|
journallocation.Text = Config.Global.JournalLocation;
|
|
}
|
|
|
|
private void InitialiseTime() {
|
|
DateTime today = DateTime.Today;
|
|
DateTime tomorrow = today.AddDays(1);
|
|
|
|
startdate.CultureInfo = enddate.CultureInfo = CultureInfo.InvariantCulture;
|
|
|
|
startdate.Value = today;
|
|
enddate.Value = tomorrow;
|
|
}
|
|
|
|
private void TreeView_CheckBox_Updated(object sender, RoutedEventArgs args) {
|
|
GenerateLog();
|
|
}
|
|
|
|
private void Report_OnLog(string message) {
|
|
StringBuilder builder = new StringBuilder();
|
|
|
|
builder.Append(DateTime.Now.ToString());
|
|
builder.Append(": ");
|
|
builder.Append(message);
|
|
builder.Append("\n");
|
|
|
|
log.AppendText(builder.ToString());
|
|
}
|
|
|
|
private void Log(string message) {
|
|
Report_OnLog(message);
|
|
}
|
|
|
|
private void HandleEntries(List<Entry> entries, DateTime start, DateTime end) {
|
|
try {
|
|
TransactionParser parser = new TransactionParser();
|
|
List<Transaction> transactions = parser.Parse(entries);
|
|
|
|
// Filter the transactions down to the given time frame
|
|
transactions = transactions
|
|
.Where(t => t.CompletedAtDateTime >= start && t.CompletedAtDateTime <= end)
|
|
.ToList()
|
|
;
|
|
|
|
List<IncompleteTransaction> incompletes = transactions.OfType<IncompleteTransaction>().ToList();
|
|
// Log incomplete and remove them from the results.
|
|
foreach (var incomplete in incompletes) {
|
|
Log(incomplete.Reason);
|
|
}
|
|
transactions.RemoveAll(x => incompletes.Contains(x));
|
|
|
|
report = new Report(transactions);
|
|
this.entries.ItemsSource = report.Objectives;
|
|
} catch (Exception exception) {
|
|
Log("Something went terribly wrong while parsing the E:D player journal.");
|
|
Log("Please send this to CMDR Hekateh:");
|
|
Log(exception.ToString());
|
|
}
|
|
}
|
|
|
|
private void HandleEntries(List<Entry> entries) {
|
|
HandleEntries(entries, DateTime.Now, DateTime.Now);
|
|
}
|
|
|
|
private void Loadentries_EntriesLoaded(List<Entry> lines) {
|
|
HandleEntries(lines);
|
|
}
|
|
|
|
private void ParseJournal_Click(object sender, RoutedEventArgs e) {
|
|
try {
|
|
TransactionParser parser = new TransactionParser();
|
|
|
|
DateTime start = startdate.Value ?? DateTime.Now;
|
|
DateTime end = enddate.Value ?? DateTime.Now;
|
|
|
|
journal.Open(); // Load all files
|
|
// Log files only get rotated if you restart the game client. This means that there might
|
|
// be - say - entries from the 4th of May in the file with a timestamp of 3rd of May. This
|
|
// happens if you happen to play a session late into the night.
|
|
// At first I tried extracting the first and last line of a file to see the date range, but
|
|
// if you have a lot of files this becomes quite slow, and quite the memory hog (as journal
|
|
// files have to be read in their entirety to check this). So we assume that you can't play
|
|
// three days straight, and keep the code fast.
|
|
DateTime actualstart = start.AddDays(-3);
|
|
DateTime actualend = end.AddDays(1);
|
|
List<Entry> entries = journal.Files
|
|
.Where(f => f.NormalisedDateTime >= actualstart && f.NormalisedDateTime <= actualend)
|
|
.SelectMany(e => e.Entries)
|
|
.ToList()
|
|
;
|
|
|
|
HandleEntries(entries, start, end);
|
|
GenerateLog();
|
|
} catch (Exception exception) {
|
|
Log("Something went terribly wrong while parsing the E:D player journal.");
|
|
Log("Please send this to CMDR Hekateh:");
|
|
Log(exception.ToString());
|
|
}
|
|
}
|
|
|
|
private void GenerateLog() {
|
|
try {
|
|
DiscordLogGenerator discord = LogType.SelectedItem as DiscordLogGenerator;
|
|
string report = discord.GenerateDiscordLog(this.report);
|
|
|
|
DiscordLog.Text = report;
|
|
} catch (Exception exception) {
|
|
Log("Something went terribly wrong while generating the Discord log.");
|
|
Log("Please send this to CMDR Hekateh:");
|
|
Log(exception.ToString());
|
|
}
|
|
}
|
|
|
|
private void GenerateDiscord_Click(object sender, RoutedEventArgs e) {
|
|
GenerateLog();
|
|
}
|
|
|
|
private void RemoveCurrentObjective() {
|
|
if (entries.SelectedItem == null) {
|
|
return;
|
|
}
|
|
|
|
object obj = entries.SelectedItem;
|
|
bool removed = false;
|
|
|
|
if (obj.GetType() == typeof(Objective)) {
|
|
removed = report.Objectives.Remove(obj as Objective);
|
|
} else if (obj.GetType() == typeof(UITransaction) ||
|
|
obj.GetType().IsSubclassOf(typeof(UITransaction))) {
|
|
foreach (Objective parent in report.Objectives) {
|
|
if (parent.UITransactions.Remove(obj as UITransaction)) {
|
|
removed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (removed) {
|
|
RefreshView();
|
|
}
|
|
}
|
|
|
|
private void entries_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) {
|
|
if (e.Key == Key.Delete) {
|
|
RemoveCurrentObjective();
|
|
}
|
|
}
|
|
|
|
private void browsejournallocation_Click(object sender, RoutedEventArgs e) {
|
|
var dialog = new VistaFolderBrowserDialog();
|
|
|
|
if ((bool)!dialog.ShowDialog()) {
|
|
return;
|
|
}
|
|
|
|
Config.Global.JournalLocation = dialog.SelectedPath;
|
|
journallocation.Text = Config.Global.JournalLocation;
|
|
journal = new PlayerJournal(Config.Global.JournalLocation);
|
|
}
|
|
|
|
private Objective GetObjectiveFromControl(object sender) {
|
|
System.Windows.Controls.Control control = sender as System.Windows.Controls.Control;
|
|
if (control == null || control.DataContext == null) {
|
|
return null;
|
|
}
|
|
|
|
return control.DataContext as Objective;
|
|
}
|
|
|
|
private void AddCombatZone_Click(object sender, RoutedEventArgs e) {
|
|
Objective objective = GetObjectiveFromControl(sender);
|
|
if (objective == null) {
|
|
return;
|
|
}
|
|
|
|
CombatZone zone = new CombatZone {
|
|
Faction = objective.Faction,
|
|
System = objective.System,
|
|
Grade = "Low",
|
|
Type = "Ship",
|
|
};
|
|
|
|
UITransaction uitransaction = new UITransaction(zone);
|
|
objective.UITransactions.Add(uitransaction);
|
|
|
|
RefreshView();
|
|
}
|
|
|
|
private void RefreshView() {
|
|
entries.Items.Refresh();
|
|
GenerateLog();
|
|
}
|
|
|
|
private void LogType_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
|
if (LogType.SelectedItem == null) {
|
|
return;
|
|
}
|
|
|
|
string template = LogType.SelectedItem.ToString();
|
|
Config.Global.LastUsedDiscordTemplate = template;
|
|
GenerateLog();
|
|
}
|
|
|
|
private void ManuallyParse_Click(object sender, RoutedEventArgs e) {
|
|
if (loadentries != null) {
|
|
loadentries.Show();
|
|
return;
|
|
}
|
|
|
|
loadentries = new LoadEntriesWindow();
|
|
loadentries.Closed += Loadentries_Closed;
|
|
loadentries.EntriesLoaded += Loadentries_EntriesLoaded;
|
|
loadentries.Show();
|
|
}
|
|
|
|
private void Loadentries_Closed(object sender, EventArgs e) {
|
|
loadentries = null;
|
|
}
|
|
|
|
private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
|
|
loadentries?.Close();
|
|
loadentries = null;
|
|
}
|
|
|
|
private void Transaction_Initialized(object sender, EventArgs e) {
|
|
}
|
|
|
|
private TransactionType GetTransaction<TransactionType>(object sender) where TransactionType : Transaction {
|
|
System.Windows.Controls.Control button = sender as System.Windows.Controls.Control;
|
|
if (button == null || button.DataContext == null) {
|
|
return null;
|
|
}
|
|
|
|
UITransaction transaction = button.DataContext as UITransaction;
|
|
if (transaction == null) {
|
|
return null;
|
|
}
|
|
|
|
return transaction.Transaction as TransactionType;
|
|
}
|
|
|
|
private void Low_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Grade = CombatZones.DifficultyLow;
|
|
RefreshView();
|
|
}
|
|
|
|
private void Med_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Grade = CombatZones.DifficultyMedium;
|
|
RefreshView();
|
|
}
|
|
|
|
private void High_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Grade = CombatZones.DifficultyHigh;
|
|
RefreshView();
|
|
}
|
|
|
|
private void VeryHigh_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Grade = CombatZones.DifficultyVeryHigh;
|
|
RefreshView();
|
|
}
|
|
|
|
private void Ground_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Type = CombatZones.GroundCombatZone;
|
|
RefreshView();
|
|
}
|
|
|
|
private void Ship_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Type = CombatZones.ShipCombatZone;
|
|
RefreshView();
|
|
}
|
|
|
|
private void Thargoid_Click(object sender, RoutedEventArgs e) {
|
|
CombatZone transaction = GetTransaction<CombatZone>(sender);
|
|
if (transaction == null) {
|
|
return;
|
|
}
|
|
|
|
transaction.Type = CombatZones.AXCombatZone;
|
|
RefreshView();
|
|
}
|
|
|
|
private void Profit_LostFocus(object sender, RoutedEventArgs e) {
|
|
RefreshView();
|
|
}
|
|
|
|
private void Profit_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) {
|
|
if (e.Key == Key.Enter) {
|
|
RefreshView();
|
|
}
|
|
}
|
|
|
|
private DateTime ResetTimeToZero(DateTime d) {
|
|
DateTime obj = d;
|
|
|
|
obj = obj.AddHours(d.Hour * -1);
|
|
obj = obj.AddMinutes(d.Minute * -1);
|
|
obj = obj.AddSeconds(d.Second * -1);
|
|
|
|
return obj;
|
|
}
|
|
|
|
private void ResetTime_Click(object sender, RoutedEventArgs e) {
|
|
DateTime? d = startdate.Value;
|
|
if (d != null) {
|
|
startdate.Value = ResetTimeToZero(d.Value);
|
|
}
|
|
|
|
d = enddate.Value;
|
|
if (d != null) {
|
|
enddate.Value = ResetTimeToZero(d.Value);
|
|
}
|
|
}
|
|
|
|
private void ToggleAll_Click(object sender, RoutedEventArgs e) {
|
|
ToggleButton button = sender as ToggleButton;
|
|
Objective objective = GetObjectiveFromControl(sender);
|
|
if (objective == null) {
|
|
return;
|
|
}
|
|
|
|
objective.UITransactions
|
|
.ForEach(x => x.IsEnabled = (button.IsChecked ?? true))
|
|
;
|
|
}
|
|
}
|