Compare commits
	
		
			No commits in common. "6cbe54ff7380a4857312553ac915bdefb7c92031" and "5ea288ee86c5000bf1fc4d0503fcd4344307c74a" have entirely different histories.
		
	
	
		
			6cbe54ff73
			...
			5ea288ee86
		
	
		
@ -35,10 +35,10 @@ public class Cartographics : Transaction {
 | 
				
			|||||||
            /* add multi sell and normal ones together */
 | 
					            /* add multi sell and normal ones together */
 | 
				
			||||||
            long total =
 | 
					            long total =
 | 
				
			||||||
                Entries.OfType<MultiSellExplorationDataEntry>()
 | 
					                Entries.OfType<MultiSellExplorationDataEntry>()
 | 
				
			||||||
                .Sum(x => x.Total)
 | 
					                .Sum(x => x.TotalEarnings)
 | 
				
			||||||
                +
 | 
					                +
 | 
				
			||||||
                Entries.OfType<SellExplorationDataEntry>()
 | 
					                Entries.OfType<SellExplorationDataEntry>()
 | 
				
			||||||
                .Sum(x => x.Total)
 | 
					                .Sum(x => x.TotalEarnings)
 | 
				
			||||||
                ;
 | 
					                ;
 | 
				
			||||||
            return total;
 | 
					            return total;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +0,0 @@
 | 
				
			|||||||
using EDPlayerJournal.BGS;
 | 
					 | 
				
			||||||
using EDPlayerJournal.Entries;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal class CommanderParser : ITransactionParserPart {
 | 
					 | 
				
			||||||
    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
					 | 
				
			||||||
        CommanderEntry commanderEntry = (CommanderEntry)entry;
 | 
					 | 
				
			||||||
        if (commanderEntry != null && !string.IsNullOrEmpty(commanderEntry.FullName)) {
 | 
					 | 
				
			||||||
            if (!context.Commanders.Contains(commanderEntry.FullName)) {
 | 
					 | 
				
			||||||
                context.Commanders.Add(commanderEntry.FullName);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // A commander entry happens when you log out, and log back in again
 | 
					 | 
				
			||||||
        // for example when switching from Open, to Solo or PG.
 | 
					 | 
				
			||||||
        context.DiscernCombatZone(transactions, entry);
 | 
					 | 
				
			||||||
        context.ResetCombatZone();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,84 +0,0 @@
 | 
				
			|||||||
using EDPlayerJournal.Entries;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace EDPlayerJournal.BGS.Parsers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal class RedeemVoucherParser : ITransactionParserPart {
 | 
					 | 
				
			||||||
    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
					 | 
				
			||||||
        RedeemVoucherEntry? entry = e as RedeemVoucherEntry;
 | 
					 | 
				
			||||||
        if (entry == null) {
 | 
					 | 
				
			||||||
            throw new NotImplementedException();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (context.CurrentSystem == null) {
 | 
					 | 
				
			||||||
            transactions.AddIncomplete(new Vouchers(),
 | 
					 | 
				
			||||||
                "Could not find out where the vouchers were redeemed", e
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        List<Faction>? current_factions = context.GetFactions(context.CurrentSystem);
 | 
					 | 
				
			||||||
        if (current_factions == null) {
 | 
					 | 
				
			||||||
            transactions.AddIncomplete(new Vouchers(),
 | 
					 | 
				
			||||||
                "Current system factions are unknown, so vouchers were ineffective", e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (string faction in entry.Factions) {
 | 
					 | 
				
			||||||
            bool relevantBond = false;
 | 
					 | 
				
			||||||
            string relevantFaction = faction;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (string.Compare(faction, Factions.PilotsFederationVouchers) == 0) {
 | 
					 | 
				
			||||||
                // Target faction is pilots' federation, so we assume thargoid bonks
 | 
					 | 
				
			||||||
                // Also assign this combat bond to the Pilots Federation
 | 
					 | 
				
			||||||
                relevantFaction = Factions.PilotsFederation;
 | 
					 | 
				
			||||||
                relevantBond = true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (current_factions != null && !relevantBond) {
 | 
					 | 
				
			||||||
                // If we have local factions, and it ain't thargoid bonds see if the bonds were
 | 
					 | 
				
			||||||
                // useful in the current system
 | 
					 | 
				
			||||||
                if (current_factions.Find(x => string.Compare(x.Name, faction, true) == 0) != null) {
 | 
					 | 
				
			||||||
                    relevantBond = true;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    transactions.AddIncomplete(new Vouchers(),
 | 
					 | 
				
			||||||
                        string.Format("Vouchers for \"{0}\" had no effect in \"{1}\" since said " +
 | 
					 | 
				
			||||||
                        "faction is not present there", faction, context.CurrentSystem), e
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!relevantBond) {
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var voucher = new Vouchers(entry) {
 | 
					 | 
				
			||||||
                System = context.CurrentSystem,
 | 
					 | 
				
			||||||
                Station = context.CurrentStation,
 | 
					 | 
				
			||||||
                Faction = relevantFaction,
 | 
					 | 
				
			||||||
                ControllingFaction = context.ControllingFaction,
 | 
					 | 
				
			||||||
                IsLegacy = context.IsLegacy,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (options.FilterDoubleRedeemVouchers) {
 | 
					 | 
				
			||||||
                // To filter out doubly redeemed vouchers, find another redeem voucher
 | 
					 | 
				
			||||||
                // event that happened in the same system, same total sum, and also the
 | 
					 | 
				
			||||||
                // same faction. If there is one, filter this one out.
 | 
					 | 
				
			||||||
                var doubledEntry = transactions
 | 
					 | 
				
			||||||
                    .OfType<Vouchers>()
 | 
					 | 
				
			||||||
                    .Where(x => x.TotalSum == voucher.TotalSum &&
 | 
					 | 
				
			||||||
                                x.System == voucher.System &&
 | 
					 | 
				
			||||||
                                x.Faction == voucher.Faction)
 | 
					 | 
				
			||||||
                    .ToList()
 | 
					 | 
				
			||||||
                    ;
 | 
					 | 
				
			||||||
                if (doubledEntry.Count > 0) {
 | 
					 | 
				
			||||||
                    transactions.AddIncomplete(
 | 
					 | 
				
			||||||
                        voucher, 
 | 
					 | 
				
			||||||
                        string.Format("A doubled redeem voucher for {0} valued {1} was detected",
 | 
					 | 
				
			||||||
                                      voucher.Faction, Credits.FormatMillions(voucher.TotalSum)), 
 | 
					 | 
				
			||||||
                        e);
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            transactions.Add(voucher);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -49,11 +49,10 @@ public class SellCargo : Transaction {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (MarketSellEntry sell in sold) {
 | 
					        foreach (MarketSellEntry sell in sold) {
 | 
				
			||||||
            builder.AppendFormat("Sold {0} {1} to the {2} of {3}",
 | 
					            builder.AppendFormat("Sold {0} {1} to the {2}",
 | 
				
			||||||
                sell.Count,
 | 
					                sell.Count,
 | 
				
			||||||
                Cargo,
 | 
					                Cargo,
 | 
				
			||||||
                Market,
 | 
					                Market
 | 
				
			||||||
                Station
 | 
					 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (Profit != 0) {
 | 
					            if (Profit != 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -28,14 +28,6 @@ public class TransactionParserOptions {
 | 
				
			|||||||
    /// Whether we should ignore things done for the fleet carrier faction.
 | 
					    /// Whether we should ignore things done for the fleet carrier faction.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public bool IgnoreFleetCarrierFaction { get; set; } = true;
 | 
					    public bool IgnoreFleetCarrierFaction { get; set; } = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Filter out double redeem vouchers that happen when you redeem a specific
 | 
					 | 
				
			||||||
    /// voucher, and then redeem the rest of your vouchers (say from a KWS) in
 | 
					 | 
				
			||||||
    /// bulk. The bulk redeem will also list the first voucher redeem again in
 | 
					 | 
				
			||||||
    /// its bulk list.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public bool FilterDoubleRedeemVouchers { get; set; } = true;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TransactionList : List<Transaction> {
 | 
					public class TransactionList : List<Transaction> {
 | 
				
			||||||
@ -430,6 +422,63 @@ internal class MissionFailedParser : ITransactionParserPart {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal class RedeemVoucherParser : ITransactionParserPart {
 | 
				
			||||||
 | 
					    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
				
			||||||
 | 
					        RedeemVoucherEntry? entry = e as RedeemVoucherEntry;
 | 
				
			||||||
 | 
					        if (entry == null) {
 | 
				
			||||||
 | 
					            throw new NotImplementedException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (context.CurrentSystem == null) {
 | 
				
			||||||
 | 
					            transactions.AddIncomplete(new Vouchers(),
 | 
				
			||||||
 | 
					                "Could not find out where the vouchers were redeemed", e
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<Faction>? current_factions = context.GetFactions(context.CurrentSystem);
 | 
				
			||||||
 | 
					        if (current_factions == null) {
 | 
				
			||||||
 | 
					            transactions.AddIncomplete(new Vouchers(),
 | 
				
			||||||
 | 
					                "Current system factions are unknown, so vouchers were ineffective", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (string faction in entry.Factions) {
 | 
				
			||||||
 | 
					            bool relevantBond = false;
 | 
				
			||||||
 | 
					            string relevantFaction = faction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (string.Compare(faction, Factions.PilotsFederationVouchers) == 0) {
 | 
				
			||||||
 | 
					                // Target faction is pilots' federation, so we assume thargoid bonks
 | 
				
			||||||
 | 
					                // Also assign this combat bond to the Pilots Federation
 | 
				
			||||||
 | 
					                relevantFaction = Factions.PilotsFederation;
 | 
				
			||||||
 | 
					                relevantBond = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (current_factions != null && !relevantBond) {
 | 
				
			||||||
 | 
					                // If we have local factions, and it ain't thargoid bonds see if the bonds were
 | 
				
			||||||
 | 
					                // useful in the current system
 | 
				
			||||||
 | 
					                if (current_factions.Find(x => string.Compare(x.Name, faction, true) == 0) != null) {
 | 
				
			||||||
 | 
					                    relevantBond = true;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    transactions.AddIncomplete(new Vouchers(),
 | 
				
			||||||
 | 
					                        string.Format("Vouchers for \"{0}\" had no effect in \"{1}\" since said " +
 | 
				
			||||||
 | 
					                        "faction is not present there", faction, context.CurrentSystem), e
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (relevantBond) {
 | 
				
			||||||
 | 
					                transactions.Add(new Vouchers(entry) {
 | 
				
			||||||
 | 
					                    System = context.CurrentSystem,
 | 
				
			||||||
 | 
					                    Station = context.CurrentStation,
 | 
				
			||||||
 | 
					                    Faction = relevantFaction,
 | 
				
			||||||
 | 
					                    ControllingFaction = context.ControllingFaction,
 | 
				
			||||||
 | 
					                    IsLegacy = context.IsLegacy,
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal class SellMicroResourcesParser : ITransactionParserPart {
 | 
					internal class SellMicroResourcesParser : ITransactionParserPart {
 | 
				
			||||||
    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
					    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
				
			||||||
        SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry;
 | 
					        SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry;
 | 
				
			||||||
@ -602,6 +651,15 @@ internal class DropshipDeployParser : ITransactionParserPart {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal class CommanderParser : ITransactionParserPart {
 | 
				
			||||||
 | 
					    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
				
			||||||
 | 
					        // A commander entry happens when you log out, and log back in again
 | 
				
			||||||
 | 
					        // for example when switching from Open, to Solo or PG.
 | 
				
			||||||
 | 
					        context.DiscernCombatZone(transactions, entry);
 | 
				
			||||||
 | 
					        context.ResetCombatZone();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TransactionParser {
 | 
					public class TransactionParser {
 | 
				
			||||||
    private static Dictionary<string, ITransactionParserPart> ParserParts { get; } = new()
 | 
					    private static Dictionary<string, ITransactionParserPart> ParserParts { get; } = new()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -660,11 +718,6 @@ public class TransactionParser {
 | 
				
			|||||||
        return Parse(entries, defaultOptions);
 | 
					        return Parse(entries, defaultOptions);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// List of commanders seen during parsing.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public List<string> Commanders { get; set; } = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public List<Transaction>? Parse(IEnumerable<Entry> entries, TransactionParserOptions options) {
 | 
					    public List<Transaction>? Parse(IEnumerable<Entry> entries, TransactionParserOptions options) {
 | 
				
			||||||
        TransactionList transactions = new();
 | 
					        TransactionList transactions = new();
 | 
				
			||||||
        TransactionParserContext context = new();
 | 
					        TransactionParserContext context = new();
 | 
				
			||||||
@ -682,9 +735,6 @@ public class TransactionParser {
 | 
				
			|||||||
            transactionParserPart.Parse(entry, context, options, transactions);
 | 
					            transactionParserPart.Parse(entry, context, options, transactions);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Copy out list of commanders seen
 | 
					 | 
				
			||||||
        Commanders = context.Commanders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return transactions.ToList();
 | 
					        return transactions.ToList();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,11 +3,6 @@
 | 
				
			|||||||
namespace EDPlayerJournal.BGS;
 | 
					namespace EDPlayerJournal.BGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal class TransactionParserContext {
 | 
					internal class TransactionParserContext {
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// List of commander names seen in the logs. May be empty.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public List<string> Commanders { get; } = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Name of the current system the player is in.
 | 
					    /// Name of the current system the player is in.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -8,13 +8,4 @@ public class CommanderEntry : Entry {
 | 
				
			|||||||
        Name = JSON.Value<string>("Name") ?? "";
 | 
					        Name = JSON.Value<string>("Name") ?? "";
 | 
				
			||||||
        FID = JSON.Value<string>("FID") ?? "";
 | 
					        FID = JSON.Value<string>("FID") ?? "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public string FullName {
 | 
					 | 
				
			||||||
        get {
 | 
					 | 
				
			||||||
            if (string.IsNullOrEmpty(Name)) {
 | 
					 | 
				
			||||||
                return string.Empty;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return "CMDR " + Name;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,23 +1,8 @@
 | 
				
			|||||||
namespace EDPlayerJournal.Entries; 
 | 
					namespace EDPlayerJournal.Entries; 
 | 
				
			||||||
 | 
					 | 
				
			||||||
public class MultiSellExplorationDataEntry : Entry {
 | 
					public class MultiSellExplorationDataEntry : Entry {
 | 
				
			||||||
    protected override void Initialise() {
 | 
					    protected override void Initialise() {
 | 
				
			||||||
        TotalEarnings = JSON.Value<long?>("TotalEarnings") ?? 0;
 | 
					        TotalEarnings = (JSON.Value<int?>("TotalEarnings") ?? 0);
 | 
				
			||||||
        BaseValue = JSON.Value<long?>("BaseValue") ?? 0;
 | 
					 | 
				
			||||||
        Bonus = JSON.Value<long?>("Bonus") ?? 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public long Total {
 | 
					    public int TotalEarnings { get; set; } = 0;
 | 
				
			||||||
        get { return BaseValue + Bonus; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public long BaseValue { get; set; } = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public long Bonus { get; set; } = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Total Earnings are the actual earnings without bonus. So this
 | 
					 | 
				
			||||||
    /// value is BaseValue minus any percent a crew pilot takes.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public long TotalEarnings { get; set; } = 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,17 +6,8 @@ namespace EDPlayerJournal.Entries;
 | 
				
			|||||||
public class SellExplorationDataEntry : Entry {
 | 
					public class SellExplorationDataEntry : Entry {
 | 
				
			||||||
    public long BaseValue { get; set; }
 | 
					    public long BaseValue { get; set; }
 | 
				
			||||||
    public long Bonus { get; set; }
 | 
					    public long Bonus { get; set; }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Total Earnings are the actual earnings without bonus. So this
 | 
					 | 
				
			||||||
    /// value is BaseValue minus any percent a crew pilot takes.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public long TotalEarnings { get; set; }
 | 
					    public long TotalEarnings { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public long Total {
 | 
					 | 
				
			||||||
        get { return BaseValue + Bonus; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public List<string> Systems { get; set; } = new List<string>();
 | 
					    public List<string> Systems { get; set; } = new List<string>();
 | 
				
			||||||
    public List<string> Discovered { get; set; } = new List<string>();
 | 
					    public List<string> Discovered { get; set; } = new List<string>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
{"timestamp":"2024-04-27T13:27:08Z","event":"Fileheader","part":1,"language":"English/UK","Odyssey":true,"gameversion":"4.0.0.1803","build":"r301470/r0 "}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T13:27:34Z","event":"Commander","FID":"F9183790","Name":"Jeremaya"}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T15:06:31Z","event":"FSDJump","Taxi":false,"Multicrew":false,"StarSystem":"HIP 3318","SystemAddress":525890177387,"StarPos":[50.21875,-190.6875,37.5],"SystemAllegiance":"Empire","SystemEconomy":"$economy_Refinery;","SystemEconomy_Localised":"Refinery","SystemSecondEconomy":"$economy_Extraction;","SystemSecondEconomy_Localised":"Extraction","SystemGovernment":"$government_Patronage;","SystemGovernment_Localised":"Patronage","SystemSecurity":"$SYSTEM_SECURITY_high;","SystemSecurity_Localised":"High Security","Population":239484,"Body":"HIP 3318 A","BodyID":2,"BodyType":"Star","JumpDist":27.495,"FuelUsed":3.115176,"FuelLevel":13.228082,"Factions":[{"Name":"HIP 3318 Autocracy","FactionState":"None","Government":"Dictatorship","Influence":0.119192,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Chakho Gold Galactic Limited","FactionState":"None","Government":"Corporate","Influence":0.09798,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"HIP 3318 Interstellar","FactionState":"None","Government":"Corporate","Influence":0.075758,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"HIP 3318 Values Party","FactionState":"None","Government":"Democracy","Influence":0.032323,"Allegiance":"Independent","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Nationalists of HIP 3318","FactionState":"None","Government":"Dictatorship","Influence":0.035354,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":0.0},{"Name":"Nova Paresa","FactionState":"Boom","Government":"Patronage","Influence":0.434343,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","SquadronFaction":true,"MyReputation":100.0,"PendingStates":[{"State":"Expansion","Trend":0}]},{"Name":"Empire Consulate Ltd","FactionState":"None","Government":"Patronage","Influence":0.20505,"Allegiance":"Empire","Happiness":"$Faction_HappinessBand2;","Happiness_Localised":"Happy","MyReputation":94.474998}],"SystemFaction":{"Name":"Nova Paresa","FactionState":"Boom"}}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T15:12:23Z","event":"ApproachSettlement","Name":"Koh Biological Installation","MarketID":3803792128,"StationFaction":{"Name":"Nova Paresa","FactionState":"Boom"},"StationGovernment":"$government_Patronage;","StationGovernment_Localised":"Patronage","StationAllegiance":"Empire","StationServices":["dock","autodock","commodities","contacts","exploration","missions","refuel","repair","engineer","missionsgenerated","flightcontroller","stationoperations","searchrescue","stationMenu"],"StationEconomy":"$economy_HighTech;","StationEconomy_Localised":"High Tech","StationEconomies":[{"Name":"$economy_HighTech;","Name_Localised":"High Tech","Proportion":1.0}],"SystemAddress":525890177387,"BodyID":26,"BodyName":"HIP 3318 D 3","Latitude":-0.893061,"Longitude":-62.928345}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T15:14:08Z","event":"Docked","StationName":"Koh Biological Installation","StationType":"OnFootSettlement","Taxi":false,"Multicrew":false,"StarSystem":"HIP 3318","SystemAddress":525890177387,"MarketID":3803792128,"StationFaction":{"Name":"Nova Paresa","FactionState":"Boom"},"StationGovernment":"$government_Patronage;","StationGovernment_Localised":"Patronage","StationAllegiance":"Empire","StationServices":["dock","autodock","commodities","contacts","exploration","missions","refuel","repair","engineer","missionsgenerated","flightcontroller","stationoperations","searchrescue","stationMenu"],"StationEconomy":"$economy_HighTech;","StationEconomy_Localised":"High Tech","StationEconomies":[{"Name":"$economy_HighTech;","Name_Localised":"High Tech","Proportion":1.0}],"DistFromStarLS":11972.63409,"LandingPads":{"Small":1,"Medium":0,"Large":1}}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T15:15:10Z","event":"RedeemVoucher","Type":"bounty","Amount":9449329,"Factions":[{"Faction":"Nova Paresa","Amount":9449329}]}
 | 
					 | 
				
			||||||
{"timestamp":"2024-04-27T15:15:51Z","event":"RedeemVoucher","Type":"bounty","Amount":18780130,"Factions":[{"Faction":"","Amount":224449},{"Faction":"","Amount":730880},{"Faction":"","Amount":1272764},{"Faction":"","Amount":580384},{"Faction":"","Amount":10180261},{"Faction":"","Amount":1413153},{"Faction":"","Amount":1365934},{"Faction":"","Amount":202193},{"Faction":"Nova Paresa","Amount":9449329},{"Faction":"","Amount":104412},{"Faction":"","Amount":2453443},{"Faction":"","Amount":252257}]}
 | 
					 | 
				
			||||||
@ -111,6 +111,10 @@ public class DiscordLogGenerator {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        string summary = GenerateSummary(objective);
 | 
					        string summary = GenerateSummary(objective);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log.AppendFormat("**Log Generated:** {0} by {1}\n", 
 | 
				
			||||||
 | 
					            DateTime.Now.ToString("dd/MM/yyyy"),
 | 
				
			||||||
 | 
					            GetToolVersion()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
        var earliest = GetDateOfEarliestEntry(objective);
 | 
					        var earliest = GetDateOfEarliestEntry(objective);
 | 
				
			||||||
        var latest = GetDateOfLatestEntry(objective);
 | 
					        var latest = GetDateOfLatestEntry(objective);
 | 
				
			||||||
        if (earliest != null && latest != null) {
 | 
					        if (earliest != null && latest != null) {
 | 
				
			||||||
@ -121,7 +125,7 @@ public class DiscordLogGenerator {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        log.AppendFormat("**Target:** {0}\n", location);
 | 
					        log.AppendFormat("**Target:** {0}\n", location);
 | 
				
			||||||
        if (!string.IsNullOrEmpty(summary)) {
 | 
					        if (!string.IsNullOrEmpty(summary)) {
 | 
				
			||||||
            log.AppendFormat("**Summary:** {0}\n", summary);
 | 
					            log.AppendFormat("**Summary**: {0}\n", summary);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (legacycount > 0) {
 | 
					        if (legacycount > 0) {
 | 
				
			||||||
            log.AppendFormat("**Warning:** Some actions were performed on ED Legacy\n");
 | 
					            log.AppendFormat("**Warning:** Some actions were performed on ED Legacy\n");
 | 
				
			||||||
@ -145,16 +149,6 @@ public class DiscordLogGenerator {
 | 
				
			|||||||
        return log;
 | 
					        return log;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public virtual string Name {
 | 
					 | 
				
			||||||
        get { return "GenericLog"; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual string BotHeader() {
 | 
					 | 
				
			||||||
        var sb = new StringBuilder();
 | 
					 | 
				
			||||||
        sb.AppendFormat("**Bot-Header:** {0}; {1}\n", GetToolVersion(), this.Name);
 | 
					 | 
				
			||||||
        return sb.ToString();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public virtual string GenerateDiscordLog(Report report) {
 | 
					    public virtual string GenerateDiscordLog(Report report) {
 | 
				
			||||||
        StringBuilder log = new StringBuilder();
 | 
					        StringBuilder log = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -170,7 +164,6 @@ public class DiscordLogGenerator {
 | 
				
			|||||||
            return "";
 | 
					            return "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log.AppendFormat("{0}", BotHeader());
 | 
					 | 
				
			||||||
        log.AppendFormat("{0}", GenerateHeader());
 | 
					        log.AppendFormat("{0}", GenerateHeader());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (Objective objective in objectives) {
 | 
					        foreach (Objective objective in objectives) {
 | 
				
			||||||
@ -198,65 +191,4 @@ public class DiscordLogGenerator {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return log.ToString().Trim();
 | 
					        return log.ToString().Trim();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public virtual string[] SplitLog(string log, int maxcount = 2000) {
 | 
					 | 
				
			||||||
        throw new NotImplementedException();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected string[] SplitLogWithHeader(string log, string header, int maxcount = 2000) {
 | 
					 | 
				
			||||||
        string[] lines = log.Split("\n");
 | 
					 | 
				
			||||||
        List<string> chunks = new();
 | 
					 | 
				
			||||||
        string chunk = string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Optimisation
 | 
					 | 
				
			||||||
        if (log.Length <= maxcount) {
 | 
					 | 
				
			||||||
            return new string[] { log };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // First split the log into its headers
 | 
					 | 
				
			||||||
        // skip first bot header line
 | 
					 | 
				
			||||||
        for (int i = 1; i < lines.Length; i++) {
 | 
					 | 
				
			||||||
            string line = lines[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (line.StartsWith(header) && !string.IsNullOrEmpty(chunk)) {
 | 
					 | 
				
			||||||
                chunks.Add(chunk.Trim());
 | 
					 | 
				
			||||||
                chunk = string.Empty;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            chunk = chunk + "\n" + line;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int curchunk = 0;
 | 
					 | 
				
			||||||
        string botheader = BotHeader().Trim() + "\n";
 | 
					 | 
				
			||||||
        // Leave room for botheader and some leeway
 | 
					 | 
				
			||||||
        int maxlength = (2000 - botheader.Length - 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Then try to collate chunks
 | 
					 | 
				
			||||||
        for (curchunk = 0; curchunk < chunks.Count; ++curchunk) {
 | 
					 | 
				
			||||||
            int count = chunks[curchunk].Length;
 | 
					 | 
				
			||||||
            while (count < maxlength && (curchunk+1) < chunks.Count) {
 | 
					 | 
				
			||||||
                count += chunks[curchunk + 1].Length + 2;
 | 
					 | 
				
			||||||
                if (count < maxlength) {
 | 
					 | 
				
			||||||
                    chunks[curchunk] += "\n";
 | 
					 | 
				
			||||||
                    chunks[curchunk] += chunks[curchunk + 1];
 | 
					 | 
				
			||||||
                    chunks.RemoveAt(curchunk + 1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Readd bott headers
 | 
					 | 
				
			||||||
        for (int i = 0; i < chunks.Count; i++) {
 | 
					 | 
				
			||||||
            chunks[i] = chunks[i].Insert(0, botheader);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Now finally check if any one chunk is bigger than max length
 | 
					 | 
				
			||||||
        for (int i = 0; i < chunks.Count; i++) {
 | 
					 | 
				
			||||||
            if (chunks[i].Length > maxcount) {
 | 
					 | 
				
			||||||
                throw new ApplicationException(
 | 
					 | 
				
			||||||
                    string.Format("a chunk turned out bigger than {0}", maxcount));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return chunks.ToArray();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,32 +0,0 @@
 | 
				
			|||||||
using EliteBGS.Util;
 | 
					 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using System.Text.Json.Nodes;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace EliteBGS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class DiscordPoster {
 | 
					 | 
				
			||||||
    public static readonly int DiscordLimit = 2000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static void PostToDiscord(DiscordWebhook webhook, string log, string username = "EDBGS") {
 | 
					 | 
				
			||||||
        JsonObject obj = new();
 | 
					 | 
				
			||||||
        obj.Add("content", log);
 | 
					 | 
				
			||||||
        obj.Add("username", username);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        using (var client = new HttpClient()) {
 | 
					 | 
				
			||||||
            var content = new StringContent(obj.ToString(), Encoding.UTF8, "application/json");
 | 
					 | 
				
			||||||
            var response = client.PostAsync(webhook.Webhook, content);
 | 
					 | 
				
			||||||
            if (response == null) {
 | 
					 | 
				
			||||||
                throw new Exception("failed to post content to Discord webhook");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            response.Wait();
 | 
					 | 
				
			||||||
            var resp = response.Result;
 | 
					 | 
				
			||||||
            if (!resp.IsSuccessStatusCode) {
 | 
					 | 
				
			||||||
                throw new Exception(string.Format(
 | 
					 | 
				
			||||||
                    "failed to post content to webhook {0}: {1} / {2}",
 | 
					 | 
				
			||||||
                    webhook.Name, resp.StatusCode, resp.Content.ToString()));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
  <PropertyGroup>
 | 
					  <PropertyGroup>
 | 
				
			||||||
    <TargetFramework>net7.0-windows</TargetFramework>
 | 
					    <TargetFramework>net7.0-windows</TargetFramework>
 | 
				
			||||||
    <OutputType>WinExe</OutputType>
 | 
					    <OutputType>WinExe</OutputType>
 | 
				
			||||||
    <Version>0.4.3</Version>
 | 
					    <Version>0.3.7</Version>
 | 
				
			||||||
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
 | 
					    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
 | 
				
			||||||
    <UseWindowsForms>true</UseWindowsForms>
 | 
					    <UseWindowsForms>true</UseWindowsForms>
 | 
				
			||||||
    <UseWPF>true</UseWPF>
 | 
					    <UseWPF>true</UseWPF>
 | 
				
			||||||
@ -18,15 +18,12 @@
 | 
				
			|||||||
    <Copyright>Copyright 2019 by Florian Stinglmayr</Copyright>
 | 
					    <Copyright>Copyright 2019 by Florian Stinglmayr</Copyright>
 | 
				
			||||||
    <RepositoryUrl>https://codeberg.org/nola/EDBGS</RepositoryUrl>
 | 
					    <RepositoryUrl>https://codeberg.org/nola/EDBGS</RepositoryUrl>
 | 
				
			||||||
    <PackageTags>ED;Elite Dangerous;BGS</PackageTags>
 | 
					    <PackageTags>ED;Elite Dangerous;BGS</PackageTags>
 | 
				
			||||||
    <PackageProjectUrl>https://salusinvicta.org/bgstool/</PackageProjectUrl>
 | 
					    <PackageProjectUrl>https://bgs.n0la.org</PackageProjectUrl>
 | 
				
			||||||
    <PackageReadmeFile>README.md</PackageReadmeFile>
 | 
					    <PackageReadmeFile>README.md</PackageReadmeFile>
 | 
				
			||||||
    <Description>Elite: Dangerous BGS logging and reporting tool
 | 
					    <Description>Elite: Dangerous BGS logging and reporting tool
 | 
				
			||||||
</Description>
 | 
					</Description>
 | 
				
			||||||
    <PackageIcon>logo_v5.png</PackageIcon>
 | 
					    <PackageIcon>logo_v5.png</PackageIcon>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					 | 
				
			||||||
    <None Remove="main-page.png" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <Resource Include="main-page.png">
 | 
					    <Resource Include="main-page.png">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
@ -40,10 +37,15 @@
 | 
				
			|||||||
      <Pack>True</Pack>
 | 
					      <Pack>True</Pack>
 | 
				
			||||||
      <PackagePath>\</PackagePath>
 | 
					      <PackagePath>\</PackagePath>
 | 
				
			||||||
    </None>
 | 
					    </None>
 | 
				
			||||||
    <None Update="CHANGELOG.md">
 | 
					    <None Update="docs\CHANGELOG.md">
 | 
				
			||||||
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
 | 
				
			||||||
    </None>
 | 
					    </None>
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Resource Include="docs\main-page.png">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </Resource>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <Content Include="LICENCE.txt">
 | 
					    <Content Include="LICENCE.txt">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
@ -53,12 +55,12 @@
 | 
				
			|||||||
    <Resource Include="Salus.ico" />
 | 
					    <Resource Include="Salus.ico" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <PackageReference Include="MahApps.Metro" Version="2.4.10" />
 | 
					    <PackageReference Include="MahApps.Metro" Version="2.4.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
 | 
					    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Windows.Compatibility" Version="8.0.4" />
 | 
					    <PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
 | 
					    <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
 | 
				
			||||||
    <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
 | 
					    <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,18 +1,7 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					namespace EliteBGS;
 | 
				
			||||||
using System.Windows.Documents;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace EliteBGS;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class GenericDiscordLog : DiscordLogGenerator {
 | 
					public class GenericDiscordLog : DiscordLogGenerator {
 | 
				
			||||||
    public override string ToString() {
 | 
					    public override string ToString() {
 | 
				
			||||||
        return "Generic";
 | 
					        return "Generic Log";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string Name {
 | 
					 | 
				
			||||||
        get { return "Generic"; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string[] SplitLog(string log, int maxcount = 2000) {
 | 
					 | 
				
			||||||
        return SplitLogWithHeader(log, "**Date:**", maxcount);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ public partial class LoadEntriesWindow : Window {
 | 
				
			|||||||
        dialog.DefaultExt = ".log";
 | 
					        dialog.DefaultExt = ".log";
 | 
				
			||||||
        dialog.Filter = "Log files (*.log)|*.log|All files (*.*)|*";
 | 
					        dialog.Filter = "Log files (*.log)|*.log|All files (*.*)|*";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var location = AppConfig.DefaultJournalLocation;
 | 
					        var location = config.Global.DefaultJournalLocation;
 | 
				
			||||||
        if (Directory.Exists(location)) {
 | 
					        if (Directory.Exists(location)) {
 | 
				
			||||||
            dialog.InitialDirectory = location;
 | 
					            dialog.InitialDirectory = location;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -5,57 +5,75 @@
 | 
				
			|||||||
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
					        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
				
			||||||
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
					        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
				
			||||||
        xmlns:local="clr-namespace:EliteBGS"
 | 
					        xmlns:local="clr-namespace:EliteBGS"
 | 
				
			||||||
        xmlns:Util="clr-namespace:EliteBGS.Util"
 | 
					        xmlns:Util="clr-namespace:EliteBGS.Util" d:DataContext="{d:DesignInstance Type=Util:AppConfig}" x:Name="window" x:Class="EliteBGS.MainWindow"
 | 
				
			||||||
        d:DataContext="{d:DesignInstance Type=Util:AppConfig}"
 | 
					 | 
				
			||||||
        x:Name="window"
 | 
					 | 
				
			||||||
        x:Class="EliteBGS.MainWindow"
 | 
					 | 
				
			||||||
        mc:Ignorable="d"
 | 
					        mc:Ignorable="d"
 | 
				
			||||||
        Title="Elite: Dangerous BGS Helper" Height="620" Width="950" Icon="Salus.ico"  Closing="window_Closing"
 | 
					        Title="Elite: Dangerous BGS Helper" Height="520" Width="950" Icon="Salus.ico"  Closing="window_Closing">
 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
    <Window.Resources>
 | 
					    <Window.Resources>
 | 
				
			||||||
        <local:MinusFortyFiveConverter x:Key="MinusFortyFiveConverter" />
 | 
					 | 
				
			||||||
        <Style x:Key="StretchingTreeViewStyle" TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
 | 
					        <Style x:Key="StretchingTreeViewStyle" TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
 | 
				
			||||||
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
 | 
					            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
 | 
				
			||||||
        </Style>
 | 
					        </Style>
 | 
				
			||||||
 | 
					        <local:MinusFortyFiveConverter x:Key="MinusFortyFiveConverter" />
 | 
				
			||||||
        <local:Report x:Key="ObjectivesBasedOnSystem" />
 | 
					    </Window.Resources>
 | 
				
			||||||
        <Util:Config x:Key="Config" />
 | 
					    <mah:MetroWindow.RightWindowCommands>
 | 
				
			||||||
 | 
					        <mah:WindowCommands ShowSeparators="False">
 | 
				
			||||||
        <DataTemplate DataType="{x:Type Util:DiscordWebhook}">
 | 
					            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,5,0">
 | 
				
			||||||
 | 
					                <Hyperlink x:Name="URL" NavigateUri="https://bgs.n0la.org/" RequestNavigate="URL_RequestNavigate">Homepage</Hyperlink>
 | 
				
			||||||
 | 
					            </TextBlock>
 | 
				
			||||||
 | 
					            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,15,0">
 | 
				
			||||||
 | 
					                <Hyperlink x:Name="SRC" NavigateUri="https://codeberg.org/nola/EDBGS" RequestNavigate="URL_RequestNavigate">Source</Hyperlink>
 | 
				
			||||||
 | 
					            </TextBlock>
 | 
				
			||||||
 | 
					            <mah:ToggleSwitch Content="Dark Theme" x:Name="SwitchTheme" IsOn="True" Toggled="SwitchTheme_Toggled"/>
 | 
				
			||||||
 | 
					        </mah:WindowCommands>
 | 
				
			||||||
 | 
					    </mah:MetroWindow.RightWindowCommands>
 | 
				
			||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <Grid.ColumnDefinitions>
 | 
					        <Grid.ColumnDefinitions>
 | 
				
			||||||
                    <ColumnDefinition Width="Auto" />
 | 
					 | 
				
			||||||
                    <ColumnDefinition Width="Auto" />
 | 
					 | 
				
			||||||
                    <ColumnDefinition Width="Auto" />
 | 
					 | 
				
			||||||
            <ColumnDefinition Width="*"/>
 | 
					            <ColumnDefinition Width="*"/>
 | 
				
			||||||
        </Grid.ColumnDefinitions>
 | 
					        </Grid.ColumnDefinitions>
 | 
				
			||||||
                <TextBlock Text="Name: " Grid.Column="0" Margin="2,0,0,0"/>
 | 
					        <Grid.RowDefinitions>
 | 
				
			||||||
                <TextBox Text="{Binding Name}" Grid.Column="1"/>
 | 
					            <RowDefinition Height="*"/>
 | 
				
			||||||
 | 
					        </Grid.RowDefinitions>
 | 
				
			||||||
                <TextBlock Text="Webhook URL: " Grid.Column="2" Margin="2,0,0,0"/>
 | 
					        <TabControl Style="{DynamicResource MahApps.Styles.TabControl.Animated}">
 | 
				
			||||||
                <TextBox Text="{Binding Webhook}" Grid.Column="3"/>
 | 
					            <TabItem Header="Current Objectives">
 | 
				
			||||||
            </Grid>
 | 
					                <Grid>
 | 
				
			||||||
        </DataTemplate>
 | 
					                    <Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
        <HierarchicalDataTemplate DataType="{x:Type local:SystemObjectives}" ItemsSource="{Binding Path=Objectives}">
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
            <Grid
 | 
					                        <RowDefinition/>
 | 
				
			||||||
                 HorizontalAlignment="Stretch"
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
                 Width="{Binding ActualWidth, ElementName=entries, Converter={StaticResource MinusFortyFiveConverter}}"
 | 
					                        <RowDefinition/>
 | 
				
			||||||
                >
 | 
					                    </Grid.RowDefinitions>
 | 
				
			||||||
                    <Grid.ColumnDefinitions>
 | 
					                    <Grid.ColumnDefinitions>
 | 
				
			||||||
                    <ColumnDefinition Width="Auto"/>
 | 
					                        <ColumnDefinition Width="*"/>
 | 
				
			||||||
 | 
					                        <ColumnDefinition Width="*"/>
 | 
				
			||||||
 | 
					                        <ColumnDefinition Width="*"/>
 | 
				
			||||||
                    </Grid.ColumnDefinitions>
 | 
					                    </Grid.ColumnDefinitions>
 | 
				
			||||||
                <StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,2,0,2">
 | 
					                    <ToolBar VerticalAlignment="Top" Grid.Row="0" Width="Auto" Margin="0,0,0,0" Height="Auto" Grid.ColumnSpan="3" HorizontalAlignment="Left">
 | 
				
			||||||
                    <CheckBox Focusable="False" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center"/>
 | 
					                        <Button x:Name="ParseJournal" Content="Parse Journal" VerticalAlignment="Center" Click="ParseJournal_Click" HorizontalAlignment="Center"/>
 | 
				
			||||||
                    <TextBlock Text="System: " Margin="2,0,0,0"/>
 | 
					                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
				
			||||||
                    <TextBlock Text="{Binding SystemName}" FontWeight="DemiBold"/>
 | 
					                        <Label Content="From (UTC):" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Center"/>
 | 
				
			||||||
                </StackPanel>
 | 
					                        <mah:DateTimePicker x:Name="startdate" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
				
			||||||
            </Grid>
 | 
					                        <Label Content="To (UTC):" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
				
			||||||
        </HierarchicalDataTemplate>
 | 
					                        <mah:DateTimePicker x:Name="enddate" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
				
			||||||
 | 
					                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
				
			||||||
        <HierarchicalDataTemplate DataType="{x:Type local:Objective}"
 | 
					                        <Button x:Name="ResetTime" Content="Reset Time" Click="ResetTime_Click" />
 | 
				
			||||||
                                  ItemsSource="{Binding Path=UITransactions}"
 | 
					                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
				
			||||||
                                  ItemContainerStyle="{StaticResource StretchingTreeViewStyle}">
 | 
					                        <Button x:Name="ManuallyParse" Content="Manually Parse" Click="ManuallyParse_Click" />
 | 
				
			||||||
 | 
					                    </ToolBar>
 | 
				
			||||||
 | 
					                    <ToolBar Grid.Row="1" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="3">
 | 
				
			||||||
 | 
					                        <Button x:Name="GenerateDiscord" Content="Generate Discord Report" VerticalAlignment="Stretch" Margin="0,0,0,0" VerticalContentAlignment="Center" Click="GenerateDiscord_Click"/>
 | 
				
			||||||
 | 
					                        <Separator />
 | 
				
			||||||
 | 
					                        <ComboBox x:Name="LogType" VerticalAlignment="Stretch" Margin="0,3,0,3" Width="140" SelectionChanged="LogType_SelectionChanged" />
 | 
				
			||||||
 | 
					                    </ToolBar>
 | 
				
			||||||
 | 
					                    <TreeView CheckBox.Checked="TreeView_CheckBox_Updated"
 | 
				
			||||||
 | 
					                              CheckBox.Unchecked="TreeView_CheckBox_Updated"
 | 
				
			||||||
 | 
					                              x:Name="entries" Margin="0,0,0,0"
 | 
				
			||||||
 | 
					                              Grid.ColumnSpan="3" Grid.Row="2"
 | 
				
			||||||
 | 
					                              KeyUp="entries_KeyUp"
 | 
				
			||||||
 | 
					                              HorizontalAlignment="Stretch"
 | 
				
			||||||
 | 
					                              HorizontalContentAlignment="Stretch"
 | 
				
			||||||
 | 
					                              >
 | 
				
			||||||
 | 
					                        <TreeView.ItemTemplate>
 | 
				
			||||||
 | 
					                            <HierarchicalDataTemplate DataType="{x:Type local:Objective}" ItemsSource="{Binding UITransactions}" ItemContainerStyle="{StaticResource StretchingTreeViewStyle}">
 | 
				
			||||||
                                <Grid
 | 
					                                <Grid
 | 
				
			||||||
                                     HorizontalAlignment="Stretch"
 | 
					                                     HorizontalAlignment="Stretch"
 | 
				
			||||||
                                     Width="{Binding ActualWidth, ElementName=entries, Converter={StaticResource MinusFortyFiveConverter}}"
 | 
					                                     Width="{Binding ActualWidth, ElementName=entries, Converter={StaticResource MinusFortyFiveConverter}}"
 | 
				
			||||||
@ -67,8 +85,10 @@
 | 
				
			|||||||
                                    </Grid.ColumnDefinitions>
 | 
					                                    </Grid.ColumnDefinitions>
 | 
				
			||||||
                                    <StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,2,0,2">
 | 
					                                    <StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,2,0,2">
 | 
				
			||||||
                                        <CheckBox Focusable="False" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center"/>
 | 
					                                        <CheckBox Focusable="False" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center"/>
 | 
				
			||||||
                    <TextBlock Text="Faction: " Margin="2,0,0,0"/>
 | 
					                                        <TextBlock Text="System: " Visibility="{Binding HasSystem}" Margin="2,0,0,0"/>
 | 
				
			||||||
                    <TextBlock Text="{Binding Faction}" FontWeight="DemiBold"/>
 | 
					                                        <TextBlock Text="{Binding System}" FontWeight="DemiBold" Visibility="{Binding HasSystem}"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="Faction: " Visibility="{Binding HasFaction}" Margin="2,0,0,0"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{Binding Faction}" FontWeight="DemiBold" Visibility="{Binding HasFaction}"/>
 | 
				
			||||||
                                    </StackPanel>
 | 
					                                    </StackPanel>
 | 
				
			||||||
                                    <Separator Visibility="Hidden" Grid.Column="1" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" />
 | 
					                                    <Separator Visibility="Hidden" Grid.Column="1" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" />
 | 
				
			||||||
                                    <StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Orientation="Horizontal">
 | 
					                                    <StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Orientation="Horizontal">
 | 
				
			||||||
@ -77,9 +97,8 @@
 | 
				
			|||||||
                                        <Button x:Name="AddCombatZone" Content="Add Combat Zone" Click="AddCombatZone_Click" />
 | 
					                                        <Button x:Name="AddCombatZone" Content="Add Combat Zone" Click="AddCombatZone_Click" />
 | 
				
			||||||
                                    </StackPanel>
 | 
					                                    </StackPanel>
 | 
				
			||||||
                                </Grid>
 | 
					                                </Grid>
 | 
				
			||||||
        </HierarchicalDataTemplate>
 | 
					                                <HierarchicalDataTemplate.ItemTemplate>
 | 
				
			||||||
 | 
					                                    <HierarchicalDataTemplate>
 | 
				
			||||||
        <DataTemplate DataType="{x:Type local:UITransaction}">
 | 
					 | 
				
			||||||
                                        <!-- This will stretch out the width of the item-->
 | 
					                                        <!-- This will stretch out the width of the item-->
 | 
				
			||||||
                                        <Grid Initialized="Transaction_Initialized"
 | 
					                                        <Grid Initialized="Transaction_Initialized"
 | 
				
			||||||
                                              HorizontalAlignment="Left"
 | 
					                                              HorizontalAlignment="Left"
 | 
				
			||||||
@ -129,76 +148,10 @@
 | 
				
			|||||||
                                                <TextBox x:Name="Profit" MinWidth="80" HorizontalContentAlignment="Right" Text="{Binding Profit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" LostFocus="Profit_LostFocus" KeyUp="Profit_KeyUp"/>
 | 
					                                                <TextBox x:Name="Profit" MinWidth="80" HorizontalContentAlignment="Right" Text="{Binding Profit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" LostFocus="Profit_LostFocus" KeyUp="Profit_KeyUp"/>
 | 
				
			||||||
                                            </StackPanel>
 | 
					                                            </StackPanel>
 | 
				
			||||||
                                        </Grid>
 | 
					                                        </Grid>
 | 
				
			||||||
        </DataTemplate>
 | 
					                                    </HierarchicalDataTemplate>
 | 
				
			||||||
 | 
					                                </HierarchicalDataTemplate.ItemTemplate>
 | 
				
			||||||
    </Window.Resources>
 | 
					                            </HierarchicalDataTemplate>
 | 
				
			||||||
    <mah:MetroWindow.RightWindowCommands>
 | 
					                        </TreeView.ItemTemplate>
 | 
				
			||||||
        <mah:WindowCommands ShowSeparators="False">
 | 
					 | 
				
			||||||
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,5,0">
 | 
					 | 
				
			||||||
                <Hyperlink x:Name="URL" NavigateUri="https://salusinvicta.org/bgstool/" RequestNavigate="URL_RequestNavigate">Homepage</Hyperlink>
 | 
					 | 
				
			||||||
            </TextBlock>
 | 
					 | 
				
			||||||
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,15,0">
 | 
					 | 
				
			||||||
                <Hyperlink x:Name="SRC" NavigateUri="https://codeberg.org/nola/EDBGS" RequestNavigate="URL_RequestNavigate">Source</Hyperlink>
 | 
					 | 
				
			||||||
            </TextBlock>
 | 
					 | 
				
			||||||
            <mah:ToggleSwitch Content="Dark Theme" x:Name="SwitchTheme" IsOn="True" Toggled="SwitchTheme_Toggled"/>
 | 
					 | 
				
			||||||
        </mah:WindowCommands>
 | 
					 | 
				
			||||||
    </mah:MetroWindow.RightWindowCommands>
 | 
					 | 
				
			||||||
    <Grid>
 | 
					 | 
				
			||||||
        <Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
            <ColumnDefinition Width="*"/>
 | 
					 | 
				
			||||||
        </Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
        <Grid.RowDefinitions>
 | 
					 | 
				
			||||||
            <RowDefinition Height="*"/>
 | 
					 | 
				
			||||||
        </Grid.RowDefinitions>
 | 
					 | 
				
			||||||
        <TabControl Style="{DynamicResource MahApps.Styles.TabControl.Animated}">
 | 
					 | 
				
			||||||
            <TabItem Header="Current Objectives">
 | 
					 | 
				
			||||||
                <Grid>
 | 
					 | 
				
			||||||
                    <Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					 | 
				
			||||||
                        <RowDefinition/>
 | 
					 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					 | 
				
			||||||
                        <RowDefinition/>
 | 
					 | 
				
			||||||
                    </Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                    <Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
                        <ColumnDefinition Width="*"/>
 | 
					 | 
				
			||||||
                        <ColumnDefinition Width="*"/>
 | 
					 | 
				
			||||||
                        <ColumnDefinition Width="*"/>
 | 
					 | 
				
			||||||
                    </Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
                    <ToolBar VerticalAlignment="Top" Grid.Row="0" Width="Auto" Margin="0,0,0,0" Height="Auto" Grid.ColumnSpan="3" HorizontalAlignment="Left">
 | 
					 | 
				
			||||||
                        <Button x:Name="ParseJournal" Content="Parse Journal" VerticalAlignment="Center" Click="ParseJournal_Click" HorizontalAlignment="Center"/>
 | 
					 | 
				
			||||||
                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
					 | 
				
			||||||
                        <Label Content="From (UTC):" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Center"/>
 | 
					 | 
				
			||||||
                        <mah:DateTimePicker x:Name="startdate" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
					 | 
				
			||||||
                        <Label Content="To (UTC):" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
					 | 
				
			||||||
                        <mah:DateTimePicker x:Name="enddate" Height="26.2857142857143" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
					 | 
				
			||||||
                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
					 | 
				
			||||||
                        <Button x:Name="ResetTime" Content="Reset Time" Click="ResetTime_Click" />
 | 
					 | 
				
			||||||
                        <Separator Margin="1" VerticalAlignment="Center" MinWidth="1" HorizontalAlignment="Center" MinHeight="22"/>
 | 
					 | 
				
			||||||
                        <Button x:Name="ManuallyParse" Content="Manually Parse" Click="ManuallyParse_Click" />
 | 
					 | 
				
			||||||
                    </ToolBar>
 | 
					 | 
				
			||||||
                    <ToolBar Grid.Row="1" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="3">
 | 
					 | 
				
			||||||
                        <Button x:Name="GenerateDiscord" Content="Generate Discord Report" VerticalAlignment="Stretch" Margin="0,0,0,0" VerticalContentAlignment="Center" Click="GenerateDiscord_Click"/>
 | 
					 | 
				
			||||||
                        <Separator />
 | 
					 | 
				
			||||||
                        <ComboBox x:Name="LogType" VerticalAlignment="Stretch" Margin="0,3,0,3" Width="140" SelectionChanged="LogType_SelectionChanged" />
 | 
					 | 
				
			||||||
                        <Separator />
 | 
					 | 
				
			||||||
                        <CheckBox x:Name="SelectAll" Content="Select All" IsChecked="True" Click="SelectAll_Click"/>
 | 
					 | 
				
			||||||
                        <Separator />
 | 
					 | 
				
			||||||
                        <Label Content="Post log as" VerticalAlignment="Center" Margin="0,3,0,3" />
 | 
					 | 
				
			||||||
                        <ComboBox x:Name="Commanders" VerticalAlignment="Stretch" Margin="0,3,0,3" Width="180" />
 | 
					 | 
				
			||||||
                        <Label Content="to" VerticalAlignment="Center" Margin="0,3,0,3" />
 | 
					 | 
				
			||||||
                        <mah:DropDownButton x:Name="PostToDiscord" Content="Discord" />
 | 
					 | 
				
			||||||
                    </ToolBar>
 | 
					 | 
				
			||||||
                    <TreeView CheckBox.Checked="TreeView_CheckBox_Updated"
 | 
					 | 
				
			||||||
                              CheckBox.Unchecked="TreeView_CheckBox_Updated"
 | 
					 | 
				
			||||||
                              x:Name="entries" Margin="0,0,0,0"
 | 
					 | 
				
			||||||
                              Grid.ColumnSpan="3"
 | 
					 | 
				
			||||||
                              Grid.Row="2"
 | 
					 | 
				
			||||||
                              KeyUp="entries_KeyUp"
 | 
					 | 
				
			||||||
                              HorizontalAlignment="Stretch"
 | 
					 | 
				
			||||||
                              HorizontalContentAlignment="Stretch"
 | 
					 | 
				
			||||||
                              ItemsSource="{Binding Source={StaticResource ObjectivesBasedOnSystem}}"
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                        <TreeView.ItemContainerStyle>
 | 
					                        <TreeView.ItemContainerStyle>
 | 
				
			||||||
                            <Style TargetType="TreeViewItem">
 | 
					                            <Style TargetType="TreeViewItem">
 | 
				
			||||||
                                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
 | 
					                                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
 | 
				
			||||||
@ -215,7 +168,6 @@
 | 
				
			|||||||
                        <RowDefinition Height="Auto"/>
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					                        <RowDefinition Height="Auto"/>
 | 
				
			||||||
                        <RowDefinition Height="Auto"/>
 | 
					 | 
				
			||||||
                        <RowDefinition Height="*"/>
 | 
					                        <RowDefinition Height="*"/>
 | 
				
			||||||
                    </Grid.RowDefinitions>
 | 
					                    </Grid.RowDefinitions>
 | 
				
			||||||
                    <Grid.ColumnDefinitions>
 | 
					                    <Grid.ColumnDefinitions>
 | 
				
			||||||
@ -271,35 +223,6 @@
 | 
				
			|||||||
                            <mah:ToggleSwitch x:Name="NoFleetCarrier" Grid.Row="2" Grid.ColumnSpan="2" Content="Ignore transactions done on a Fleet Carrier" Toggled="NoFleetCarrier_Toggled" />
 | 
					                            <mah:ToggleSwitch x:Name="NoFleetCarrier" Grid.Row="2" Grid.ColumnSpan="2" Content="Ignore transactions done on a Fleet Carrier" Toggled="NoFleetCarrier_Toggled" />
 | 
				
			||||||
                        </Grid>
 | 
					                        </Grid>
 | 
				
			||||||
                    </GroupBox>
 | 
					                    </GroupBox>
 | 
				
			||||||
                    <GroupBox Header="Discord Webhooks" Grid.Row="3" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="3" Margin="0,5,0,0">
 | 
					 | 
				
			||||||
                        <Grid>
 | 
					 | 
				
			||||||
                            <Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                                <RowDefinition Height="Auto" />
 | 
					 | 
				
			||||||
                                <RowDefinition Height="Auto" />
 | 
					 | 
				
			||||||
                            </Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                            <DataGrid x:Name="Webhooks"
 | 
					 | 
				
			||||||
                                      Grid.Row="0"
 | 
					 | 
				
			||||||
                                      ItemsSource="{Binding Webhooks}"
 | 
					 | 
				
			||||||
                                      AutoGenerateColumns="False"
 | 
					 | 
				
			||||||
                                      ScrollViewer.CanContentScroll="True"
 | 
					 | 
				
			||||||
                                      ScrollViewer.VerticalScrollBarVisibility="Auto"
 | 
					 | 
				
			||||||
                                      ScrollViewer.HorizontalScrollBarVisibility="Auto"
 | 
					 | 
				
			||||||
                                      MaxHeight="100"
 | 
					 | 
				
			||||||
                                      MinHeight="100"
 | 
					 | 
				
			||||||
                                      KeyUp="Webhooks_KeyUp"
 | 
					 | 
				
			||||||
                                      CellEditEnding="Webhooks_CellEditEnding"
 | 
					 | 
				
			||||||
                                      >
 | 
					 | 
				
			||||||
                                <DataGrid.Columns>
 | 
					 | 
				
			||||||
                                    <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
 | 
					 | 
				
			||||||
                                    <DataGridTextColumn Header="Webhook URL" Binding="{Binding Webhook}" Width="*"/>
 | 
					 | 
				
			||||||
                                </DataGrid.Columns>
 | 
					 | 
				
			||||||
                            </DataGrid>
 | 
					 | 
				
			||||||
                            <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5,10,5,0">
 | 
					 | 
				
			||||||
                                <Button x:Name="AddWebHook" Content="Add" Click="AddWebHook_Click"/>
 | 
					 | 
				
			||||||
                                <Button x:Name="RemoveWebHook" Content="Remove" Click="RemoveWebHook_Click" />
 | 
					 | 
				
			||||||
                            </StackPanel>
 | 
					 | 
				
			||||||
                        </Grid>
 | 
					 | 
				
			||||||
                    </GroupBox>
 | 
					 | 
				
			||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            </TabItem>
 | 
					            </TabItem>
 | 
				
			||||||
            <TabItem Header="Event Log">
 | 
					            <TabItem Header="Event Log">
 | 
				
			||||||
 | 
				
			|||||||
@ -32,8 +32,8 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
    private LoadEntriesWindow loadentries = null;
 | 
					    private LoadEntriesWindow loadentries = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static readonly List<DiscordLogGenerator> logtypes = new List<DiscordLogGenerator>() {
 | 
					    private static readonly List<DiscordLogGenerator> logtypes = new List<DiscordLogGenerator>() {
 | 
				
			||||||
        new GenericDiscordLog(),
 | 
					 | 
				
			||||||
        new NonaDiscordLog(),
 | 
					        new NonaDiscordLog(),
 | 
				
			||||||
 | 
					        new GenericDiscordLog(),
 | 
				
			||||||
        new OneLineDiscordLog(),
 | 
					        new OneLineDiscordLog(),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,9 +46,6 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
            /* ignored */
 | 
					            /* ignored */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Webhooks.ItemsSource = Config.Global.Webhooks;
 | 
					 | 
				
			||||||
        RefreshPostMenu();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (DiscordLogGenerator type in logtypes) {
 | 
					        foreach (DiscordLogGenerator type in logtypes) {
 | 
				
			||||||
            LogType.Items.Add(type);
 | 
					            LogType.Items.Add(type);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -110,10 +107,6 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
            //{ "HouseSalus", Color.FromRgb(0xBC, 0x94, 0x39) },
 | 
					            //{ "HouseSalus", Color.FromRgb(0xBC, 0x94, 0x39) },
 | 
				
			||||||
            { "HouseSalus", Color.FromRgb(0xED, 0xDA, 0x70) },
 | 
					            { "HouseSalus", Color.FromRgb(0xED, 0xDA, 0x70) },
 | 
				
			||||||
            { "NovaNavy", Color.FromRgb(0xA1, 0xA4, 0xDB) },
 | 
					            { "NovaNavy", Color.FromRgb(0xA1, 0xA4, 0xDB) },
 | 
				
			||||||
            // Official Red of the Polish Flag
 | 
					 | 
				
			||||||
            { "PolskaGurom", Color.FromRgb(0xD4, 0x21, 0x3D) },
 | 
					 | 
				
			||||||
            // Official Blue in the Armenian Flag
 | 
					 | 
				
			||||||
            { "ArmeniaBlue", Color.FromRgb(0x00, 0x33, 0xA0) },
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (var colourtheme in colorThemes) {
 | 
					        foreach (var colourtheme in colorThemes) {
 | 
				
			||||||
@ -185,11 +178,6 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            List<Transaction> transactions = parser.Parse(entries, options);
 | 
					            List<Transaction> transactions = parser.Parse(entries, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Commanders.ItemsSource = parser.Commanders;
 | 
					 | 
				
			||||||
            if (Commanders.Items.Count > 0) {
 | 
					 | 
				
			||||||
                Commanders.SelectedIndex = 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Filter the transactions down to the given time frame
 | 
					            // Filter the transactions down to the given time frame
 | 
				
			||||||
            transactions = transactions
 | 
					            transactions = transactions
 | 
				
			||||||
                .Where(t => t.CompletedAtDateTime >= start && t.CompletedAtDateTime <= end)
 | 
					                .Where(t => t.CompletedAtDateTime >= start && t.CompletedAtDateTime <= end)
 | 
				
			||||||
@ -204,7 +192,7 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
            transactions.RemoveAll(x => incompletes.Contains(x));
 | 
					            transactions.RemoveAll(x => incompletes.Contains(x));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            report = new Report(transactions);
 | 
					            report = new Report(transactions);
 | 
				
			||||||
            this.entries.ItemsSource = report.SystemObjectives;
 | 
					            this.entries.ItemsSource = report.Objectives;
 | 
				
			||||||
        } catch (Exception exception) {
 | 
					        } catch (Exception exception) {
 | 
				
			||||||
            Log("Something went terribly wrong while parsing the E:D player journal.");
 | 
					            Log("Something went terribly wrong while parsing the E:D player journal.");
 | 
				
			||||||
            Log("Please send this to CMDR Hekateh:");
 | 
					            Log("Please send this to CMDR Hekateh:");
 | 
				
			||||||
@ -283,27 +271,15 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
        object obj = entries.SelectedItem;
 | 
					        object obj = entries.SelectedItem;
 | 
				
			||||||
        bool removed = false;
 | 
					        bool removed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obj.GetType() == typeof(SystemObjectives)) {
 | 
					        if (obj.GetType() == typeof(Objective)) {
 | 
				
			||||||
            removed = report.SystemObjectives.Remove(obj as SystemObjectives);
 | 
					            removed = report.Objectives.Remove(obj as Objective);
 | 
				
			||||||
        } else if (obj.GetType() == typeof(Objective)) {
 | 
					 | 
				
			||||||
            report
 | 
					 | 
				
			||||||
                .SystemObjectives
 | 
					 | 
				
			||||||
                .ForEach(x => {
 | 
					 | 
				
			||||||
                    if (x.Objectives.Remove(obj as Objective)) {
 | 
					 | 
				
			||||||
                        removed = true;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
        } else if (obj.GetType() == typeof(UITransaction) ||
 | 
					        } else if (obj.GetType() == typeof(UITransaction) ||
 | 
				
			||||||
            obj.GetType().IsSubclassOf(typeof(UITransaction))) {
 | 
					            obj.GetType().IsSubclassOf(typeof(UITransaction))) {
 | 
				
			||||||
            report
 | 
					            foreach (Objective parent in report.Objectives) {
 | 
				
			||||||
                .SystemObjectives
 | 
					                if (parent.UITransactions.Remove(obj as UITransaction)) {
 | 
				
			||||||
                .SelectMany(x => 
 | 
					                    removed = true;
 | 
				
			||||||
                    x.Objectives
 | 
					                }
 | 
				
			||||||
                    .Where(x => x.UITransactions.Contains(obj as UITransaction))
 | 
					            }
 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                .ToList()
 | 
					 | 
				
			||||||
                .ForEach(x => removed = x.UITransactions.Remove(obj as UITransaction))
 | 
					 | 
				
			||||||
                ;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (removed) {
 | 
					        if (removed) {
 | 
				
			||||||
@ -581,136 +557,4 @@ public partial class MainWindow : MetroWindow {
 | 
				
			|||||||
        } catch (Exception) {
 | 
					        } catch (Exception) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void SelectAll_Click(object sender, RoutedEventArgs e) {
 | 
					 | 
				
			||||||
        if (report == null) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        report.SystemObjectives.ForEach(t => { t.IsEnabled = (bool)SelectAll.IsChecked; });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void AddWebHook_Click(object sender, RoutedEventArgs e) {
 | 
					 | 
				
			||||||
        Config.Global.Webhooks.Add(new DiscordWebhook {
 | 
					 | 
				
			||||||
            Name = "Discord Server Name",
 | 
					 | 
				
			||||||
            Webhook = "..."
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        Webhooks.Items.Refresh();
 | 
					 | 
				
			||||||
        RefreshPostMenu();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void RemoveWebHook_Click(object sender, RoutedEventArgs e) {
 | 
					 | 
				
			||||||
        if (Webhooks.SelectedItems.Count <= 0) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var selection = Webhooks.SelectedItems
 | 
					 | 
				
			||||||
            .OfType<DiscordWebhook>()
 | 
					 | 
				
			||||||
            .ToList()
 | 
					 | 
				
			||||||
            ;
 | 
					 | 
				
			||||||
        foreach (var item in selection) {
 | 
					 | 
				
			||||||
            Config.Global.Webhooks.Remove(item);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Webhooks.Items.Refresh();
 | 
					 | 
				
			||||||
        RefreshPostMenu();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void Webhooks_KeyUp(object sender, KeyEventArgs e) {
 | 
					 | 
				
			||||||
        DataGridCell cell = e.OriginalSource as DataGridCell;
 | 
					 | 
				
			||||||
        /* We also get keypresses from DataGridCells that are currently
 | 
					 | 
				
			||||||
         * editing their content. Filter those out. We don't want to delete
 | 
					 | 
				
			||||||
         * the row when the user presses DEL while editing the cells content
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        if (cell == null || cell.IsEditing) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (e.Key == Key.Delete) {
 | 
					 | 
				
			||||||
            RemoveWebHook_Click(this, new RoutedEventArgs());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void Webhooks_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Config.SaveGlobal();
 | 
					 | 
				
			||||||
        } catch (Exception) { }
 | 
					 | 
				
			||||||
        e.Cancel = false;
 | 
					 | 
				
			||||||
        RefreshPostMenu();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void RefreshPostMenu() {
 | 
					 | 
				
			||||||
        MenuItem menu;
 | 
					 | 
				
			||||||
        PostToDiscord.Items.Clear();
 | 
					 | 
				
			||||||
        if (Config.Global.Webhooks.Count <= 0) {
 | 
					 | 
				
			||||||
            PostToDiscord.IsEnabled = false;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            PostToDiscord.IsEnabled = true;
 | 
					 | 
				
			||||||
            foreach (var item in Config.Global.Webhooks) {
 | 
					 | 
				
			||||||
                menu = new MenuItem();
 | 
					 | 
				
			||||||
                menu.Header = item.Name;
 | 
					 | 
				
			||||||
                menu.Click += DiscordWebhook_Click;
 | 
					 | 
				
			||||||
                PostToDiscord.Items.Add(menu);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            PostToDiscord.Items.Add(new Separator());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            menu = new MenuItem();
 | 
					 | 
				
			||||||
            menu.Header = "All";
 | 
					 | 
				
			||||||
            menu.Click += PostToAll_Click;
 | 
					 | 
				
			||||||
            PostToDiscord.Items.Add(menu);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void PostToDiscordWebhook(IEnumerable<DiscordWebhook> hooks) {
 | 
					 | 
				
			||||||
        if (string.IsNullOrEmpty(DiscordLog.Text)) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        DiscordLogGenerator discord = LogType.SelectedItem as DiscordLogGenerator;
 | 
					 | 
				
			||||||
        string[] chunks;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            chunks = discord.SplitLog(DiscordLog.Text);
 | 
					 | 
				
			||||||
        } catch (Exception) {
 | 
					 | 
				
			||||||
            MessageBox.Show(
 | 
					 | 
				
			||||||
                "The log could not be split into discord appropriate length.\n" +
 | 
					 | 
				
			||||||
                "This happens with the bigger logs formats if you do lots of things in one system.\n" +
 | 
					 | 
				
			||||||
                "Try posting the log in the OneLine format.",
 | 
					 | 
				
			||||||
                "Sorry!", MessageBoxButton.OK, MessageBoxImage.Error
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        string commander = "EDBGS";
 | 
					 | 
				
			||||||
        if (Commanders.SelectedIndex >= 0) {
 | 
					 | 
				
			||||||
            commander = Commanders.SelectedItem.ToString();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (var hook in hooks) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                foreach (var chunk in chunks) {
 | 
					 | 
				
			||||||
                    DiscordPoster.PostToDiscord(hook, chunk, commander);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                Log(string.Format("successfully posted to discord webhook `{0}`", hook.Name));
 | 
					 | 
				
			||||||
            } catch (Exception ex) {
 | 
					 | 
				
			||||||
                Log(string.Format("failed to post to discord webhook `{0}`: {1}",
 | 
					 | 
				
			||||||
                    hook.Name, ex.Message));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void DiscordWebhook_Click(object sender, RoutedEventArgs e) {
 | 
					 | 
				
			||||||
        MenuItem item = sender as MenuItem;
 | 
					 | 
				
			||||||
        if (item == null) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        DiscordWebhook hook = Config.Global.Webhooks
 | 
					 | 
				
			||||||
            .Find(x => string.Compare(x.Name, item.Header.ToString()) == 0)
 | 
					 | 
				
			||||||
            ;
 | 
					 | 
				
			||||||
        if (hook == null) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        PostToDiscordWebhook(new DiscordWebhook[] { hook });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void PostToAll_Click(object sender, RoutedEventArgs e) {
 | 
					 | 
				
			||||||
        PostToDiscordWebhook(Config.Global.Webhooks);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ public class MinusFortyFiveConverter : IValueConverter {
 | 
				
			|||||||
    /// <inheritdoc/>
 | 
					    /// <inheritdoc/>
 | 
				
			||||||
    public object Convert(
 | 
					    public object Convert(
 | 
				
			||||||
        object value, Type targetType, object parameter, CultureInfo culture) {
 | 
					        object value, Type targetType, object parameter, CultureInfo culture) {
 | 
				
			||||||
        return (double)value - 110;
 | 
					        return (double)value - 80;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc/>
 | 
					    /// <inheritdoc/>
 | 
				
			||||||
 | 
				
			|||||||
@ -7,12 +7,6 @@ using System.Linq;
 | 
				
			|||||||
namespace EliteBGS.BGS;
 | 
					namespace EliteBGS.BGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class NonaDiscordLog : DiscordLogGenerator {
 | 
					public class NonaDiscordLog : DiscordLogGenerator {
 | 
				
			||||||
    protected override string BotHeader() {
 | 
					 | 
				
			||||||
        var sb = new StringBuilder();
 | 
					 | 
				
			||||||
        sb.AppendFormat(":robot: `Bot-Header:` {0}; {1}\n", GetToolVersion(), this.Name);
 | 
					 | 
				
			||||||
        return sb.ToString();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private string FormatDate() {
 | 
					    private string FormatDate() {
 | 
				
			||||||
        CultureInfo cultureInfo = CultureInfo.InvariantCulture;
 | 
					        CultureInfo cultureInfo = CultureInfo.InvariantCulture;
 | 
				
			||||||
        StringBuilder date = new StringBuilder();
 | 
					        StringBuilder date = new StringBuilder();
 | 
				
			||||||
@ -85,14 +79,6 @@ public class NonaDiscordLog : DiscordLogGenerator {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override string ToString() {
 | 
					    public override string ToString() {
 | 
				
			||||||
        return "Nova Navy";
 | 
					        return "Nova Navy Log";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string Name {
 | 
					 | 
				
			||||||
        get { return "NovaNavy"; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string[] SplitLog(string log, int maxcount = 2000) {
 | 
					 | 
				
			||||||
        return SplitLogWithHeader(log, ":clock2: `Date:`", maxcount);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -242,7 +242,7 @@ public class UITransaction : INotifyPropertyChanged {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Objective : IComparable<Objective> {
 | 
					public class Objective : IComparable<Objective> {
 | 
				
			||||||
    public bool IsEnabled { get; set; } = true;
 | 
					    public bool IsEnabled { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<UITransaction> UITransactions { get; } = new List<UITransaction>();
 | 
					    public List<UITransaction> UITransactions { get; } = new List<UITransaction>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,6 @@
 | 
				
			|||||||
using EliteBGS.LogGenerator;
 | 
					using EliteBGS.LogGenerator;
 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.Windows.Documents;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace EliteBGS;
 | 
					namespace EliteBGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -28,30 +25,6 @@ public class OneLineDiscordLog : DiscordLogGenerator {
 | 
				
			|||||||
        return "";
 | 
					        return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override string[] SplitLog(string log, int maxcount = 2000) {
 | 
					 | 
				
			||||||
        string[] lines = log.Split('\n');
 | 
					 | 
				
			||||||
        List<string> chunks = new();
 | 
					 | 
				
			||||||
        string chunk = string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Optimisation
 | 
					 | 
				
			||||||
        if (log.Length <= maxcount) {
 | 
					 | 
				
			||||||
            return new string[] { log };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < lines.Length; i++) {
 | 
					 | 
				
			||||||
            string line = lines[i];
 | 
					 | 
				
			||||||
            if ((chunk.Length + line.Length) > maxcount || i == lines.Length - 1) {
 | 
					 | 
				
			||||||
                chunks.Add(chunk.Trim());
 | 
					 | 
				
			||||||
                chunk = string.Empty;
 | 
					 | 
				
			||||||
                chunk = chunk.Insert(0, BotHeader()).Trim();
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                chunk = chunk + "\n" + line;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return chunks.ToArray();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string GenerateDiscordLog(Report report) {
 | 
					    public override string GenerateDiscordLog(Report report) {
 | 
				
			||||||
        StringBuilder log = new StringBuilder();
 | 
					        StringBuilder log = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -67,8 +40,6 @@ public class OneLineDiscordLog : DiscordLogGenerator {
 | 
				
			|||||||
            return "";
 | 
					            return "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log.AppendFormat("{0}", BotHeader());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (Objective objective in objectives) {
 | 
					        foreach (Objective objective in objectives) {
 | 
				
			||||||
            log.AppendFormat("{0}", GenerateObjectiveHeader(objective));
 | 
					            log.AppendFormat("{0}", GenerateObjectiveHeader(objective));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,10 +60,6 @@ public class OneLineDiscordLog : DiscordLogGenerator {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override string ToString() {
 | 
					    public override string ToString() {
 | 
				
			||||||
        return "One Line";
 | 
					        return "One Line Report";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override string Name {
 | 
					 | 
				
			||||||
        get { return "OneLine"; }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -49,5 +49,5 @@ using System.Windows;
 | 
				
			|||||||
// You can specify all the values or you can default the Build and Revision Numbers
 | 
					// You can specify all the values or you can default the Build and Revision Numbers
 | 
				
			||||||
// by using the '*' as shown below:
 | 
					// by using the '*' as shown below:
 | 
				
			||||||
// [assembly: AssemblyVersion("1.0.*")]
 | 
					// [assembly: AssemblyVersion("1.0.*")]
 | 
				
			||||||
[assembly: AssemblyVersion("0.4.3.0")]
 | 
					[assembly: AssemblyVersion("0.3.7.0")]
 | 
				
			||||||
[assembly: AssemblyFileVersion("0.4.3.0")]
 | 
					[assembly: AssemblyFileVersion("0.3.7.0")]
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ been parsed, you may then generate a BGS report you can copy/paste into Discord.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Source code is available at [https://codeberg.org/nola/edbgs](https://codeberg.org/nola/edbgs).
 | 
					Source code is available at [https://codeberg.org/nola/edbgs](https://codeberg.org/nola/edbgs).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Binary downloads can be found here: [https://salusinvicta.org/bgstool/](https://salusinvicta.org/bgstool/).
 | 
					Binary downloads can be found here: [https://bgs.n0la.org/](https://bgs.n0la.org/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## How To
 | 
					## How To
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,38 +1,10 @@
 | 
				
			|||||||
using System;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.ComponentModel;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using EDPlayerJournal.BGS;
 | 
					using EDPlayerJournal.BGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace EliteBGS;
 | 
					namespace EliteBGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SystemObjectives : INotifyPropertyChanged, IComparable<SystemObjectives> {
 | 
					 | 
				
			||||||
    public event PropertyChangedEventHandler PropertyChanged;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private bool isenabled = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public bool IsEnabled {
 | 
					 | 
				
			||||||
        get { return isenabled; }
 | 
					 | 
				
			||||||
        set {
 | 
					 | 
				
			||||||
            isenabled = value;
 | 
					 | 
				
			||||||
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsEnabled"));
 | 
					 | 
				
			||||||
        } 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public bool IsExpanded { get; set; } = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public string SystemName { get; set; } = string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public List<Objective> Objectives { get; set; } = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int CompareTo(SystemObjectives other) {
 | 
					 | 
				
			||||||
        if (other == null) return 1;
 | 
					 | 
				
			||||||
        return string.Compare(SystemName, other.SystemName, StringComparison.OrdinalIgnoreCase);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Report {
 | 
					public class Report {
 | 
				
			||||||
    public List<SystemObjectives> SystemObjectives { get; set; } = new();
 | 
					    public List<Objective> Objectives { get; set; } = new List<Objective>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Report() { }
 | 
					    public Report() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,35 +12,29 @@ public class Report {
 | 
				
			|||||||
        Populate(transactions);
 | 
					        Populate(transactions);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<Objective> Objectives {
 | 
					 | 
				
			||||||
        get {
 | 
					 | 
				
			||||||
            return SystemObjectives
 | 
					 | 
				
			||||||
                .Where(t => t.IsEnabled)
 | 
					 | 
				
			||||||
                .SelectMany(x => x.Objectives)
 | 
					 | 
				
			||||||
                .ToList()
 | 
					 | 
				
			||||||
                ;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void Populate(List<Transaction> transactions) {
 | 
					    private void Populate(List<Transaction> transactions) {
 | 
				
			||||||
        if (transactions == null || transactions.Count == 0) {
 | 
					        if (transactions == null || transactions.Count == 0) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (Transaction t in transactions) {
 | 
					        foreach (Transaction t in transactions) {
 | 
				
			||||||
            var o = SystemObjectives.Find(x => string.Compare(x.SystemName, t.System) == 0);
 | 
					            Objective o;
 | 
				
			||||||
            if (o == null) {
 | 
					            if (t.SystemContribution) {
 | 
				
			||||||
                o = new SystemObjectives() { SystemName = t.System };
 | 
					                o = Objectives.Find(x => x.Matches(t.System));
 | 
				
			||||||
                SystemObjectives.Add(o);
 | 
					            } else {
 | 
				
			||||||
            }
 | 
					                o = Objectives.Find(x => x.Matches(t.System, t.Faction));
 | 
				
			||||||
            var objective = o.Objectives.Find(x => x.Matches(t.System, t.Faction));
 | 
					 | 
				
			||||||
            if (objective == null) {
 | 
					 | 
				
			||||||
                objective = new Objective() { Faction = t.Faction, System = t.System };
 | 
					 | 
				
			||||||
                o.Objectives.Add(objective);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            objective.UITransactions.Add(new UITransaction(t));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SystemObjectives.Sort();
 | 
					            if (o == null) {
 | 
				
			||||||
 | 
					                if (t.SystemContribution) {
 | 
				
			||||||
 | 
					                    o = new Objective() { System = t.System };
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    o = new Objective() { Faction = t.Faction, System = t.System };
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Objectives.Add(o);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            o.UITransactions.Add(new UITransaction(t));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,13 @@
 | 
				
			|||||||
using Newtonsoft.Json;
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.ComponentModel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace EliteBGS.Util;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace EliteBGS.Util {
 | 
				
			||||||
    public class AppConfig {
 | 
					    public class AppConfig {
 | 
				
			||||||
        private static readonly string default_journal_location = "%UserProfile%\\Saved Games\\Frontier Developments\\Elite Dangerous";
 | 
					        private static readonly string default_journal_location = "%UserProfile%\\Saved Games\\Frontier Developments\\Elite Dangerous";
 | 
				
			||||||
        private string journal_location = default_journal_location;
 | 
					        private string journal_location = default_journal_location;
 | 
				
			||||||
 | 
					        public string DefaultJournalLocation => default_journal_location;
 | 
				
			||||||
        private string colour = "Amber";
 | 
					        private string colour = "Amber";
 | 
				
			||||||
        private string theme = "Dark";
 | 
					        private string theme = "Dark";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static string DefaultJournalLocation => default_journal_location;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public string LastUsedDiscordTemplate { get; set; }
 | 
					        public string LastUsedDiscordTemplate { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string JournalLocation {
 | 
					        public string JournalLocation {
 | 
				
			||||||
@ -67,13 +63,9 @@ public class AppConfig {
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public bool IgnoreFleetCarrier { get; set; } = true;
 | 
					        public bool IgnoreFleetCarrier { get; set; } = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// List of Webhooks configured
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public List<DiscordWebhook> Webhooks { get; set; } = new List<DiscordWebhook>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        [JsonIgnore]
 | 
					        [JsonIgnore]
 | 
				
			||||||
        public string FullTheme {
 | 
					        public string FullTheme {
 | 
				
			||||||
            get { return Theme + "." + Colour; }
 | 
					            get { return Theme + "." + Colour; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@
 | 
				
			|||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using Newtonsoft.Json;
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
using System.ComponentModel;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace EliteBGS.Util {
 | 
					namespace EliteBGS.Util {
 | 
				
			||||||
    public class Config {
 | 
					    public class Config {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +0,0 @@
 | 
				
			|||||||
namespace EliteBGS.Util;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class DiscordWebhook {
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Webhook URL
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public string Webhook { get; set; } = string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Human readable name for easier identification
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public string Name { get; set; } = string.Empty;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 75 KiB  | 
@ -1,47 +1,12 @@
 | 
				
			|||||||
# EliteBGS changelog
 | 
					# EliteBGS changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.4.3 on 18.09.2024
 | 
					# 0.3.7 on 29.01.2024
 | 
				
			||||||
 | 
					 | 
				
			||||||
* Add possibility to post log reports to Discord webhooks.
 | 
					 | 
				
			||||||
  Logs are automatically split to fit discord length, and you can choose the
 | 
					 | 
				
			||||||
  name of the Commander to post it as. There are some restrictions, so for
 | 
					 | 
				
			||||||
  ultra long logs the one line log format might be necessary.
 | 
					 | 
				
			||||||
* Fix cartographics data value by igonring `TotalEarnings`. Total earnings
 | 
					 | 
				
			||||||
  is the same as `BaseValue`, except any percentages taken by crew members
 | 
					 | 
				
			||||||
  is deducted. Actual total value is `BaseValue` plus `Bonus`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 0.4.2 on 02.05.2024
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Add a bot header for all generated logs that shows the tool version, as
 | 
					 | 
				
			||||||
  well as the name of of the log format used. This makes it easier for bots
 | 
					 | 
				
			||||||
  to parse these logs. Since the different formats have become popular, its
 | 
					 | 
				
			||||||
  always good to make it easier for bots to parse the logs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 0.4.1 on 28.04.2024
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Filter out vouchers that are redeemed twice, due to bulk turn-in. If you
 | 
					 | 
				
			||||||
  redeem a singular voucher for value X, and then redeem the rest of your
 | 
					 | 
				
			||||||
  vouchers - say KWS vouchers - in bulk, the first voucher of value X will
 | 
					 | 
				
			||||||
  appear again in the logs. It appears twice in the logs, but only counts
 | 
					 | 
				
			||||||
  once.
 | 
					 | 
				
			||||||
* Add the market name to the trading log entries.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 0.4.0 on 13.04.2024
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Change layout of the results into System -> Faction -> Transaction.
 | 
					 | 
				
			||||||
  Many people who contribute *a lot* of things to the BGS have preferred such
 | 
					 | 
				
			||||||
  a layout to find the right things to post to various discord guilds/threads.
 | 
					 | 
				
			||||||
* Sort all systems in the new overview by name. It just makes them easier to
 | 
					 | 
				
			||||||
  find when there are a lot of entries.
 | 
					 | 
				
			||||||
* Add a button to deselect/select all buttons.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 0.3.7 on 29.01.2024
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Fix wrong locations of BGS action if you remain on your carrier while its
 | 
					* Fix wrong locations of BGS action if you remain on your carrier while its
 | 
				
			||||||
  jumping to a new system.
 | 
					  jumping to a new system.
 | 
				
			||||||
* Identify a capital ship in a high CZ by its music.
 | 
					* Identify a capital ship in a high CZ by its music.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.3.6 on 25.10.2023
 | 
					# 0.3.6 on 25.10.2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* U17 introduced invalid JSON into the player journal. EliteBGS can now skip over
 | 
					* U17 introduced invalid JSON into the player journal. EliteBGS can now skip over
 | 
				
			||||||
  those and keep processing. This way players won't have to delete lines in their
 | 
					  those and keep processing. This way players won't have to delete lines in their
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								EliteBGS/docs/combatzone.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								EliteBGS/docs/combatzone.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 68 KiB  | 
@ -26,7 +26,7 @@ You can download the **latest** version **0.3.7** at CodeBerg:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Or alternatively from my server:
 | 
					Or alternatively from my server:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [https://bgs.n0la.org/elitebgs-0.3.7.zip](https://bgs.n0la.org/elitebgs-0.3.7.zip)
 | 
					* [https://bgs.n0la.org/elitebgs-0.3.6.zip](https://bgs.n0la.org/elitebgs-0.3.7.zip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Old Versions
 | 
					## Old Versions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								EliteBGS/docs/main-page.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								EliteBGS/docs/main-page.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 67 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 67 KiB  | 
							
								
								
									
										15
									
								
								EliteBGS/mkdocs.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								EliteBGS/mkdocs.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					site_name: EliteBGS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					markdown_extensions:
 | 
				
			||||||
 | 
					    - pymdownx.snippets:
 | 
				
			||||||
 | 
					          check_paths: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					theme:
 | 
				
			||||||
 | 
					    name: lumen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav:
 | 
				
			||||||
 | 
					    - Overview: 'index.md'
 | 
				
			||||||
 | 
					    - "Detailed Description": 'description.md'
 | 
				
			||||||
 | 
					    - "Combat Zones": 'combatzones.md'
 | 
				
			||||||
 | 
					    - FAQ: 'faq.md'
 | 
				
			||||||
 | 
					    - Changelog: 'CHANGELOG.md'
 | 
				
			||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
EDBGS is a project containing the EliteBGS BGS application. It also contains the dotnet
 | 
					EDBGS is a project containing the EliteBGS BGS application. It also contains the dotnet
 | 
				
			||||||
class library EDPlayerJournal, which reads and parses Elite Dangerous player journals.
 | 
					class library EDPlayerJournal, which reads and parses Elite Dangerous player journals.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See [https://salusinvicta.org/bgstool/](https://salusinvicta.org/bgstool/) for further details.
 | 
					See [https://bgs.n0la.org/](https://bgs.n0la.org) for further details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The tool helps with creating BGS reports for squadrons that support factions in
 | 
					The tool helps with creating BGS reports for squadrons that support factions in
 | 
				
			||||||
Elite: Dangerous that can be copy and pasted into a Discord server. It finds all BGS
 | 
					Elite: Dangerous that can be copy and pasted into a Discord server. It finds all BGS
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user