Compare commits
	
		
			No commits in common. "5ea288ee86c5000bf1fc4d0503fcd4344307c74a" and "d7dc9bd904105e244b4162185b38b2d569013a0e" have entirely different histories.
		
	
	
		
			5ea288ee86
			...
			d7dc9bd904
		
	
		
@ -19,36 +19,20 @@ public class CombatZone : Transaction {
 | 
			
		||||
    public bool? SpecOps { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether allied captain objective was won
 | 
			
		||||
    /// Whether captain was won
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool? AlliedCaptain { get; set; }
 | 
			
		||||
    public bool? Captain { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether enemy captain objective was won
 | 
			
		||||
    /// Whether correspondent objective was won
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool? EnemyCaptain { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether the allied correspondent objective was won
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool? AlliedCorrespondent { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether the enemy correspondent objective was won
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool? EnemyCorrespondent { get; set; }
 | 
			
		||||
    public bool? Correspondent { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether cap ship objective was won
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool? CapitalShip { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// If we have a combat zone, this might point to the settlement
 | 
			
		||||
    /// in question.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string? Settlement { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// How many optional objectives were completed?
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@ -57,14 +41,7 @@ public class CombatZone : Transaction {
 | 
			
		||||
            if (IsGround) {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            return new List<bool?>() { 
 | 
			
		||||
                SpecOps, 
 | 
			
		||||
                AlliedCaptain,
 | 
			
		||||
                EnemyCaptain,
 | 
			
		||||
                AlliedCorrespondent,
 | 
			
		||||
                EnemyCorrespondent,
 | 
			
		||||
                CapitalShip 
 | 
			
		||||
            }
 | 
			
		||||
            return new List<bool?>() { SpecOps, Captain, Correspondent, CapitalShip }
 | 
			
		||||
                .Where(x => x != null && x == true)
 | 
			
		||||
                .Count()
 | 
			
		||||
                ;
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ namespace EDPlayerJournal.BGS;
 | 
			
		||||
/// faction to another. Both sometimes gain influence.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class InfluenceSupport : Transaction {
 | 
			
		||||
    public MissionInfluence? Influence { get; set; } = null;
 | 
			
		||||
    public string Influence { get; set; } = "";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Relevant mission completed entry
 | 
			
		||||
@ -46,7 +46,7 @@ public class InfluenceSupport : Transaction {
 | 
			
		||||
 | 
			
		||||
        builder.AppendFormat("Influence gained from \"{0}\": \"{1}\"",
 | 
			
		||||
            missionname,
 | 
			
		||||
            Influence == null ? "NONE" : Influence.TrendAdjustedInfluence
 | 
			
		||||
            string.IsNullOrEmpty(Influence) ? "NONE" : Influence
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        return builder.ToString();
 | 
			
		||||
 | 
			
		||||
@ -38,14 +38,7 @@ public class MissionCompleted : Transaction {
 | 
			
		||||
                return "";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return string.Join("",
 | 
			
		||||
                CompletedEntry
 | 
			
		||||
                .Mission
 | 
			
		||||
                .GetInfluenceForFaction(Faction, SystemAddress)
 | 
			
		||||
                .Select(x => x.Influence)
 | 
			
		||||
                .ToArray()
 | 
			
		||||
                )
 | 
			
		||||
                ;
 | 
			
		||||
            return (CompletedEntry.Mission.GetInfluenceForFaction(Faction, SystemAddress) ?? "");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -77,10 +70,8 @@ public class MissionCompleted : Transaction {
 | 
			
		||||
        var influence = CompletedEntry.Mission.GetInfluenceForFaction(Faction, SystemAddress);
 | 
			
		||||
 | 
			
		||||
        builder.AppendFormat("{0}", MissionName);
 | 
			
		||||
        if (influence != null && influence.Length > 0) {
 | 
			
		||||
            builder.AppendFormat(", Influence: {0}", 
 | 
			
		||||
                influence.Select(x => x.InfluenceAmount).Sum()
 | 
			
		||||
                );
 | 
			
		||||
        if (influence != "") {
 | 
			
		||||
            builder.AppendFormat(", Influence: {0}", influence);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return builder.ToString();
 | 
			
		||||
 | 
			
		||||
@ -13,21 +13,6 @@ public class MissionFailed : Transaction {
 | 
			
		||||
        Failed = failed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Returns the amount of influence generated by failing this mission. The
 | 
			
		||||
    /// system returns no influence for one INF missions, but sadly also for
 | 
			
		||||
    /// when the influence had no affect at all (i.e. during a war).
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public long InfluenceAmount {
 | 
			
		||||
        get {
 | 
			
		||||
            if (Mission == null || string.IsNullOrEmpty(Mission.Influence)) {
 | 
			
		||||
                return -1;
 | 
			
		||||
            } else {
 | 
			
		||||
                return Mission.Influence.Length * -1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override int CompareTo(Transaction? other) {
 | 
			
		||||
        if (other == null || other.GetType() != typeof(MissionFailed)) {
 | 
			
		||||
            return -1;
 | 
			
		||||
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
using EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
namespace EDPlayerJournal.BGS.Parsers;
 | 
			
		||||
 | 
			
		||||
internal class ApproachSettlementParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        ApproachSettlementEntry? approach = entry as ApproachSettlementEntry;
 | 
			
		||||
        if (approach == null || string.IsNullOrEmpty(approach.Name)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        context.Settlement = approach.Name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
using EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
namespace EDPlayerJournal.BGS.Parsers;
 | 
			
		||||
 | 
			
		||||
internal class CarrierJumpParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        CarrierJump? jump = entry as CarrierJump;
 | 
			
		||||
 | 
			
		||||
        if (jump == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!jump.Docked) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        context.CurrentSystem = jump.StarSystem;
 | 
			
		||||
        context.CurrentSystemAddress = jump.SystemAddress;
 | 
			
		||||
 | 
			
		||||
        context.SystemsByID.TryAdd(jump.SystemAddress, jump.StarSystem);
 | 
			
		||||
 | 
			
		||||
        if (!string.IsNullOrEmpty(jump.SystemFaction)) {
 | 
			
		||||
            context.ControllingFaction = jump.SystemFaction;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (jump.SystemFactions != null && jump.SystemFactions.Count > 0) {
 | 
			
		||||
            context.SystemFactions[jump.StarSystem] = jump.SystemFactions;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
using EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
namespace EDPlayerJournal.BGS.Parsers;
 | 
			
		||||
 | 
			
		||||
internal class MusicParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        MusicEntry? entryMusic = (MusicEntry)entry;
 | 
			
		||||
 | 
			
		||||
        if (entryMusic == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (string.Compare(entryMusic.MusicTrack, "Combat_CapitalShip") == 0) {
 | 
			
		||||
            context.HaveSeenCapShip = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,65 +0,0 @@
 | 
			
		||||
using EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
namespace EDPlayerJournal.BGS;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// With ship targeted we might find out to which faction a given NPC belonged. This is
 | 
			
		||||
/// useful later when said NPC gets killed or murdered.
 | 
			
		||||
/// </summary>
 | 
			
		||||
internal class ShipTargetedParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        ShipTargetedEntry? entry = e as ShipTargetedEntry;
 | 
			
		||||
        if (entry == null) {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Scan happens in stages, and sometimes this information is not known
 | 
			
		||||
        // yet. Do now throw an error, this is expected behaviour.
 | 
			
		||||
        if (!string.IsNullOrEmpty(entry.PilotNameLocalised) &&
 | 
			
		||||
            !string.IsNullOrEmpty(entry.Faction)) {
 | 
			
		||||
            context.NPCFaction.TryAdd(entry.PilotNameLocalised, entry.Faction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        string? faction = context.LastRecordedAwardingFaction;
 | 
			
		||||
 | 
			
		||||
        // We have seen a captain?
 | 
			
		||||
        if (NPCs.IsWarzoneCaptain(entry.PilotName)) {
 | 
			
		||||
            // if we have faction information, we can compare it to figure out
 | 
			
		||||
            // whether it is the enemy or allied faction. but this is not always
 | 
			
		||||
            // possible. In such a case we assume we have seen the enemy captain.
 | 
			
		||||
            if (!string.IsNullOrEmpty(entry.Faction) &&
 | 
			
		||||
                !string.IsNullOrEmpty(faction)) {
 | 
			
		||||
                if (string.Compare(faction, entry.Faction) != 0) {
 | 
			
		||||
                    context.HaveSeenEnemyCaptain = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    context.HaveSeenAlliedCaptain = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                context.HaveSeenEnemyCaptain = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Spec ops?
 | 
			
		||||
        if (NPCs.IsSpecOps(entry.PilotName)) {
 | 
			
		||||
            context.HaveSeenSpecOps = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Correspondent?
 | 
			
		||||
        if (NPCs.IsWarzoneCorrespondent(entry.PilotName)) {
 | 
			
		||||
            // if we have faction information, we can compare it to figure out
 | 
			
		||||
            // whether it is the enemy or allied faction. but this is not always
 | 
			
		||||
            // possible. In such a case we assume we have seen the enemy
 | 
			
		||||
            // correspondent.
 | 
			
		||||
            if (!string.IsNullOrEmpty(entry.Faction) &&
 | 
			
		||||
                !string.IsNullOrEmpty(faction)) {
 | 
			
		||||
                if (string.Compare(faction, entry.Faction) != 0) {
 | 
			
		||||
                    context.HaveSeenEnemyCorrespondent = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    context.HaveSeenAlliedCorrespondent = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                context.HaveSeenEnemyCorrespondent = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -137,6 +137,41 @@ internal class DockedParser : ITransactionParserPart {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// With ship targeted we might find out to which faction a given NPC belonged. This is
 | 
			
		||||
/// useful later when said NPC gets killed or murdered.
 | 
			
		||||
/// </summary>
 | 
			
		||||
internal class ShipTargetedParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        ShipTargetedEntry? entry = e as ShipTargetedEntry;
 | 
			
		||||
        if (entry == null) {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Scan happens in stages, and sometimes this information is not known
 | 
			
		||||
        // yet. Do now throw an error, this is expected behaviour.
 | 
			
		||||
        if (!string.IsNullOrEmpty(entry.PilotNameLocalised) &&
 | 
			
		||||
            !string.IsNullOrEmpty(entry.Faction)) {
 | 
			
		||||
            context.NPCFaction.TryAdd(entry.PilotNameLocalised, entry.Faction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We have seen a captain?
 | 
			
		||||
        if (NPCs.IsWarzoneCaptain(entry.PilotName)) {
 | 
			
		||||
            context.HaveSeenCaptain = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Spec ops?
 | 
			
		||||
        if (NPCs.IsSpecOps(entry.PilotName)) {
 | 
			
		||||
            context.HaveSeenSpecOps = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Correspondent?
 | 
			
		||||
        if (NPCs.IsWarzoneCorrespondent(entry.PilotName)) {
 | 
			
		||||
            context.HaveSeenCorrespondent = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Commit crime can result in a transaction, especially if the crime committed is
 | 
			
		||||
/// murder.
 | 
			
		||||
@ -298,20 +333,20 @@ internal class MissionCompletedParser : ITransactionParserPart {
 | 
			
		||||
                    if (context.CurrentSystemAddress == null) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    other.Value.Add(context.CurrentSystemAddress.Value, new MissionInfluence());
 | 
			
		||||
                    other.Value.Add(context.CurrentSystemAddress.Value, "");
 | 
			
		||||
                    // Mission gave no influence to the target faction, so we assume
 | 
			
		||||
                    // the target faction was in the same system.
 | 
			
		||||
                } else if (string.Compare(source_faction_name, faction, true) == 0) {
 | 
			
		||||
                    // This happens if the source faction is not getting any influence
 | 
			
		||||
                    // This could be if the source faction is in a conflict, and thus does
 | 
			
		||||
                    // not gain any influence at all.
 | 
			
		||||
                    other.Value.Add(accepted_location.SystemAddress, new MissionInfluence());
 | 
			
		||||
                    other.Value.Add(accepted_location.SystemAddress, "");
 | 
			
		||||
 | 
			
		||||
                    // Just check if the target/source faction are the same, in which case
 | 
			
		||||
                    // we also have to make an additional entry
 | 
			
		||||
                    if (string.Compare(source_faction_name, target_faction_name, true) == 0 &&
 | 
			
		||||
                        context.CurrentSystemAddress != null) {
 | 
			
		||||
                        other.Value.Add(context.CurrentSystemAddress.Value, new MissionInfluence());
 | 
			
		||||
                        other.Value.Add(context.CurrentSystemAddress.Value, "");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -632,10 +667,6 @@ internal class ReceiveTextParser : ITransactionParserPart {
 | 
			
		||||
 | 
			
		||||
internal class DiedParser : ITransactionParserPart {
 | 
			
		||||
    public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
 | 
			
		||||
        // Death only matters in ship. On foot you can just redeploy with the dropship.
 | 
			
		||||
        if (context.IsOnFoot) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // You can't complete a combat zone if you die in it. Others might keep it open
 | 
			
		||||
        // for you, but still you will not have completed it unless you jump back in.
 | 
			
		||||
        context.ResetCombatZone();
 | 
			
		||||
@ -663,9 +694,7 @@ internal class CommanderParser : ITransactionParserPart {
 | 
			
		||||
public class TransactionParser {
 | 
			
		||||
    private static Dictionary<string, ITransactionParserPart> ParserParts { get; } = new()
 | 
			
		||||
    {
 | 
			
		||||
        { Events.ApproachSettlement, new ApproachSettlementParser() },
 | 
			
		||||
        { Events.CapShipBond, new CapShipBondParser() },
 | 
			
		||||
        { Events.CarrierJump, new CarrierJumpParser() },
 | 
			
		||||
        { Events.Commander, new CommanderParser() },
 | 
			
		||||
        { Events.CommitCrime, new CommitCrimeParser() },
 | 
			
		||||
        { Events.Died, new DiedParser() },
 | 
			
		||||
@ -684,7 +713,6 @@ public class TransactionParser {
 | 
			
		||||
        { Events.MissionFailed, new MissionFailedParser() },
 | 
			
		||||
        { Events.Missions, new MissionsParser() },
 | 
			
		||||
        { Events.MultiSellExplorationData, new MultiSellExplorationDataParser() },
 | 
			
		||||
        { Events.Music, new MusicParser() },
 | 
			
		||||
        { Events.ReceiveText, new ReceiveTextParser() },
 | 
			
		||||
        { Events.RedeemVoucher, new RedeemVoucherParser() },
 | 
			
		||||
        { Events.SearchAndRescue, new SearchAndRescueParser() },
 | 
			
		||||
 | 
			
		||||
@ -51,16 +51,9 @@ internal class TransactionParserContext {
 | 
			
		||||
    public ulong? HighestCombatBond { get; set; }
 | 
			
		||||
 | 
			
		||||
    public bool HaveSeenCapShip { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenAlliedCaptain { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenEnemyCaptain { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenCaptain { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenSpecOps { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenAlliedCorrespondent { get; set; } = false;
 | 
			
		||||
    public bool HaveSeenEnemyCorrespondent { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Current Odyssey settlement.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string? Settlement { get; set; } = null;
 | 
			
		||||
    public bool HaveSeenCorrespondent { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Returns true if the current session is legacy
 | 
			
		||||
@ -120,7 +113,6 @@ internal class TransactionParserContext {
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void LeftInstance() {
 | 
			
		||||
        CurrentInstanceType = null;
 | 
			
		||||
        Settlement = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void DiscernCombatZone(TransactionList transactions, Entry e) {
 | 
			
		||||
@ -200,11 +192,7 @@ internal class TransactionParserContext {
 | 
			
		||||
            if (HaveSeenCapShip) {
 | 
			
		||||
                grade = CombatZones.DifficultyHigh;
 | 
			
		||||
            } else {
 | 
			
		||||
                int warzoneNpcs = new List<bool>() { 
 | 
			
		||||
                    HaveSeenEnemyCaptain, 
 | 
			
		||||
                    HaveSeenEnemyCorrespondent, 
 | 
			
		||||
                    HaveSeenSpecOps 
 | 
			
		||||
                }
 | 
			
		||||
                int warzoneNpcs = new List<bool>() { HaveSeenCaptain, HaveSeenCorrespondent, HaveSeenSpecOps }
 | 
			
		||||
                                    .Where(x => x == true)
 | 
			
		||||
                                    .Count()
 | 
			
		||||
                                    ;
 | 
			
		||||
@ -229,16 +217,13 @@ internal class TransactionParserContext {
 | 
			
		||||
            System = CurrentSystem,
 | 
			
		||||
            Faction = faction,
 | 
			
		||||
            IsLegacy = IsLegacy,
 | 
			
		||||
            Settlement = Settlement,
 | 
			
		||||
            Grade = grade,
 | 
			
		||||
            Type = cztype,
 | 
			
		||||
            // Sad truth is, if HaveSeenXXX is false, we just don't know for certain
 | 
			
		||||
            CapitalShip = HaveSeenCapShip ? true : null,
 | 
			
		||||
            SpecOps = HaveSeenSpecOps ? true : null,
 | 
			
		||||
            EnemyCorrespondent = HaveSeenEnemyCorrespondent ? true : null,
 | 
			
		||||
            AlliedCorrespondent = HaveSeenAlliedCorrespondent ? true : null,
 | 
			
		||||
            EnemyCaptain = HaveSeenEnemyCaptain ? true : null,
 | 
			
		||||
            AlliedCaptain = HaveSeenAlliedCaptain ? true : null,
 | 
			
		||||
            Correspondent = HaveSeenCorrespondent ? true : null,
 | 
			
		||||
            Captain = HaveSeenCaptain ? true : null,
 | 
			
		||||
        };
 | 
			
		||||
        zone.Entries.Add(e);
 | 
			
		||||
        transactions.Add(zone);
 | 
			
		||||
@ -261,10 +246,8 @@ internal class TransactionParserContext {
 | 
			
		||||
    public void ResetCombatZone() {
 | 
			
		||||
        HighestCombatBond = null;
 | 
			
		||||
        HaveSeenCapShip = false;
 | 
			
		||||
        HaveSeenAlliedCaptain = false;
 | 
			
		||||
        HaveSeenEnemyCaptain = false;
 | 
			
		||||
        HaveSeenAlliedCorrespondent = false;
 | 
			
		||||
        HaveSeenEnemyCorrespondent = false;
 | 
			
		||||
        HaveSeenCaptain = false;
 | 
			
		||||
        HaveSeenCorrespondent = false;
 | 
			
		||||
        HaveSeenSpecOps = false;
 | 
			
		||||
        LastRecordedAwardingFaction = null;
 | 
			
		||||
        OnFootKills = 0;
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,16 @@ public class Vouchers : Transaction {
 | 
			
		||||
        Entries.Add(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override bool SystemContribution {
 | 
			
		||||
        get {
 | 
			
		||||
            if (Faction == Factions.PilotsFederation && Type == "Combat Bond") {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public long TotalSum {
 | 
			
		||||
        get {
 | 
			
		||||
            if (Faction == null) {
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,6 @@ public class Credits {
 | 
			
		||||
            return string.Format("{0:0.00}M", millions);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return string.Format("{0}", amount);
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -107,7 +107,6 @@ public class EnglishMissionNames {
 | 
			
		||||
        {"Mission_Rescue_Elections_name", "Liberate Hostages (Election)" },
 | 
			
		||||
        {"Mission_Rescue_name", "Liberate Hostages" },
 | 
			
		||||
        {"Mission_Rescue_Planet_Expansion_name", "Planet Rescue (Expansion)" },
 | 
			
		||||
        {"Mission_Rescue_Planet_Retreat_name", "Planet Rescue (Retreat)" },
 | 
			
		||||
        {"Mission_Rescue_Planet_name", "Planet Rescue"},
 | 
			
		||||
        {"MISSION_Salvage_CivilUnrest_name", "Salvage (Civil Unrest)"},
 | 
			
		||||
        {"MISSION_Salvage_Expansion_name", "Salvage (Expansion)"},
 | 
			
		||||
@ -130,8 +129,6 @@ public class EnglishMissionNames {
 | 
			
		||||
        {"Mission_TW_Massacre_Medusa_Singular_name", "Kill Medusa" },
 | 
			
		||||
        {"Mission_TW_Massacre_Scout_Plural_name", "Kill Scouts" },
 | 
			
		||||
        {"Mission_TW_OnFoot_Reboot_Occupied_MB_name", "Reboot Settlement (Thargoid)" },
 | 
			
		||||
        {"Mission_TW_OnFoot_Reboot_NR_name", "Reboot Settlement (Thargoid)" },
 | 
			
		||||
        {"Mission_TW_OnFoot_Reboot_MB_name", "Reboot Settlement (Thargoid)" },
 | 
			
		||||
        {"Mission_TW_PassengerEvacuation_Burning_name", "Passenger Evacuation (Significant Damage)" },
 | 
			
		||||
        {"Mission_TW_PassengerEvacuation_UnderAttack_name", "Passenger Evacuation (Thargoid Invasion)" },
 | 
			
		||||
        {"Mission_TW_Rescue_UnderAttack_name", "Rescue (Thargoid Attack)" },
 | 
			
		||||
 | 
			
		||||
@ -1,48 +0,0 @@
 | 
			
		||||
namespace EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
public class ApproachSettlementEntry : Entry {
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Settlement name
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string? Name { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Market ID of the settlement
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public long? MarketID { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// System ID
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public long? SystemAddress { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Body ID
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public long? BodyID { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Name of the planet
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string? BodyName { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Planet latitude
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public double Latitude { get; set; } = 0.0;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Planet longitude
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public double Longitude { get; set; } = 0.0;
 | 
			
		||||
 | 
			
		||||
    protected override void Initialise() {
 | 
			
		||||
        Name = JSON.Value<string?>("Name");
 | 
			
		||||
        MarketID = JSON.Value<long?>("MarketID");
 | 
			
		||||
        SystemAddress = JSON.Value<long?>("SystemID");
 | 
			
		||||
        BodyID = JSON.Value<long?>("BodyID");
 | 
			
		||||
        BodyName = JSON.Value<string?>("BodyName");
 | 
			
		||||
        Longitude = JSON.Value<double?>("Longitude") ?? 0.0;
 | 
			
		||||
        Latitude = JSON.Value<double?>("Latitude") ?? 0.0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
 | 
			
		||||
namespace EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
public class CarrierJump : Entry {
 | 
			
		||||
    public bool Docked { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
    public string? StationName { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    public string? StationType { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    public string? StarSystem { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    public ulong SystemAddress { get; set; } = 0;
 | 
			
		||||
 | 
			
		||||
    public string? SystemFaction { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    public List<Faction> SystemFactions { get; set; } = new List<Faction>();
 | 
			
		||||
 | 
			
		||||
    protected override void Initialise() {
 | 
			
		||||
        Docked = JSON.Value<bool?>("Docked") ?? false;
 | 
			
		||||
 | 
			
		||||
        StarSystem = JSON.Value<string>("StarSystem");
 | 
			
		||||
        SystemAddress = JSON.Value<ulong?>("SystemAddress") ?? 0;
 | 
			
		||||
 | 
			
		||||
        StationName = JSON.Value<string?>("StationName");
 | 
			
		||||
        StationType = JSON.Value<string?>("StationType");
 | 
			
		||||
 | 
			
		||||
        var faction = JSON.Value<JObject>("SystemFaction");
 | 
			
		||||
        if (faction != null) {
 | 
			
		||||
            SystemFaction = faction.Value<string>("Name");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var factions = JSON.Value<JArray>("Factions");
 | 
			
		||||
        if (factions != null) {
 | 
			
		||||
            foreach (JObject system_faction in factions) {
 | 
			
		||||
                Faction? f = Faction.FromJSON(system_faction);
 | 
			
		||||
                if (f != null) {
 | 
			
		||||
                    SystemFactions.Add(f);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -12,10 +12,8 @@ namespace EDPlayerJournal.Entries;
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Entry {
 | 
			
		||||
    private static readonly Dictionary<string, Type> classes = new Dictionary<string, Type> {
 | 
			
		||||
        { Events.ApproachSettlement, typeof(ApproachSettlementEntry) },
 | 
			
		||||
        { Events.Bounty, typeof(BountyEntry) },
 | 
			
		||||
        { Events.CapShipBond, typeof(CapShipBondEntry) },
 | 
			
		||||
        { Events.CarrierJump, typeof(CarrierJump) },
 | 
			
		||||
        { Events.Commander, typeof(CommanderEntry) },
 | 
			
		||||
        { Events.CommitCrime, typeof(CommitCrimeEntry) },
 | 
			
		||||
        { Events.Died, typeof(DiedEntry) },
 | 
			
		||||
@ -38,7 +36,6 @@ public class Entry {
 | 
			
		||||
        { Events.MissionRedirected, typeof(MissionRedirectedEntry) },
 | 
			
		||||
        { Events.Missions, typeof(MissionsEntry) },
 | 
			
		||||
        { Events.MultiSellExplorationData, typeof(MultiSellExplorationDataEntry) },
 | 
			
		||||
        { Events.Music, typeof(MusicEntry) },
 | 
			
		||||
        { Events.ReceiveText, typeof(ReceiveTextEntry) },
 | 
			
		||||
        { Events.RedeemVoucher, typeof(RedeemVoucherEntry) },
 | 
			
		||||
        { Events.SearchAndRescue, typeof(SearchAndRescueEntry) },
 | 
			
		||||
@ -66,15 +63,7 @@ public class Entry {
 | 
			
		||||
    public static Entry? Parse(string journalline) {
 | 
			
		||||
        using (JsonReader reader = new JsonTextReader(new StringReader(journalline))) {
 | 
			
		||||
            reader.DateParseHandling = DateParseHandling.None;
 | 
			
		||||
            JObject? json = null;
 | 
			
		||||
            try {
 | 
			
		||||
                json = JObject.Load(reader);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                throw new InvalidJournalEntryException(
 | 
			
		||||
                    "invalid JSON journal entry: " + journalline,
 | 
			
		||||
                    e
 | 
			
		||||
                    );
 | 
			
		||||
            }
 | 
			
		||||
            var json = JObject.Load(reader);
 | 
			
		||||
            if (json == null) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,8 @@
 | 
			
		||||
namespace EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
public class Events {
 | 
			
		||||
    public static readonly string ApproachSettlement = "ApproachSettlement";
 | 
			
		||||
    public static readonly string Bounty = "Bounty";
 | 
			
		||||
    public static readonly string CapShipBond = "CapShipBond";
 | 
			
		||||
    public static readonly string CarrierJump = "CarrierJump";
 | 
			
		||||
    public static readonly string Commander = "Commander";
 | 
			
		||||
    public static readonly string CommitCrime = "CommitCrime";
 | 
			
		||||
    public static readonly string Died = "Died";
 | 
			
		||||
@ -28,7 +26,6 @@ public class Events {
 | 
			
		||||
    public static readonly string MissionRedirected = "MissionRedirected";
 | 
			
		||||
    public static readonly string Missions = "Missions";
 | 
			
		||||
    public static readonly string MultiSellExplorationData = "MultiSellExplorationData";
 | 
			
		||||
    public static readonly string Music = "Music";
 | 
			
		||||
    public static readonly string ReceiveText = "ReceiveText";
 | 
			
		||||
    public static readonly string RedeemVoucher = "RedeemVoucher";
 | 
			
		||||
    public static readonly string SearchAndRescue = "SearchAndRescue";
 | 
			
		||||
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
namespace EDPlayerJournal.Entries;
 | 
			
		||||
 | 
			
		||||
public class MusicEntry : Entry {
 | 
			
		||||
    public string? MusicTrack { get; set; } = null;
 | 
			
		||||
 | 
			
		||||
    protected override void Initialise() {
 | 
			
		||||
        MusicTrack = JSON.Value<string?>("MusicTrack");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -6,7 +6,6 @@
 | 
			
		||||
public class InvalidJournalEntryException : Exception {
 | 
			
		||||
    public InvalidJournalEntryException() { }
 | 
			
		||||
    public InvalidJournalEntryException(string message) : base(message) { }
 | 
			
		||||
    public InvalidJournalEntryException(string message, Exception inner) : base(message, inner) { }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 | 
			
		||||
@ -17,11 +17,6 @@ public class JournalFile : IComparable<JournalFile>
 | 
			
		||||
    private static Regex update11regex = new Regex("Journal\\.([^\\.]+)\\.(\\d+).log");
 | 
			
		||||
    private static string iso8601 = "yyyyMMddTHHmmss";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A public list of errors encountered while parsing the journal files
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public List<Exception> Errors { get; private set; } = new List<Exception>();
 | 
			
		||||
 | 
			
		||||
    public static bool VerifyFile(string path) {
 | 
			
		||||
        string filename = Path.GetFileName(path);
 | 
			
		||||
 | 
			
		||||
@ -130,20 +125,15 @@ public class JournalFile : IComparable<JournalFile>
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        entries.Clear();
 | 
			
		||||
        Errors.Clear();
 | 
			
		||||
        foreach(var line in lines) {
 | 
			
		||||
            // Skip empty lines
 | 
			
		||||
            if (line.Trim().Length == 0) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
            Entry? entry = Entry.Parse(line);
 | 
			
		||||
            if (entry != null) {
 | 
			
		||||
                entries.Add(entry);
 | 
			
		||||
            }
 | 
			
		||||
            } catch (Exception ex) {
 | 
			
		||||
                Errors.Add(ex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,31 +36,6 @@ public class MissionInfluence {
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Influence { get; set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    public long InfluenceAmount {
 | 
			
		||||
        get {
 | 
			
		||||
            string trend = TrendAdjustedInfluence;
 | 
			
		||||
            return (long)
 | 
			
		||||
                   (trend.Count(x => x == '-') * -1) +
 | 
			
		||||
                    trend.Count(x => x == '+')
 | 
			
		||||
                   ;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Returns how much influence was made, represented in pluses for positive influence,
 | 
			
		||||
    /// and minuses with negative influence. This takes Trend (up, bad etc.) into account.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string TrendAdjustedInfluence {
 | 
			
		||||
        get {
 | 
			
		||||
            if (!string.IsNullOrEmpty(Trend) &&
 | 
			
		||||
                Trend.Contains("bad", StringComparison.OrdinalIgnoreCase)) {
 | 
			
		||||
                return new string('-', Influence.Length);
 | 
			
		||||
            } else {
 | 
			
		||||
                return new string('+', Influence.Length);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static MissionInfluence FromJSON(JObject obj) {
 | 
			
		||||
        MissionInfluence missionInfluence = new MissionInfluence();
 | 
			
		||||
 | 
			
		||||
@ -419,29 +394,27 @@ public class Mission : IComparable<Mission> {
 | 
			
		||||
    /// <param name="faction">Faction name in question.</param>
 | 
			
		||||
    /// <param name="systemaddr">Star System address</param>
 | 
			
		||||
    /// <returns>null if no entry was found, or a string denoting pluses for the amount influence gained.</returns>
 | 
			
		||||
    public MissionInfluence[]? GetInfluenceForFaction(string faction, ulong systemaddr) {
 | 
			
		||||
    public string? GetInfluenceForFaction(string faction, ulong systemaddr) {
 | 
			
		||||
        var results = FactionEffects
 | 
			
		||||
            .Where(x => string.Compare(x.Faction, faction) == 0)
 | 
			
		||||
            .SelectMany(x => x.Influences)
 | 
			
		||||
            .Where(x => (x.SystemAddress != null && x.SystemAddress == systemaddr))
 | 
			
		||||
            .Select(x => x)
 | 
			
		||||
            .Select(x => x.Influence)
 | 
			
		||||
            .ToArray()
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
        if (results == null || results.Length == 0) {
 | 
			
		||||
            return new MissionInfluence[0];
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return results;
 | 
			
		||||
        return string.Join("", results);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A convenient Dictionary containing all influences given out by faction,
 | 
			
		||||
    /// then by system address and then by influence handed out. Influence can
 | 
			
		||||
    /// be either a series of "+" for positive influence, or "-" for negative
 | 
			
		||||
    /// influence.
 | 
			
		||||
    /// then by system address and then by influence handed out.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Dictionary<string, Dictionary<ulong, MissionInfluence>> Influences {
 | 
			
		||||
    public Dictionary<string, Dictionary<ulong, string>> Influences {
 | 
			
		||||
        get {
 | 
			
		||||
            return FactionEffects
 | 
			
		||||
                .Where(x => x.Faction != null)
 | 
			
		||||
@ -449,10 +422,7 @@ public class Mission : IComparable<Mission> {
 | 
			
		||||
                    x => (x.Faction ?? string.Empty),
 | 
			
		||||
                    x => x.Influences
 | 
			
		||||
                            .Where(x => x.SystemAddress != null)
 | 
			
		||||
                            .ToDictionary(
 | 
			
		||||
                                x => (x.SystemAddress ?? 0), 
 | 
			
		||||
                                x => x
 | 
			
		||||
                                )
 | 
			
		||||
                            .ToDictionary(x => (x.SystemAddress ?? 0), x => x.Influence)
 | 
			
		||||
                    );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -22,12 +22,6 @@ public class PlayerJournal {
 | 
			
		||||
        ScanFiles();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<Exception> AllErrors {
 | 
			
		||||
        get {
 | 
			
		||||
            return Files.SelectMany(x => x.Errors).ToList();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<JournalFile> Files {
 | 
			
		||||
        get { return journalfiles; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -8,16 +8,11 @@ public enum ThargoidVessel {
 | 
			
		||||
    Basilisk = 4,
 | 
			
		||||
    Medusa = 5,
 | 
			
		||||
    Hydra = 6,
 | 
			
		||||
    // Includes Glaive and Scythe
 | 
			
		||||
    Hunter = 7,
 | 
			
		||||
    Glaive = 7,
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Thargoid drone
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Revenant = 8,
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// New thargoid drone in U17
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Banshee = 9,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class Thargoid {
 | 
			
		||||
@ -28,10 +23,8 @@ public class Thargoid {
 | 
			
		||||
        {    25000, ThargoidVessel.Revenant },
 | 
			
		||||
        {    65000, ThargoidVessel.Scout },
 | 
			
		||||
        {    75000, ThargoidVessel.Scout },
 | 
			
		||||
        // New in Update 17
 | 
			
		||||
        {   100000, ThargoidVessel.Banshee },
 | 
			
		||||
        // New in Update 15
 | 
			
		||||
        {  4500000, ThargoidVessel.Hunter },
 | 
			
		||||
        {  4500000, ThargoidVessel.Glaive },
 | 
			
		||||
        {  6500000, ThargoidVessel.Cyclops },
 | 
			
		||||
        { 20000000, ThargoidVessel.Basilisk },
 | 
			
		||||
        //{ 25000000, ThargoidVessel.Orthrus },
 | 
			
		||||
@ -53,7 +46,7 @@ public class Thargoid {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public static Dictionary<ThargoidVessel, string?> VesselNames { get; } = new() {
 | 
			
		||||
        { ThargoidVessel.Unknown, "(Unknown)" },
 | 
			
		||||
        { ThargoidVessel.Unknown, null },
 | 
			
		||||
        { ThargoidVessel.Revenant, "Revenant" },
 | 
			
		||||
        { ThargoidVessel.Scout, "Scout" },
 | 
			
		||||
        { ThargoidVessel.Orthrus, "Orthrus" },
 | 
			
		||||
@ -61,8 +54,7 @@ public class Thargoid {
 | 
			
		||||
        { ThargoidVessel.Basilisk, "Basilisk" },
 | 
			
		||||
        { ThargoidVessel.Medusa, "Medusa" },
 | 
			
		||||
        { ThargoidVessel.Hydra, "Hydra" },
 | 
			
		||||
        { ThargoidVessel.Hunter, "Hunter" },
 | 
			
		||||
        { ThargoidVessel.Banshee, "Banshee" },
 | 
			
		||||
        { ThargoidVessel.Glaive, "Glaive" },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public static ThargoidVessel GetVesselByPayout(ulong payout) {
 | 
			
		||||
 | 
			
		||||
@ -59,9 +59,9 @@ public class MissionTest {
 | 
			
		||||
        Assert.IsTrue(e.IsEmptyFaction);
 | 
			
		||||
        Assert.AreEqual(e.Faction, string.Empty);
 | 
			
		||||
 | 
			
		||||
        var influence = m.GetInfluenceForFaction("", 251012319587UL);
 | 
			
		||||
        string? influence = m.GetInfluenceForFaction("", 251012319587UL);
 | 
			
		||||
        Assert.IsNotNull(influence);
 | 
			
		||||
        Assert.AreEqual(influence[0].Influence, "+");
 | 
			
		||||
        Assert.AreEqual(influence, "+");
 | 
			
		||||
 | 
			
		||||
        e = m.FactionEffects[1];
 | 
			
		||||
        Assert.AreEqual(e.Faction, "Social LHS 6103 Confederation");
 | 
			
		||||
@ -101,25 +101,22 @@ public class MissionTest {
 | 
			
		||||
 | 
			
		||||
        Assert.AreEqual(effect.Reputation, "++");
 | 
			
		||||
 | 
			
		||||
        var influence = m.GetInfluenceForFaction("Salus Imperial Society", 1865919973739UL);
 | 
			
		||||
        Assert.IsNotNull(influence);
 | 
			
		||||
        Assert.IsTrue(influence.Length > 0);
 | 
			
		||||
        Assert.AreEqual(influence[0].Influence, "++");
 | 
			
		||||
        string? influence;
 | 
			
		||||
 | 
			
		||||
        influence = m.GetInfluenceForFaction("Salus Imperial Society", 1865919973739UL);
 | 
			
		||||
        Assert.AreEqual(influence, "++");
 | 
			
		||||
 | 
			
		||||
        influence = m.GetInfluenceForFaction("Salus Imperial Society", 1733186884306UL);
 | 
			
		||||
        Assert.IsNotNull(influence);
 | 
			
		||||
        Assert.IsTrue(influence.Length > 0);
 | 
			
		||||
        Assert.AreEqual(influence[0].Influence, "++");
 | 
			
		||||
        Assert.AreEqual(influence, "++");
 | 
			
		||||
 | 
			
		||||
        influence = m.GetInfluenceForFaction("Saelishi Saxons", 1733186884306UL);
 | 
			
		||||
        Assert.IsNotNull(influence);
 | 
			
		||||
        Assert.AreEqual(influence.Length, 0);
 | 
			
		||||
        Assert.IsNull(influence);
 | 
			
		||||
 | 
			
		||||
        // Only one entry are we only have Salus
 | 
			
		||||
        Assert.AreEqual(m.Influences.Count, 1);
 | 
			
		||||
        Assert.AreEqual(m.Influences["Salus Imperial Society"].Count, 2);
 | 
			
		||||
        Assert.AreEqual(m.Influences["Salus Imperial Society"][1865919973739UL].Influence, "++");
 | 
			
		||||
        Assert.AreEqual(m.Influences["Salus Imperial Society"][1733186884306UL].Influence, "++");
 | 
			
		||||
        Assert.AreEqual(m.Influences["Salus Imperial Society"][1865919973739UL], "++");
 | 
			
		||||
        Assert.AreEqual(m.Influences["Salus Imperial Society"][1733186884306UL], "++");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [TestMethod]
 | 
			
		||||
 | 
			
		||||
@ -19,13 +19,7 @@ public class TestTransactionParser {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var options = new TransactionParserOptions() {
 | 
			
		||||
            IgnoreInfluenceSupport = false,
 | 
			
		||||
            IgnoreExoBiology = false,
 | 
			
		||||
            IgnoreFleetCarrierFaction = false,
 | 
			
		||||
            IgnoreMarketBuy = false,
 | 
			
		||||
        };
 | 
			
		||||
        List<Transaction>? transactions = parser.Parse(entries, options);
 | 
			
		||||
        List<Transaction>? transactions = parser.Parse(entries);
 | 
			
		||||
        Assert.IsNotNull(transactions, "could not parse entries");
 | 
			
		||||
        Assert.AreEqual(transactions.Count, 3);
 | 
			
		||||
 | 
			
		||||
@ -150,14 +144,7 @@ public class TestTransactionParser {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var options = new TransactionParserOptions() {
 | 
			
		||||
            IgnoreInfluenceSupport = false,
 | 
			
		||||
            IgnoreExoBiology = false,
 | 
			
		||||
            IgnoreFleetCarrierFaction = false,
 | 
			
		||||
            IgnoreMarketBuy = false,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        List<Transaction>? transactions = parser.Parse(entries, options);
 | 
			
		||||
        List<Transaction>? transactions = parser.Parse(entries);
 | 
			
		||||
        Assert.IsNotNull(transactions, "could not parse entries");
 | 
			
		||||
        Assert.AreEqual(transactions.Count, 1);
 | 
			
		||||
        Assert.IsInstanceOfType(transactions[0], typeof(OrganicData), "result is not of type Organic Data");
 | 
			
		||||
 | 
			
		||||
@ -22,17 +22,14 @@ public class ThargoidKills {
 | 
			
		||||
        Assert.IsNotNull(transactions, "could not parse entries");
 | 
			
		||||
        Assert.AreEqual(transactions.Count, 3);
 | 
			
		||||
 | 
			
		||||
        // In recent updates the payout was changed, that's why this test reports unknown thargoid vessels
 | 
			
		||||
        // This test makes sure the new parser does not conflict with legacy values
 | 
			
		||||
        //
 | 
			
		||||
        Assert.IsInstanceOfType(transactions[0], typeof(ThargoidKill), "result is not of type ThargoidKill");
 | 
			
		||||
        Assert.AreEqual(transactions[0].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
 | 
			
		||||
        Assert.AreEqual(transactions[0].ThargoidType, EDPlayerJournal.ThargoidVessel.Scout);
 | 
			
		||||
 | 
			
		||||
        Assert.IsInstanceOfType(transactions[1], typeof(ThargoidKill), "result is not of type ThargoidKill");
 | 
			
		||||
        Assert.AreEqual(transactions[1].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
 | 
			
		||||
        Assert.AreEqual(transactions[1].ThargoidType, EDPlayerJournal.ThargoidVessel.Basilisk);
 | 
			
		||||
 | 
			
		||||
        Assert.IsInstanceOfType(transactions[2], typeof(ThargoidKill), "result is not of type ThargoidKill");
 | 
			
		||||
        Assert.AreEqual(transactions[2].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
 | 
			
		||||
        Assert.AreEqual(transactions[2].ThargoidType, EDPlayerJournal.ThargoidVessel.Scout);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [TestMethod]
 | 
			
		||||
 | 
			
		||||
@ -3,13 +3,13 @@ using System.Linq;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using EliteBGS.LogGenerator;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace EliteBGS;
 | 
			
		||||
 | 
			
		||||
public class DiscordLogGenerator {
 | 
			
		||||
    protected List<LogFormatter> formatters = new List<LogFormatter>() {
 | 
			
		||||
        new MissionFormat(),
 | 
			
		||||
        new FailedMissionFormat(),
 | 
			
		||||
        new MurderFormat(),
 | 
			
		||||
        new VoucherFormat(),
 | 
			
		||||
        new ThargoidFormatter(),
 | 
			
		||||
@ -23,41 +23,6 @@ public class DiscordLogGenerator {
 | 
			
		||||
        new SearchAndRescueFormat(),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    protected virtual string GetToolVersion() {
 | 
			
		||||
        Version v = Assembly.GetCallingAssembly().GetName().Version;
 | 
			
		||||
        string ver;
 | 
			
		||||
        if (v == null) {
 | 
			
		||||
            ver = "v?.?.?";
 | 
			
		||||
        } else {
 | 
			
		||||
            ver = "v" + v.ToString(3);
 | 
			
		||||
        }
 | 
			
		||||
        return string.Format("EliteBGS {0}", ver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected virtual DateTime? GetDateOfEarliestEntry(Objective objective) {
 | 
			
		||||
        var it = objective
 | 
			
		||||
            .Transactions
 | 
			
		||||
            .OrderBy(x => x.CompletedAtDateTime)
 | 
			
		||||
            .FirstOrDefault()
 | 
			
		||||
            ;
 | 
			
		||||
        if (it != null) {
 | 
			
		||||
            return it.CompletedAtDateTime;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected virtual DateTime? GetDateOfLatestEntry(Objective objective) {
 | 
			
		||||
        var it = objective
 | 
			
		||||
            .Transactions
 | 
			
		||||
            .OrderByDescending(x => x.CompletedAtDateTime)
 | 
			
		||||
            .FirstOrDefault()
 | 
			
		||||
            ;
 | 
			
		||||
        if (it != null) {
 | 
			
		||||
            return it.CompletedAtDateTime;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected virtual string GenerateSummary(Objective objective) {
 | 
			
		||||
        StringBuilder sb = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
@ -111,18 +76,7 @@ public class DiscordLogGenerator {
 | 
			
		||||
 | 
			
		||||
        string summary = GenerateSummary(objective);
 | 
			
		||||
 | 
			
		||||
        log.AppendFormat("**Log Generated:** {0} by {1}\n", 
 | 
			
		||||
            DateTime.Now.ToString("dd/MM/yyyy"),
 | 
			
		||||
            GetToolVersion()
 | 
			
		||||
            );
 | 
			
		||||
        var earliest = GetDateOfEarliestEntry(objective);
 | 
			
		||||
        var latest = GetDateOfLatestEntry(objective);
 | 
			
		||||
        if (earliest != null && latest != null) {
 | 
			
		||||
            log.AppendFormat("**Date:** {0} - {1}\n",
 | 
			
		||||
                GetDateOfEarliestEntry(objective),
 | 
			
		||||
                GetDateOfLatestEntry(objective)
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
        log.AppendFormat("**Date:** {0}\n", DateTime.Now.ToString("dd/MM/yyyy"));
 | 
			
		||||
        log.AppendFormat("**Target:** {0}\n", location);
 | 
			
		||||
        if (!string.IsNullOrEmpty(summary)) {
 | 
			
		||||
            log.AppendFormat("**Summary**: {0}\n", summary);
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <TargetFramework>net7.0-windows</TargetFramework>
 | 
			
		||||
    <OutputType>WinExe</OutputType>
 | 
			
		||||
    <Version>0.3.7</Version>
 | 
			
		||||
    <Version>0.3.3</Version>
 | 
			
		||||
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
 | 
			
		||||
    <UseWindowsForms>true</UseWindowsForms>
 | 
			
		||||
    <UseWPF>true</UseWPF>
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ class CombatZoneFormat : LogFormatter {
 | 
			
		||||
        var logs = objective
 | 
			
		||||
            .EnabledOfType<CombatZone>()
 | 
			
		||||
            .OrderBy(x => (CombatZones.DifficultyRank(x.Grade) ?? 0))
 | 
			
		||||
            .GroupBy(x => new { x.Type, x.Grade, x.Settlement })
 | 
			
		||||
            .GroupBy(x => new { x.Type, x.Grade })
 | 
			
		||||
            .ToDictionary(x => x.Key, x => x.ToList())
 | 
			
		||||
            ;
 | 
			
		||||
        StringBuilder builder = new StringBuilder();
 | 
			
		||||
@ -23,11 +23,6 @@ class CombatZoneFormat : LogFormatter {
 | 
			
		||||
            int optionals = log.Value
 | 
			
		||||
                                .Sum(x => x.OptionalObjectivesCompleted)
 | 
			
		||||
                                ;
 | 
			
		||||
            var settlements = log.Value
 | 
			
		||||
                                .Select(x => x.Settlement)
 | 
			
		||||
                                .Distinct()
 | 
			
		||||
                                ;
 | 
			
		||||
            string settl = string.Join(", ", settlements);
 | 
			
		||||
            if (!string.IsNullOrEmpty(log.Key.Grade)) {
 | 
			
		||||
                builder.AppendFormat("Won {0}x {1} {2} Combat Zone(s)",
 | 
			
		||||
                    log.Value.Count,
 | 
			
		||||
@ -44,9 +39,6 @@ class CombatZoneFormat : LogFormatter {
 | 
			
		||||
            if (optionals > 0) {
 | 
			
		||||
                builder.AppendFormat(" (with {0} optional objectives)", optionals);
 | 
			
		||||
            }
 | 
			
		||||
            if (!string.IsNullOrEmpty(settl)) {
 | 
			
		||||
                builder.AppendFormat(" (at {0})", settl);
 | 
			
		||||
            }
 | 
			
		||||
            builder.Append("\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								EliteBGS/LogGenerator/FailedMissionFormat.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								EliteBGS/LogGenerator/FailedMissionFormat.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using EDPlayerJournal.BGS;
 | 
			
		||||
 | 
			
		||||
namespace EliteBGS.LogGenerator;
 | 
			
		||||
 | 
			
		||||
public class FailedMissionFormat : LogFormatter {
 | 
			
		||||
    public string GenerateLog(Objective objective) {
 | 
			
		||||
        var missions = objective.EnabledOfType<MissionFailed>();
 | 
			
		||||
 | 
			
		||||
        if (missions.Count <= 0) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder builder = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
        var grouping = missions
 | 
			
		||||
                        .GroupBy(x => x.Mission.IsOnFoot)
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
        foreach (var group in grouping) {
 | 
			
		||||
            int amount = group.Count();
 | 
			
		||||
 | 
			
		||||
            if (group.Key) {
 | 
			
		||||
                builder.AppendFormat("Failed {0} On Foot Mission(s)\n", amount);
 | 
			
		||||
            } else {
 | 
			
		||||
                builder.AppendFormat("Failed {0} Ship Mission(s)\n", amount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return builder.ToString().Trim();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public string GenerateSummary(Objective objective) {
 | 
			
		||||
        var missions = objective.EnabledOfType<MissionFailed>();
 | 
			
		||||
 | 
			
		||||
        if (missions.Count <= 0) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder sb = new();
 | 
			
		||||
 | 
			
		||||
        int onFootFails = missions.Where(x => x.Mission.IsOnFoot).Count();
 | 
			
		||||
        int shipFails = missions.Where(x => !x.Mission.IsOnFoot).Count();
 | 
			
		||||
 | 
			
		||||
        sb.Append("Fails: ");
 | 
			
		||||
        if (onFootFails > 0) {
 | 
			
		||||
            sb.AppendFormat("{0} Ground", onFootFails);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (shipFails > 0) {
 | 
			
		||||
            if (onFootFails > 0) {
 | 
			
		||||
                sb.Append(", ");
 | 
			
		||||
            }
 | 
			
		||||
            sb.AppendFormat("{0} Ship", shipFails);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return sb.ToString();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -6,72 +6,17 @@ using EDPlayerJournal.BGS;
 | 
			
		||||
namespace EliteBGS.LogGenerator;
 | 
			
		||||
 | 
			
		||||
public class MissionFormat : LogFormatter {
 | 
			
		||||
    private string GenerateFailedLog(Objective objective) {
 | 
			
		||||
        var missions = objective.EnabledOfType<MissionFailed>();
 | 
			
		||||
 | 
			
		||||
        if (missions.Count <= 0) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder builder = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
        var grouping = missions
 | 
			
		||||
                        .GroupBy(x => x.Mission.IsOnFoot)
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
        foreach (var group in grouping) {
 | 
			
		||||
            int amount = group.Count();
 | 
			
		||||
 | 
			
		||||
            if (group.Key) {
 | 
			
		||||
                builder.AppendFormat("Failed {0} On Foot Mission(s)\n", amount);
 | 
			
		||||
            } else {
 | 
			
		||||
                builder.AppendFormat("Failed {0} Ship Mission(s)\n", amount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return builder.ToString().Trim();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private string GenerateFailedSummary(Objective objective) {
 | 
			
		||||
        var missions = objective.EnabledOfType<MissionFailed>();
 | 
			
		||||
 | 
			
		||||
        if (missions.Count <= 0) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder sb = new();
 | 
			
		||||
 | 
			
		||||
        int onFootFails = missions.Where(x => x.Mission.IsOnFoot).Count();
 | 
			
		||||
        int shipFails = missions.Where(x => !x.Mission.IsOnFoot).Count();
 | 
			
		||||
 | 
			
		||||
        sb.Append("Fails: ");
 | 
			
		||||
        if (onFootFails > 0) {
 | 
			
		||||
            sb.AppendFormat("{0} Ground", onFootFails);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (shipFails > 0) {
 | 
			
		||||
            if (onFootFails > 0) {
 | 
			
		||||
                sb.Append(", ");
 | 
			
		||||
            }
 | 
			
		||||
            sb.AppendFormat("{0} Ship", shipFails);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return sb.ToString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public string GenerateLog(Objective objective) {
 | 
			
		||||
        Dictionary<string, Dictionary<string, int>> collated = new();
 | 
			
		||||
        Dictionary<string, ulong> passengers = new();
 | 
			
		||||
        StringBuilder output = new StringBuilder();
 | 
			
		||||
        long total_influence = 0;
 | 
			
		||||
        int total_influence = 0;
 | 
			
		||||
 | 
			
		||||
        var missions = objective.EnabledOfType<MissionCompleted>();
 | 
			
		||||
        var support = objective.EnabledOfType<InfluenceSupport>();
 | 
			
		||||
        var failed = objective.EnabledOfType<MissionFailed>();
 | 
			
		||||
 | 
			
		||||
        if ((missions == null || missions.Count == 0) &&
 | 
			
		||||
            (support == null || support.Count == 0) &&
 | 
			
		||||
            (failed == null || failed.Count == 0)) {
 | 
			
		||||
            (support == null || support.Count == 0)) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -115,25 +60,17 @@ public class MissionFormat : LogFormatter {
 | 
			
		||||
 | 
			
		||||
        output.Append("\n");
 | 
			
		||||
 | 
			
		||||
        // Handle failed missions, and add them to the log and influence tally
 | 
			
		||||
        string failedlog = GenerateFailedLog(objective);
 | 
			
		||||
        if (!string.IsNullOrEmpty(failedlog)) {
 | 
			
		||||
            output.Append(failedlog);
 | 
			
		||||
            output.Append("\n");
 | 
			
		||||
        }
 | 
			
		||||
        total_influence += failed.Sum(x => x.InfluenceAmount);
 | 
			
		||||
 | 
			
		||||
        foreach (InfluenceSupport inf in support) {
 | 
			
		||||
            output.Append(inf.ToString());
 | 
			
		||||
            output.Append("\n");
 | 
			
		||||
            total_influence += inf.Influence.InfluenceAmount;
 | 
			
		||||
            total_influence += inf.Influence.Length;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (support.Count() > 0) {
 | 
			
		||||
            output.Append("\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (total_influence != 0) {
 | 
			
		||||
        if (total_influence > 0) {
 | 
			
		||||
            output.AppendFormat("Total Influence: {0}", total_influence);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -147,24 +84,13 @@ public class MissionFormat : LogFormatter {
 | 
			
		||||
            ;
 | 
			
		||||
        long support = objective
 | 
			
		||||
            .EnabledOfType<InfluenceSupport>()
 | 
			
		||||
            .Sum(x => x.Influence.InfluenceAmount)
 | 
			
		||||
            ;
 | 
			
		||||
        long failed = objective
 | 
			
		||||
            .EnabledOfType<MissionFailed>()
 | 
			
		||||
            .Sum(x => x.InfluenceAmount)
 | 
			
		||||
            .Sum(x => x.Influence.Length)
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
        if (influence == 0 && support == 0 && failed == 0) {
 | 
			
		||||
        if (influence + support <= 0) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        string failedsummary = GenerateFailedSummary(objective);
 | 
			
		||||
        string summary = string.Format("INF: {0}", influence + support + failed);
 | 
			
		||||
 | 
			
		||||
        if (!string.IsNullOrEmpty(failedsummary)) {
 | 
			
		||||
            string.Join("; ", summary, failedsummary);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return summary;
 | 
			
		||||
        return string.Format("INF: {0}", influence + support);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -120,10 +120,8 @@
 | 
			
		||||
                                                <Expander Header="Optional Objectives" Visibility="{Binding IsShipCombatZone}">
 | 
			
		||||
                                                    <StackPanel Orientation="Vertical">
 | 
			
		||||
                                                        <ToggleButton x:Name="CapitalShip" Margin="2,0,2,0" Content="Capital Ship" IsChecked="{Binding HasCapitalShip, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="AlliedCaptain" Margin="2,0,2,0" Content="Allied Captain" IsChecked="{Binding HasAlliedCaptain, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="EnemyCaptain" Margin="2,0,2,0" Content="Enemy Captain" IsChecked="{Binding HasEnemyCaptain, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="AlliedCorrespondent" Margin="2,0,2,0" Content="Allied Correspondent" IsChecked="{Binding HasAlliedCorrespondent, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="EnemyCorrespondent" Margin="2,0,2,0" Content="Enemy Correspondent" IsChecked="{Binding HasEnemyCorrespondent, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="Captain" Margin="2,0,2,0" Content="Captain" IsChecked="{Binding HasCaptain, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="Correspondent" Margin="2,0,2,0" Content="Correspondent" IsChecked="{Binding HasCorrespondent, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                        <ToggleButton x:Name="SpecOps" Margin="2,0,2,0" Content="Spec Ops" IsChecked="{Binding HasSpecOps, Mode=TwoWay}" IsThreeState="False"/>
 | 
			
		||||
                                                    </StackPanel>
 | 
			
		||||
                                                </Expander>
 | 
			
		||||
 | 
			
		||||
@ -233,12 +233,6 @@ public partial class MainWindow : MetroWindow {
 | 
			
		||||
 | 
			
		||||
            HandleEntries(entries, start, end);
 | 
			
		||||
            GenerateLog();
 | 
			
		||||
 | 
			
		||||
            var errors = journal.AllErrors;
 | 
			
		||||
            foreach (var error in errors) {
 | 
			
		||||
                Log("An error has occured in the Journal file, please send this to CMDR Hekateh:");
 | 
			
		||||
                Log(error.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception exception) {
 | 
			
		||||
            Log("Something went terribly wrong while parsing the E:D player journal.");
 | 
			
		||||
            Log("Please send this to CMDR Hekateh:");
 | 
			
		||||
 | 
			
		||||
@ -120,14 +120,14 @@ public class UITransaction : INotifyPropertyChanged {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool HasEnemyCaptain {
 | 
			
		||||
    public bool HasCaptain {
 | 
			
		||||
        get {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return combat.EnemyCaptain ?? false;
 | 
			
		||||
            return combat.Captain ?? false;
 | 
			
		||||
        }
 | 
			
		||||
        set {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
@ -135,18 +135,18 @@ public class UITransaction : INotifyPropertyChanged {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            combat.EnemyCaptain = value;
 | 
			
		||||
            combat.Captain = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool HasAlliedCaptain {
 | 
			
		||||
    public bool HasCorrespondent {
 | 
			
		||||
        get {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return combat.AlliedCaptain ?? false;
 | 
			
		||||
            return combat.Correspondent ?? false;
 | 
			
		||||
        }
 | 
			
		||||
        set {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
@ -154,45 +154,7 @@ public class UITransaction : INotifyPropertyChanged {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            combat.AlliedCaptain = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool HasEnemyCorrespondent {
 | 
			
		||||
        get {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return combat.EnemyCorrespondent ?? false;
 | 
			
		||||
        }
 | 
			
		||||
        set {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            combat.EnemyCorrespondent = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool HasAlliedCorrespondent {
 | 
			
		||||
        get {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return combat.AlliedCorrespondent ?? false;
 | 
			
		||||
        }
 | 
			
		||||
        set {
 | 
			
		||||
            CombatZone combat = Transaction as CombatZone;
 | 
			
		||||
            if (combat == null) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            combat.AlliedCorrespondent = value;
 | 
			
		||||
            combat.Correspondent = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,6 @@
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Resources;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
 | 
			
		||||
@ -49,5 +51,5 @@ using System.Windows;
 | 
			
		||||
// You can specify all the values or you can default the Build and Revision Numbers
 | 
			
		||||
// by using the '*' as shown below:
 | 
			
		||||
// [assembly: AssemblyVersion("1.0.*")]
 | 
			
		||||
[assembly: AssemblyVersion("0.3.7.0")]
 | 
			
		||||
[assembly: AssemblyFileVersion("0.3.7.0")]
 | 
			
		||||
[assembly: AssemblyVersion("0.3.3.0")]
 | 
			
		||||
[assembly: AssemblyFileVersion("0.3.3.0")]
 | 
			
		||||
 | 
			
		||||
@ -1,35 +1,5 @@
 | 
			
		||||
# EliteBGS changelog
 | 
			
		||||
 | 
			
		||||
# 0.3.7 on 29.01.2024
 | 
			
		||||
 | 
			
		||||
* Fix wrong locations of BGS action if you remain on your carrier while its
 | 
			
		||||
  jumping to a new system.
 | 
			
		||||
* Identify a capital ship in a high CZ by its music.
 | 
			
		||||
 | 
			
		||||
# 0.3.6 on 25.10.2023
 | 
			
		||||
 | 
			
		||||
* 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
 | 
			
		||||
  journals anymore to keep using the tool.
 | 
			
		||||
* Banshee has been added.
 | 
			
		||||
 | 
			
		||||
## 0.3.5 on 11.09.2023
 | 
			
		||||
 | 
			
		||||
* Small bounty voucher formats are no longer suppressed.
 | 
			
		||||
* Glaive has been renamed to "Hunter" since Scythe has the same bounty
 | 
			
		||||
  and they cannot be distinguished.
 | 
			
		||||
* Mission influence can now also be negative. Failed missions now properly
 | 
			
		||||
  report the amount of negative influence given to a faction.
 | 
			
		||||
* Mission secondary influences now also support negative influences. This
 | 
			
		||||
  for example happens if you take a mission to murder another faction's
 | 
			
		||||
  civlians, which causes negative INF.
 | 
			
		||||
 | 
			
		||||
## 0.3.4 on 18.06.2023
 | 
			
		||||
 | 
			
		||||
* Added possibility to specify allied, as well as enemy captain and correspondent.
 | 
			
		||||
* Added date range, and tool version to standard log format.
 | 
			
		||||
* Added new English mission names.
 | 
			
		||||
 | 
			
		||||
## 0.3.3 on 15.05.2023
 | 
			
		||||
 | 
			
		||||
* Added payout for the Thargoid Glaive.
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ tab. With update 15, this behaviour should be fixed.
 | 
			
		||||
 | 
			
		||||
The player journal only tells the faction that issued the bounty upon murder, and
 | 
			
		||||
not the faction of the NPC killed. The tool has to fetch that from you scanning the
 | 
			
		||||
ship. If you didn't fully scan the ship before murdering it, the tool won't know
 | 
			
		||||
hip. If you didn't fully scan the ship before murdering it, the tool won't know
 | 
			
		||||
the faction of the NPC.
 | 
			
		||||
 | 
			
		||||
### Why does cartography data, and sold cargo show up for the wrong faction, but for the right station/system?
 | 
			
		||||
 | 
			
		||||
@ -20,13 +20,13 @@ command line:
 | 
			
		||||
winget install Microsoft.DotNet.DesktopRuntime.7
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You can download the **latest** version **0.3.7** at CodeBerg:
 | 
			
		||||
You can download the **latest** version **0.3.3** at CodeBerg:
 | 
			
		||||
 | 
			
		||||
* [https://codeberg.org/nola/EDBGS/releases](https://codeberg.org/nola/EDBGS/releases)
 | 
			
		||||
 | 
			
		||||
Or alternatively from my server:
 | 
			
		||||
 | 
			
		||||
* [https://bgs.n0la.org/elitebgs-0.3.6.zip](https://bgs.n0la.org/elitebgs-0.3.7.zip)
 | 
			
		||||
* [https://bgs.n0la.org/elitebgs-0.3.3.zip](https://bgs.n0la.org/elitebgs-0.3.3.zip)
 | 
			
		||||
 | 
			
		||||
## Old Versions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user