Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6e2280a00 | |||
| 160f4f8370 | |||
| 4400418d30 | |||
| 43037b0a5b | |||
| afc831cf31 | |||
| 4ab54ee576 | |||
| d6842115c5 | |||
| acb60e0a08 | |||
| dac9b7b8c7 | |||
| 3338f573c8 | |||
| 204d6b8914 | |||
| 4c75515a70 | |||
| c43c6f742a | |||
| c7a70598c4 | |||
| cdd7eb33de | |||
| dab39b9a4e |
@@ -43,6 +43,12 @@ public class CombatZone : Transaction {
|
||||
/// </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>
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EDPlayerJournal.BGS;
|
||||
/// faction to another. Both sometimes gain influence.
|
||||
/// </summary>
|
||||
public class InfluenceSupport : Transaction {
|
||||
public string Influence { get; set; } = "";
|
||||
public MissionInfluence? Influence { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Relevant mission completed entry
|
||||
@@ -46,7 +46,7 @@ public class InfluenceSupport : Transaction {
|
||||
|
||||
builder.AppendFormat("Influence gained from \"{0}\": \"{1}\"",
|
||||
missionname,
|
||||
string.IsNullOrEmpty(Influence) ? "NONE" : Influence
|
||||
Influence == null ? "NONE" : Influence.TrendAdjustedInfluence
|
||||
);
|
||||
|
||||
return builder.ToString();
|
||||
|
||||
@@ -38,7 +38,14 @@ public class MissionCompleted : Transaction {
|
||||
return "";
|
||||
}
|
||||
|
||||
return (CompletedEntry.Mission.GetInfluenceForFaction(Faction, SystemAddress) ?? "");
|
||||
return string.Join("",
|
||||
CompletedEntry
|
||||
.Mission
|
||||
.GetInfluenceForFaction(Faction, SystemAddress)
|
||||
.Select(x => x.Influence)
|
||||
.ToArray()
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +77,10 @@ public class MissionCompleted : Transaction {
|
||||
var influence = CompletedEntry.Mission.GetInfluenceForFaction(Faction, SystemAddress);
|
||||
|
||||
builder.AppendFormat("{0}", MissionName);
|
||||
if (influence != "") {
|
||||
builder.AppendFormat(", Influence: {0}", influence);
|
||||
if (influence != null && influence.Length > 0) {
|
||||
builder.AppendFormat(", Influence: {0}",
|
||||
influence.Select(x => x.InfluenceAmount).Sum()
|
||||
);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
|
||||
@@ -13,6 +13,21 @@ 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;
|
||||
|
||||
15
EDPlayerJournal/BGS/Parsers/ApproachSettlementParser.cs
Normal file
15
EDPlayerJournal/BGS/Parsers/ApproachSettlementParser.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,20 +298,20 @@ internal class MissionCompletedParser : ITransactionParserPart {
|
||||
if (context.CurrentSystemAddress == null) {
|
||||
continue;
|
||||
}
|
||||
other.Value.Add(context.CurrentSystemAddress.Value, "");
|
||||
other.Value.Add(context.CurrentSystemAddress.Value, new MissionInfluence());
|
||||
// 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, "");
|
||||
other.Value.Add(accepted_location.SystemAddress, new MissionInfluence());
|
||||
|
||||
// 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, "");
|
||||
other.Value.Add(context.CurrentSystemAddress.Value, new MissionInfluence());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -663,6 +663,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.Commander, new CommanderParser() },
|
||||
{ Events.CommitCrime, new CommitCrimeParser() },
|
||||
|
||||
@@ -57,6 +57,11 @@ internal class TransactionParserContext {
|
||||
public bool HaveSeenAlliedCorrespondent { get; set; } = false;
|
||||
public bool HaveSeenEnemyCorrespondent { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Current Odyssey settlement.
|
||||
/// </summary>
|
||||
public string? Settlement { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the current session is legacy
|
||||
/// </summary>
|
||||
@@ -115,6 +120,7 @@ internal class TransactionParserContext {
|
||||
/// </summary>
|
||||
public void LeftInstance() {
|
||||
CurrentInstanceType = null;
|
||||
Settlement = null;
|
||||
}
|
||||
|
||||
public void DiscernCombatZone(TransactionList transactions, Entry e) {
|
||||
@@ -223,6 +229,7 @@ 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
|
||||
|
||||
@@ -44,6 +44,6 @@ public class Credits {
|
||||
return string.Format("{0:0.00}M", millions);
|
||||
}
|
||||
|
||||
return "";
|
||||
return string.Format("{0}", amount);
|
||||
}
|
||||
}
|
||||
|
||||
48
EDPlayerJournal/Entries/ApproachSettlementEntry.cs
Normal file
48
EDPlayerJournal/Entries/ApproachSettlementEntry.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ 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.Commander, typeof(CommanderEntry) },
|
||||
@@ -63,7 +64,15 @@ public class Entry {
|
||||
public static Entry? Parse(string journalline) {
|
||||
using (JsonReader reader = new JsonTextReader(new StringReader(journalline))) {
|
||||
reader.DateParseHandling = DateParseHandling.None;
|
||||
var json = JObject.Load(reader);
|
||||
JObject? json = null;
|
||||
try {
|
||||
json = JObject.Load(reader);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidJournalEntryException(
|
||||
"invalid JSON journal entry: " + journalline,
|
||||
e
|
||||
);
|
||||
}
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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 Commander = "Commander";
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
public class InvalidJournalEntryException : Exception {
|
||||
public InvalidJournalEntryException() { }
|
||||
public InvalidJournalEntryException(string message) : base(message) { }
|
||||
public InvalidJournalEntryException(string message, Exception inner) : base(message, inner) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,6 +17,11 @@ 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);
|
||||
|
||||
@@ -125,15 +130,20 @@ public class JournalFile : IComparable<JournalFile>
|
||||
}
|
||||
|
||||
entries.Clear();
|
||||
foreach(var line in lines) {
|
||||
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,6 +36,31 @@ 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();
|
||||
|
||||
@@ -394,27 +419,29 @@ 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 string? GetInfluenceForFaction(string faction, ulong systemaddr) {
|
||||
public MissionInfluence[]? 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.Influence)
|
||||
.Select(x => x)
|
||||
.ToArray()
|
||||
;
|
||||
|
||||
if (results == null || results.Length == 0) {
|
||||
return null;
|
||||
return new MissionInfluence[0];
|
||||
}
|
||||
|
||||
return string.Join("", results);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A convenient Dictionary containing all influences given out by faction,
|
||||
/// then by system address and then by influence handed out.
|
||||
/// then by system address and then by influence handed out. Influence can
|
||||
/// be either a series of "+" for positive influence, or "-" for negative
|
||||
/// influence.
|
||||
/// </summary>
|
||||
public Dictionary<string, Dictionary<ulong, string>> Influences {
|
||||
public Dictionary<string, Dictionary<ulong, MissionInfluence>> Influences {
|
||||
get {
|
||||
return FactionEffects
|
||||
.Where(x => x.Faction != null)
|
||||
@@ -422,7 +449,10 @@ 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.Influence)
|
||||
.ToDictionary(
|
||||
x => (x.SystemAddress ?? 0),
|
||||
x => x
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ public class PlayerJournal {
|
||||
ScanFiles();
|
||||
}
|
||||
|
||||
public List<Exception> AllErrors {
|
||||
get {
|
||||
return Files.SelectMany(x => x.Errors).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<JournalFile> Files {
|
||||
get { return journalfiles; }
|
||||
}
|
||||
|
||||
@@ -8,11 +8,16 @@ public enum ThargoidVessel {
|
||||
Basilisk = 4,
|
||||
Medusa = 5,
|
||||
Hydra = 6,
|
||||
Glaive = 7,
|
||||
// Includes Glaive and Scythe
|
||||
Hunter = 7,
|
||||
/// <summary>
|
||||
/// Thargoid drone
|
||||
/// </summary>
|
||||
Revenant = 8,
|
||||
/// <summary>
|
||||
/// New thargoid drone in U17
|
||||
/// </summary>
|
||||
Banshee = 9,
|
||||
}
|
||||
|
||||
public class Thargoid {
|
||||
@@ -23,8 +28,10 @@ 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.Glaive },
|
||||
{ 4500000, ThargoidVessel.Hunter },
|
||||
{ 6500000, ThargoidVessel.Cyclops },
|
||||
{ 20000000, ThargoidVessel.Basilisk },
|
||||
//{ 25000000, ThargoidVessel.Orthrus },
|
||||
@@ -46,7 +53,7 @@ public class Thargoid {
|
||||
};
|
||||
|
||||
public static Dictionary<ThargoidVessel, string?> VesselNames { get; } = new() {
|
||||
{ ThargoidVessel.Unknown, null },
|
||||
{ ThargoidVessel.Unknown, "(Unknown)" },
|
||||
{ ThargoidVessel.Revenant, "Revenant" },
|
||||
{ ThargoidVessel.Scout, "Scout" },
|
||||
{ ThargoidVessel.Orthrus, "Orthrus" },
|
||||
@@ -54,7 +61,8 @@ public class Thargoid {
|
||||
{ ThargoidVessel.Basilisk, "Basilisk" },
|
||||
{ ThargoidVessel.Medusa, "Medusa" },
|
||||
{ ThargoidVessel.Hydra, "Hydra" },
|
||||
{ ThargoidVessel.Glaive, "Glaive" },
|
||||
{ ThargoidVessel.Hunter, "Hunter" },
|
||||
{ ThargoidVessel.Banshee, "Banshee" },
|
||||
};
|
||||
|
||||
public static ThargoidVessel GetVesselByPayout(ulong payout) {
|
||||
|
||||
@@ -59,9 +59,9 @@ public class MissionTest {
|
||||
Assert.IsTrue(e.IsEmptyFaction);
|
||||
Assert.AreEqual(e.Faction, string.Empty);
|
||||
|
||||
string? influence = m.GetInfluenceForFaction("", 251012319587UL);
|
||||
var influence = m.GetInfluenceForFaction("", 251012319587UL);
|
||||
Assert.IsNotNull(influence);
|
||||
Assert.AreEqual(influence, "+");
|
||||
Assert.AreEqual(influence[0].Influence, "+");
|
||||
|
||||
e = m.FactionEffects[1];
|
||||
Assert.AreEqual(e.Faction, "Social LHS 6103 Confederation");
|
||||
@@ -101,22 +101,25 @@ public class MissionTest {
|
||||
|
||||
Assert.AreEqual(effect.Reputation, "++");
|
||||
|
||||
string? influence;
|
||||
|
||||
influence = m.GetInfluenceForFaction("Salus Imperial Society", 1865919973739UL);
|
||||
Assert.AreEqual(influence, "++");
|
||||
var influence = m.GetInfluenceForFaction("Salus Imperial Society", 1865919973739UL);
|
||||
Assert.IsNotNull(influence);
|
||||
Assert.IsTrue(influence.Length > 0);
|
||||
Assert.AreEqual(influence[0].Influence, "++");
|
||||
|
||||
influence = m.GetInfluenceForFaction("Salus Imperial Society", 1733186884306UL);
|
||||
Assert.AreEqual(influence, "++");
|
||||
Assert.IsNotNull(influence);
|
||||
Assert.IsTrue(influence.Length > 0);
|
||||
Assert.AreEqual(influence[0].Influence, "++");
|
||||
|
||||
influence = m.GetInfluenceForFaction("Saelishi Saxons", 1733186884306UL);
|
||||
Assert.IsNull(influence);
|
||||
Assert.IsNotNull(influence);
|
||||
Assert.AreEqual(influence.Length, 0);
|
||||
|
||||
// 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], "++");
|
||||
Assert.AreEqual(m.Influences["Salus Imperial Society"][1733186884306UL], "++");
|
||||
Assert.AreEqual(m.Influences["Salus Imperial Society"][1865919973739UL].Influence, "++");
|
||||
Assert.AreEqual(m.Influences["Salus Imperial Society"][1733186884306UL].Influence, "++");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -19,7 +19,13 @@ public class TestTransactionParser {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Transaction>? transactions = parser.Parse(entries);
|
||||
var options = new TransactionParserOptions() {
|
||||
IgnoreInfluenceSupport = false,
|
||||
IgnoreExoBiology = false,
|
||||
IgnoreFleetCarrierFaction = false,
|
||||
IgnoreMarketBuy = false,
|
||||
};
|
||||
List<Transaction>? transactions = parser.Parse(entries, options);
|
||||
Assert.IsNotNull(transactions, "could not parse entries");
|
||||
Assert.AreEqual(transactions.Count, 3);
|
||||
|
||||
@@ -144,7 +150,14 @@ public class TestTransactionParser {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Transaction>? transactions = parser.Parse(entries);
|
||||
var options = new TransactionParserOptions() {
|
||||
IgnoreInfluenceSupport = false,
|
||||
IgnoreExoBiology = false,
|
||||
IgnoreFleetCarrierFaction = false,
|
||||
IgnoreMarketBuy = false,
|
||||
};
|
||||
|
||||
List<Transaction>? transactions = parser.Parse(entries, options);
|
||||
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,14 +22,17 @@ 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.Scout);
|
||||
Assert.AreEqual(transactions[0].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
|
||||
|
||||
Assert.IsInstanceOfType(transactions[1], typeof(ThargoidKill), "result is not of type ThargoidKill");
|
||||
Assert.AreEqual(transactions[1].ThargoidType, EDPlayerJournal.ThargoidVessel.Basilisk);
|
||||
Assert.AreEqual(transactions[1].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
|
||||
|
||||
Assert.IsInstanceOfType(transactions[2], typeof(ThargoidKill), "result is not of type ThargoidKill");
|
||||
Assert.AreEqual(transactions[2].ThargoidType, EDPlayerJournal.ThargoidVessel.Scout);
|
||||
Assert.AreEqual(transactions[2].ThargoidType, EDPlayerJournal.ThargoidVessel.Unknown);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -4,14 +4,12 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using EliteBGS.LogGenerator;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace EliteBGS;
|
||||
|
||||
public class DiscordLogGenerator {
|
||||
protected List<LogFormatter> formatters = new List<LogFormatter>() {
|
||||
new MissionFormat(),
|
||||
new FailedMissionFormat(),
|
||||
new MurderFormat(),
|
||||
new VoucherFormat(),
|
||||
new ThargoidFormatter(),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Version>0.3.4</Version>
|
||||
<Version>0.3.6</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 })
|
||||
.GroupBy(x => new { x.Type, x.Grade, x.Settlement })
|
||||
.ToDictionary(x => x.Key, x => x.ToList())
|
||||
;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -23,6 +23,11 @@ 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,
|
||||
@@ -39,6 +44,9 @@ 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");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
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,17 +6,72 @@ 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();
|
||||
int total_influence = 0;
|
||||
long 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)) {
|
||||
(support == null || support.Count == 0) &&
|
||||
(failed == null || failed.Count == 0)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -60,17 +115,25 @@ 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.Length;
|
||||
total_influence += inf.Influence.InfluenceAmount;
|
||||
}
|
||||
|
||||
if (support.Count() > 0) {
|
||||
output.Append("\n");
|
||||
}
|
||||
|
||||
if (total_influence > 0) {
|
||||
if (total_influence != 0) {
|
||||
output.AppendFormat("Total Influence: {0}", total_influence);
|
||||
}
|
||||
|
||||
@@ -84,13 +147,24 @@ public class MissionFormat : LogFormatter {
|
||||
;
|
||||
long support = objective
|
||||
.EnabledOfType<InfluenceSupport>()
|
||||
.Sum(x => x.Influence.Length)
|
||||
.Sum(x => x.Influence.InfluenceAmount)
|
||||
;
|
||||
long failed = objective
|
||||
.EnabledOfType<MissionFailed>()
|
||||
.Sum(x => x.InfluenceAmount)
|
||||
;
|
||||
|
||||
if (influence + support <= 0) {
|
||||
if (influence == 0 && support == 0 && failed == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return string.Format("INF: {0}", influence + support);
|
||||
string failedsummary = GenerateFailedSummary(objective);
|
||||
string summary = string.Format("INF: {0}", influence + support + failed);
|
||||
|
||||
if (!string.IsNullOrEmpty(failedsummary)) {
|
||||
string.Join("; ", summary, failedsummary);
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +233,12 @@ 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:");
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
@@ -51,5 +49,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.4.0")]
|
||||
[assembly: AssemblyFileVersion("0.3.4.0")]
|
||||
[assembly: AssemblyVersion("0.3.6.0")]
|
||||
[assembly: AssemblyFileVersion("0.3.6.0")]
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# EliteBGS changelog
|
||||
|
||||
# 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.
|
||||
|
||||
@@ -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
|
||||
hip. If you didn't fully scan the ship before murdering it, the tool won't know
|
||||
ship. 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.4** at CodeBerg:
|
||||
You can download the **latest** version **0.3.6** 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.4.zip](https://bgs.n0la.org/elitebgs-0.3.4.zip)
|
||||
* [https://bgs.n0la.org/elitebgs-0.3.6.zip](https://bgs.n0la.org/elitebgs-0.3.6.zip)
|
||||
|
||||
## Old Versions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user