34 Commits
0.3.0 ... 0.3.2

Author SHA1 Message Date
16ee7047cd make a release 2023-04-19 15:49:20 +02:00
cedc576b47 mind spelling 2023-04-19 15:08:56 +02:00
58b8ed07c4 fix changelog 2023-04-19 10:15:49 +02:00
ef85f51734 update changelog 2023-04-19 10:15:15 +02:00
00deaf20fc better name market buy/market sold 2023-04-19 10:13:35 +02:00
5fe652f98c add profit to search and rescue 2023-04-19 10:13:02 +02:00
8cf8d7f529 change one line discord log to only show summaries 2023-04-19 10:06:10 +02:00
fce534c88f remove old ico from source files 2023-04-19 09:38:04 +02:00
25338c8754 bump version 2023-04-19 09:29:21 +02:00
139cbd05f8 update changelog 2023-04-19 09:27:57 +02:00
b0302572f8 forgot to load the setting 2023-04-19 09:25:36 +02:00
87314d0258 we still want profit info, just not BGS info 2023-04-19 09:19:37 +02:00
f4bbd3df2b add GUI elements for ignoring market buy 2023-04-19 09:17:06 +02:00
d6acbda55c add option to ignore market buy 2023-04-19 09:06:54 +02:00
5c9d9c9153 correct black market trade by properly setting StationOwner 2023-04-19 09:01:32 +02:00
da3a355695 provide station faction via Location entry 2023-04-19 08:37:22 +02:00
5224dd4555 split out some classes to avoid clutter 2023-04-19 08:31:23 +02:00
15fda7692e format credits with millions 2023-04-11 19:17:29 +02:00
4cd0c02c67 write config file in indented JSON 2023-03-29 18:41:10 +02:00
e39dd6ffda add setting to ignore influence support 2023-03-29 18:40:36 +02:00
f666a2c7c5 add additional english names 2023-03-27 21:34:13 +02:00
8574b74494 add more English mission names 2023-03-25 12:21:34 +01:00
1255bf9fa5 add two more English mission names 2023-03-18 00:57:41 +01:00
781bb7a209 more thargoid payout changes 2023-03-18 00:56:16 +01:00
24817a02a9 add more English mission names 2023-03-08 15:45:24 +01:00
d00c8d5c06 allow possibility to ignore influence support 2023-03-03 15:59:41 +01:00
b588050fb4 ignoring exo biology is now handled in the parser 2023-03-02 20:10:49 +01:00
f9eb0d34f9 introduce parser options
And use it to ignore exo biology data.
2023-03-02 20:09:19 +01:00
2a393809fc add additional mission names 2023-03-01 13:43:13 +01:00
7ee734bc33 bugfix release 2023-02-26 22:16:01 +01:00
5799b3ed16 fix summary for failed missions 2023-02-26 22:03:31 +01:00
a13e8446d2 fix summary for AX combat zones 2023-02-26 22:01:13 +01:00
0665e64459 fix VH type 2023-02-26 21:57:45 +01:00
d8ac2a7ee7 grade can be null 2023-02-26 21:57:24 +01:00
33 changed files with 704 additions and 347 deletions

View File

@@ -1,10 +1,11 @@
using System.Linq; using System.Text;
using System.Text;
using EDPlayerJournal.Entries; using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS; namespace EDPlayerJournal.BGS;
public class Cartographics : Transaction { public class Cartographics : Transaction {
public Cartographics() { }
public Cartographics(MultiSellExplorationDataEntry e) { public Cartographics(MultiSellExplorationDataEntry e) {
Entries.Add(e); Entries.Add(e);
} }

View File

@@ -4,6 +4,8 @@ using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS; namespace EDPlayerJournal.BGS;
public class OrganicData : Transaction { public class OrganicData : Transaction {
public OrganicData() { }
public OrganicData(SellOrganicDataEntry e) { public OrganicData(SellOrganicDataEntry e) {
Entries.Add(e); Entries.Add(e);
} }
@@ -36,6 +38,8 @@ public class OrganicData : Transaction {
/* Selling organic data only helps the controlling faction, just like /* Selling organic data only helps the controlling faction, just like
* selling cartographic data. * selling cartographic data.
*
* Right now: Organic data helps no one.
*/ */
public override bool OnlyControllingFaction => true; public override bool OnlyControllingFaction => true;
} }

View File

@@ -1,220 +1,27 @@
using EDPlayerJournal; using EDPlayerJournal.Entries;
using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS; namespace EDPlayerJournal.BGS;
internal class TransactionParserContext { public class TransactionParserOptions {
public string? CurrentSystem { get; set; } /// <summary>
public ulong? CurrentSystemAddress { get; set; } /// Whether to ignore exo biology. It does not contribute to BGS, so this
public string? CurrentStation { get; set; } /// is true per default.
public string? ControllingFaction { get; set; } /// </summary>
public bool IgnoreExoBiology { get; set; } = true;
public bool IsOnFoot { get; set; } = false;
public string? LastRecordedAwardingFaction { get; set; }
public ulong? HighestCombatBond { get; set; }
public bool HaveSeenCapShip { get; set; } = false;
public bool HaveSeenCaptain { get; set; } = false;
public bool HaveSeenSpecOps { get; set; } = false;
public bool HaveSeenCorrespondent { get; set; } = false;
/// <summary> /// <summary>
/// Returns true if the current session is legacy /// Whether to ignore influence support. Usually one only cares about the
/// primary faction for the influence.
/// </summary> /// </summary>
public bool IsLegacy { get; set; } = false; public bool IgnoreInfluenceSupport { get; set; } = false;
/// <summary> /// <summary>
/// How many on foot kills were done. /// Whether to ignore market buy. Buying from a market gives a small amount
/// of INF if it is sold to a high demand market, but generally one buys from
/// a market to aid the faction the stuff is being sold to. So allow it to be
/// disabled.
/// </summary> /// </summary>
public ulong OnFootKills { get; set; } = 0; public bool IgnoreMarketBuy { get; set; } = false;
/// <summary>
/// How many ship kills were done.
/// </summary>
public ulong ShipKills { get; set; } = 0;
/// <summary>
/// Thargoid scouts killed
/// </summary>
public ulong ThargoidScoutKills { get; set; } = 0;
/// <summary>
/// Thargoid interceptor kills
/// </summary>
public ulong ThargoidInterceptorKills { get; set; } = 0;
/// <summary>
/// Whether we have seen an AX warzone NPC talk to us with ReceiveText
/// </summary>
public bool HaveSeenAXWarzoneNPC { get; set; } = false;
/// <summary>
/// A list of accepted missions index by their mission ID
/// </summary>
public Dictionary<ulong, Mission> AcceptedMissions { get; } = new();
public Dictionary<ulong, Location> AcceptedMissionLocation { get; } = new();
/// <summary>
/// A way to lookup a system by its system id
/// </summary>
public Dictionary<ulong, string> SystemsByID { get; } = new();
/// <summary>
/// A list of factions present in the given star system
/// </summary>
public Dictionary<string, List<Faction>> SystemFactions { get; } = new();
/// <summary>
/// To which faction a given named NPC belonged to.
/// </summary>
public Dictionary<string, string> NPCFaction { get; } = new();
/// <summary>
/// Buy costs for a given commodity
/// </summary>
public Dictionary<string, long> BuyCost = new();
public void DiscernCombatZone(TransactionList transactions, Entry e) {
string? grade = CombatZones.DifficultyLow;
string cztype;
ulong highest = HighestCombatBond ?? 0;
string? faction = LastRecordedAwardingFaction;
if (HighestCombatBond == null &&
LastRecordedAwardingFaction == null &&
HaveSeenAXWarzoneNPC == false) {
return;
}
if (OnFootKills > 0 || IsOnFoot == true) {
cztype = CombatZones.GroundCombatZone;
// High on foot combat zones have enforcers that bring 80k a pop
if (highest >= 60000) {
grade = CombatZones.DifficultyHigh;
} else if (highest >= 30000) {
// In medium conflict zones, the enforcers are worth 30k
grade = CombatZones.DifficultyMedium;
} else {
grade = CombatZones.DifficultyLow;
}
} else if (ShipKills > 0 && !IsOnFoot) {
// Ship combat zones can be identified by the amount of kills
if (ShipKills > 20) {
grade = CombatZones.DifficultyHigh;
} else if (ShipKills > 10) {
grade = CombatZones.DifficultyMedium;
}
// Cap ship, means a high conflict zone
if (HaveSeenCapShip) {
grade = CombatZones.DifficultyHigh;
} else {
int warzoneNpcs = new List<bool>() { HaveSeenCaptain, HaveSeenCorrespondent, HaveSeenSpecOps }
.Where(x => x == true)
.Count()
;
if (warzoneNpcs >= 1 && grade == CombatZones.DifficultyLow) {
grade = CombatZones.DifficultyMedium;
}
}
cztype = CombatZones.ShipCombatZone;
} else if ((ThargoidScoutKills > 0 && ThargoidInterceptorKills > 0) ||
HaveSeenAXWarzoneNPC == true) {
// Could be a thargoid combat zones if interceptors and scouts are there
cztype = CombatZones.AXCombatZone;
// Still unknown
grade = null;
} else {
transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type", e);
return;
}
CombatZone zone = new CombatZone() {
System = CurrentSystem,
Faction = faction,
IsLegacy = IsLegacy,
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,
Correspondent = HaveSeenCorrespondent ? true : null,
Captain = HaveSeenCaptain ? true : null,
};
zone.Entries.Add(e);
transactions.Add(zone);
}
public void RecordCombatBond(FactionKillBondEntry e) {
if (HighestCombatBond == null || e.Reward > HighestCombatBond) {
HighestCombatBond = e.Reward;
}
LastRecordedAwardingFaction = e.AwardingFaction;
if (IsOnFoot) {
++OnFootKills;
} else {
++ShipKills;
}
}
public void ResetCombatZone() {
HighestCombatBond = null;
HaveSeenCapShip = false;
HaveSeenCaptain = false;
HaveSeenCorrespondent = false;
HaveSeenSpecOps = false;
LastRecordedAwardingFaction = null;
OnFootKills = 0;
ShipKills = 0;
ThargoidInterceptorKills = 0;
ThargoidScoutKills = 0;
HaveSeenAXWarzoneNPC = false;
}
public void BoughtCargo(string? cargo, long? cost) {
if (cargo == null || cost == null) {
return;
}
BuyCost[cargo] = cost.Value;
}
public List<Faction>? GetFactions(string? system) {
if (system == null || !SystemFactions.ContainsKey(system)) {
return null;
}
return SystemFactions[system];
}
public void MissionAccepted(MissionAcceptedEntry? entry) {
if (entry == null) {
return;
}
MissionAccepted(entry.Mission);
}
public void MissionAccepted(Mission? mission) {
if (CurrentSystem == null || CurrentSystemAddress == null) {
throw new Exception("Mission accepted without knowing where.");
}
if (mission == null) {
throw new Exception("Mission is null");
}
AcceptedMissions.TryAdd(mission.MissionID, mission);
Location location = new() {
StarSystem = CurrentSystem,
SystemAddress = CurrentSystemAddress.Value,
Station = (CurrentStation ?? ""),
};
AcceptedMissionLocation.TryAdd(mission.MissionID, location);
}
} }
public class TransactionList : List<Transaction> { public class TransactionList : List<Transaction> {
@@ -223,29 +30,13 @@ public class TransactionList : List<Transaction> {
} }
} }
internal interface TransactionParserPart{
/// <summary>
/// Parse a given entry of the entry type specified when declaring to implement this
/// interface. You must add your transaction to the passed list in case you did have
/// enough information to parse one or more. You may update the parser context
/// with new information in case the entry yielded new information.
/// Throw an exception if there was an error or a malformed entry. If you have an
/// incomplete entry, i.e. not enough information to complete one, add an
/// IncompleteTransaction to the list
/// </summary>
/// <param name="entry">The entry to parse</param>
/// <param name="context">Parsing context that may contain useful information</param>
/// <param name="transactions">List of parsed transactions</param>
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions);
}
/// <summary> /// <summary>
/// The location parser only updates the context with useful information, and does not /// The location parser only updates the context with useful information, and does not
/// by itself generate any transactions. Location is the best information gatherer here /// by itself generate any transactions. Location is the best information gatherer here
/// as we are getting controlling faction, system factions, address and station name. /// as we are getting controlling faction, system factions, address and station name.
/// </summary> /// </summary>
internal class LocationParser : TransactionParserPart { internal class LocationParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
LocationEntry? entry = e as LocationEntry; LocationEntry? entry = e as LocationEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -268,6 +59,12 @@ internal class LocationParser : TransactionParserPart {
context.CurrentStation = entry.StationName; context.CurrentStation = entry.StationName;
} }
if (!string.IsNullOrEmpty(entry.StationFaction)) {
context.StationOwner = entry.StationFaction;
} else {
context.StationOwner = null;
}
if (!context.SystemFactions.ContainsKey(entry.StarSystem) && if (!context.SystemFactions.ContainsKey(entry.StarSystem) &&
entry.SystemFactions != null && entry.SystemFactions.Count > 0) { entry.SystemFactions != null && entry.SystemFactions.Count > 0) {
context.SystemFactions[entry.StarSystem] = entry.SystemFactions; context.SystemFactions[entry.StarSystem] = entry.SystemFactions;
@@ -276,7 +73,7 @@ internal class LocationParser : TransactionParserPart {
} }
internal class FSDJumpParser : TransactionParserPart { internal class FSDJumpParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FSDJumpEntry? entry = e as FSDJumpEntry; FSDJumpEntry? entry = e as FSDJumpEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -309,7 +106,7 @@ internal class FSDJumpParser : TransactionParserPart {
} }
internal class DockedParser : TransactionParserPart { internal class DockedParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
DockedEntry? entry = e as DockedEntry; DockedEntry? entry = e as DockedEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -325,7 +122,7 @@ internal class DockedParser : TransactionParserPart {
context.SystemsByID.TryAdd(entry.SystemAddress.Value, entry.StarSystem); context.SystemsByID.TryAdd(entry.SystemAddress.Value, entry.StarSystem);
if (!string.IsNullOrEmpty(entry.StationFaction)) { if (!string.IsNullOrEmpty(entry.StationFaction)) {
context.ControllingFaction = entry.StationFaction; context.StationOwner = entry.StationFaction;
} }
if (!string.IsNullOrEmpty(entry.StationName)) { if (!string.IsNullOrEmpty(entry.StationName)) {
@@ -339,7 +136,7 @@ internal class DockedParser : TransactionParserPart {
/// useful later when said NPC gets killed or murdered. /// useful later when said NPC gets killed or murdered.
/// </summary> /// </summary>
internal class ShipTargetedParser : TransactionParserPart { internal class ShipTargetedParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
ShipTargetedEntry? entry = e as ShipTargetedEntry; ShipTargetedEntry? entry = e as ShipTargetedEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -374,7 +171,7 @@ internal class ShipTargetedParser : TransactionParserPart {
/// murder. /// murder.
/// </summary> /// </summary>
internal class CommitCrimeParser : TransactionParserPart { internal class CommitCrimeParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
CommitCrimeEntry? entry = e as CommitCrimeEntry; CommitCrimeEntry? entry = e as CommitCrimeEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -430,7 +227,7 @@ internal class CommitCrimeParser : TransactionParserPart {
} }
internal class MissionsParser : TransactionParserPart { internal class MissionsParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionsEntry? missions = entry as MissionsEntry; MissionsEntry? missions = entry as MissionsEntry;
if (missions == null) { if (missions == null) {
@@ -459,7 +256,7 @@ internal class MissionsParser : TransactionParserPart {
} }
internal class MissionAcceptedParser : TransactionParserPart { internal class MissionAcceptedParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionAcceptedEntry? entry = e as MissionAcceptedEntry; MissionAcceptedEntry? entry = e as MissionAcceptedEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -485,14 +282,14 @@ internal class MissionAcceptedParser : TransactionParserPart {
} }
internal class MissionCompletedParser : TransactionParserPart { internal class MissionCompletedParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionCompletedEntry? entry = e as MissionCompletedEntry; MissionCompletedEntry? entry = e as MissionCompletedEntry;
if (entry == null || entry.Mission == null) { if (entry == null || entry.Mission == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
Mission? mission = null; Mission? mission;
Location? accepted_location = null; Location? accepted_location;
string? target_faction_name = entry.Mission.TargetFaction; string? target_faction_name = entry.Mission.TargetFaction;
string? source_faction_name = entry.Mission.Faction; string? source_faction_name = entry.Mission.Faction;
@@ -577,6 +374,10 @@ internal class MissionCompletedParser : TransactionParserPart {
} else if (string.Compare(faction, source_faction_name, true) != 0 || } else if (string.Compare(faction, source_faction_name, true) != 0 ||
(string.Compare(faction, source_faction_name) == 0 && (string.Compare(faction, source_faction_name) == 0 &&
system_address != accepted_location.SystemAddress)) { system_address != accepted_location.SystemAddress)) {
// Whether we ignore influence support
if (options.IgnoreInfluenceSupport) {
continue;
}
// Source or target faction are different, and/or the system // Source or target faction are different, and/or the system
// differs. Sometimes missions go to different systems but to // differs. Sometimes missions go to different systems but to
// the same faction. // the same faction.
@@ -596,10 +397,10 @@ internal class MissionCompletedParser : TransactionParserPart {
} }
internal class MissionFailedParser : TransactionParserPart { internal class MissionFailedParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
Mission? mission = null; Mission? mission;
Location? accepted_location = null; Location? accepted_location;
string? accepted_system = null; string? accepted_system;
MissionFailedEntry? entry = e as MissionFailedEntry; MissionFailedEntry? entry = e as MissionFailedEntry;
if (entry == null) { if (entry == null) {
@@ -651,55 +452,84 @@ internal class MissionFailedParser : TransactionParserPart {
} }
internal class SellExplorationDataParser : TransactionParserPart { internal class SellExplorationDataParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SellExplorationDataEntry? entry = e as SellExplorationDataEntry; SellExplorationDataEntry? entry = e as SellExplorationDataEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (context.StationOwner == null) {
transactions.AddIncomplete(
new Cartographics(),
"Could not discern the station owner for cartographics sell.",
e);
return;
}
transactions.Add(new Cartographics(entry) { transactions.Add(new Cartographics(entry) {
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation, Station = context.CurrentStation,
Faction = context.ControllingFaction, Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class SellOrganicDataParser : TransactionParserPart { internal class SellOrganicDataParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// If exo biology is ignored, simply do nothing
if (options.IgnoreExoBiology) {
return;
}
SellOrganicDataEntry? entry = e as SellOrganicDataEntry; SellOrganicDataEntry? entry = e as SellOrganicDataEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (context.StationOwner == null) {
transactions.AddIncomplete(
new OrganicData(),
"Could not discern the station owner for organic data sell.",
e);
return;
}
transactions.Add(new OrganicData(entry) { transactions.Add(new OrganicData(entry) {
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation, Station = context.CurrentStation,
Faction = context.ControllingFaction, Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class MultiSellExplorationDataParser : TransactionParserPart { internal class MultiSellExplorationDataParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MultiSellExplorationDataEntry? entry = e as MultiSellExplorationDataEntry; MultiSellExplorationDataEntry? entry = e as MultiSellExplorationDataEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (context.StationOwner == null) {
transactions.AddIncomplete(
new Cartographics(),
"Could not discern the station owner for cartographics sell.",
e);
return;
}
transactions.Add(new Cartographics(entry) { transactions.Add(new Cartographics(entry) {
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation, Station = context.CurrentStation,
Faction = context.ControllingFaction, Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class RedeemVoucherParser : TransactionParserPart { internal class RedeemVoucherParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
RedeemVoucherEntry? entry = e as RedeemVoucherEntry; RedeemVoucherEntry? entry = e as RedeemVoucherEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -756,39 +586,55 @@ internal class RedeemVoucherParser : TransactionParserPart {
} }
internal class SellMicroResourcesParser : TransactionParserPart { internal class SellMicroResourcesParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry; SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (context.StationOwner == null) {
transactions.AddIncomplete(
new SellMicroResources(),
"Could not discern the station owner for micro resources sell.",
e);
return;
}
transactions.Add(new SellMicroResources(entry) { transactions.Add(new SellMicroResources(entry) {
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation, Station = context.CurrentStation,
Faction = context.ControllingFaction, Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class SearchAndRescueParser : TransactionParserPart { internal class SearchAndRescueParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SearchAndRescueEntry? entry = e as SearchAndRescueEntry; SearchAndRescueEntry? entry = e as SearchAndRescueEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (context.StationOwner == null) {
transactions.AddIncomplete(
new OrganicData(),
"Could not discern the station owner for S&R operations.",
e);
return;
}
transactions.Add(new SearchAndRescue(entry) { transactions.Add(new SearchAndRescue(entry) {
Faction = context.ControllingFaction,
Station = context.CurrentStation,
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation,
Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class MarketBuyParser : TransactionParserPart { internal class MarketBuyParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MarketBuyEntry? entry = e as MarketBuyEntry; MarketBuyEntry? entry = e as MarketBuyEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -796,19 +642,44 @@ internal class MarketBuyParser : TransactionParserPart {
context.BoughtCargo(entry.Type, entry.BuyPrice); context.BoughtCargo(entry.Type, entry.BuyPrice);
// We still want the information on buy price for profit,
// but if the option is on, we don't care for parsing it
// further.
// TODO: might be wise to split this parser into two; one for
// determining profit, the other for the BGS information
if (options.IgnoreMarketBuy) {
return;
}
if (context.StationOwner == null) {
transactions.AddIncomplete(
new OrganicData(),
"Could not discern the station owner for market buy.",
e);
return;
}
transactions.Add(new BuyCargo(entry) { transactions.Add(new BuyCargo(entry) {
Faction = context.ControllingFaction,
Station = context.CurrentStation,
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation,
Faction = context.StationOwner,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
} }
} }
internal class MarketSellParser : TransactionParserPart { internal class MarketSellParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
long profit = 0; long profit = 0;
if (context.StationOwner == null) {
transactions.AddIncomplete(
new OrganicData(),
"Could not discern the station owner market sell.",
e);
return;
}
MarketSellEntry? entry = e as MarketSellEntry; MarketSellEntry? entry = e as MarketSellEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -824,9 +695,9 @@ internal class MarketSellParser : TransactionParserPart {
} }
transactions.Add(new SellCargo(entry) { transactions.Add(new SellCargo(entry) {
Faction = context.ControllingFaction,
Station = context.CurrentStation,
System = context.CurrentSystem, System = context.CurrentSystem,
Station = context.CurrentStation,
Faction = context.StationOwner,
Profit = profit, Profit = profit,
IsLegacy = context.IsLegacy, IsLegacy = context.IsLegacy,
}); });
@@ -834,7 +705,7 @@ internal class MarketSellParser : TransactionParserPart {
} }
internal class FactionKillBondParser : TransactionParserPart { internal class FactionKillBondParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FactionKillBondEntry? entry = e as FactionKillBondEntry; FactionKillBondEntry? entry = e as FactionKillBondEntry;
if (entry == null) { if (entry == null) {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -867,7 +738,7 @@ internal class FactionKillBondParser : TransactionParserPart {
} }
internal class EmbarkDisembarkParser : TransactionParserPart { internal class EmbarkDisembarkParser : TransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
if (e.Is(Events.Embark)) { if (e.Is(Events.Embark)) {
context.IsOnFoot = false; context.IsOnFoot = false;
} else if (e.Is(Events.Disembark)) { } else if (e.Is(Events.Disembark)) {
@@ -877,7 +748,7 @@ internal class EmbarkDisembarkParser : TransactionParserPart {
} }
internal class SupercruiseEntryParser : TransactionParserPart { internal class SupercruiseEntryParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// After a super cruise entry we are no longer on foot. // After a super cruise entry we are no longer on foot.
context.IsOnFoot = false; context.IsOnFoot = false;
context.DiscernCombatZone(transactions, entry); context.DiscernCombatZone(transactions, entry);
@@ -886,14 +757,14 @@ internal class SupercruiseEntryParser : TransactionParserPart {
} }
internal class ShutdownParser : TransactionParserPart { internal class ShutdownParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
context.DiscernCombatZone(transactions, entry); context.DiscernCombatZone(transactions, entry);
context.ResetCombatZone(); context.ResetCombatZone();
} }
} }
internal class CapShipBondParser : TransactionParserPart { internal class CapShipBondParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
if (entry.GetType() != typeof(CapShipBondEntry)) { if (entry.GetType() != typeof(CapShipBondEntry)) {
return; return;
} }
@@ -903,7 +774,7 @@ internal class CapShipBondParser : TransactionParserPart {
} }
internal class FileHeaderParser : TransactionParserPart { internal class FileHeaderParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FileHeaderEntry? fileheader = entry as FileHeaderEntry; FileHeaderEntry? fileheader = entry as FileHeaderEntry;
if (fileheader == null) { if (fileheader == null) {
@@ -915,7 +786,7 @@ internal class FileHeaderParser : TransactionParserPart {
} }
internal class ReceiveTextParser : TransactionParserPart { internal class ReceiveTextParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
ReceiveTextEntry? receivetext = entry as ReceiveTextEntry; ReceiveTextEntry? receivetext = entry as ReceiveTextEntry;
if (receivetext == null) { if (receivetext == null) {
@@ -933,7 +804,7 @@ internal class ReceiveTextParser : TransactionParserPart {
} }
internal class DiedParser : TransactionParserPart { internal class DiedParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// You can't complete a combat zone if you die in it. Others might keep it open // 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. // for you, but still you will not have completed it unless you jump back in.
context.ResetCombatZone(); context.ResetCombatZone();
@@ -941,14 +812,14 @@ internal class DiedParser : TransactionParserPart {
} }
internal class DropshipDeployParser : TransactionParserPart { internal class DropshipDeployParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// On drop ship deploy we are now on foot // On drop ship deploy we are now on foot
context.IsOnFoot = true; context.IsOnFoot = true;
} }
} }
internal class CommanderParser : TransactionParserPart { internal class CommanderParser : TransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// A commander entry happens when you log out, and log back in again // A commander entry happens when you log out, and log back in again
// for example when switching from Open, to Solo or PG. // for example when switching from Open, to Solo or PG.
context.DiscernCombatZone(transactions, entry); context.DiscernCombatZone(transactions, entry);
@@ -1000,7 +871,17 @@ public class TransactionParser {
return IsRelevant(e.Event); return IsRelevant(e.Event);
} }
/// <summary>
/// Parses a list of entries with default options.
/// </summary>
/// <param name="entries"></param>
/// <returns></returns>
public List<Transaction>? Parse(IEnumerable<Entry> entries) { public List<Transaction>? Parse(IEnumerable<Entry> entries) {
TransactionParserOptions defaultOptions = new();
return Parse(entries, defaultOptions);
}
public List<Transaction>? Parse(IEnumerable<Entry> entries, TransactionParserOptions options) {
TransactionList transactions = new(); TransactionList transactions = new();
TransactionParserContext context = new(); TransactionParserContext context = new();
@@ -1014,7 +895,7 @@ public class TransactionParser {
} }
TransactionParserPart transactionParserPart = ParserParts[entry.Event]; TransactionParserPart transactionParserPart = ParserParts[entry.Event];
transactionParserPart.Parse(entry, context, transactions); transactionParserPart.Parse(entry, context, options, transactions);
} }
return transactions.ToList(); return transactions.ToList();

View File

@@ -0,0 +1,246 @@
using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS;
internal class TransactionParserContext {
/// <summary>
/// Name of the current system the player is in.
/// </summary>
public string? CurrentSystem { get; set; }
/// <summary>
/// 64 bit address of the current system.
/// </summary>
public ulong? CurrentSystemAddress { get; set; }
/// <summary>
/// Controlling faction of the current system.
/// </summary>
public string? ControllingFaction { get; set; }
/// <summary>
/// Name of the current station the player is docked at.
/// </summary>
public string? CurrentStation { get; set; }
/// <summary>
/// Faction that owns the current station.
/// </summary>
public string? StationOwner { get; set; }
/// <summary>
/// Whether the player is currently on foot, or in an SRV/ship.
/// </summary>
public bool IsOnFoot { get; set; } = false;
/// <summary>
/// Last faction that awarded the player with combat bonds.
/// </summary>
public string? LastRecordedAwardingFaction { get; set; }
/// <summary>
/// Highest combat bond seen so far.
/// </summary>
public ulong? HighestCombatBond { get; set; }
public bool HaveSeenCapShip { get; set; } = false;
public bool HaveSeenCaptain { get; set; } = false;
public bool HaveSeenSpecOps { get; set; } = false;
public bool HaveSeenCorrespondent { get; set; } = false;
/// <summary>
/// Returns true if the current session is legacy
/// </summary>
public bool IsLegacy { get; set; } = false;
/// <summary>
/// How many on foot kills were done.
/// </summary>
public ulong OnFootKills { get; set; } = 0;
/// <summary>
/// How many ship kills were done.
/// </summary>
public ulong ShipKills { get; set; } = 0;
/// <summary>
/// Thargoid scouts killed
/// </summary>
public ulong ThargoidScoutKills { get; set; } = 0;
/// <summary>
/// Thargoid interceptor kills
/// </summary>
public ulong ThargoidInterceptorKills { get; set; } = 0;
/// <summary>
/// Whether we have seen an AX warzone NPC talk to us with ReceiveText
/// </summary>
public bool HaveSeenAXWarzoneNPC { get; set; } = false;
/// <summary>
/// A list of accepted missions index by their mission ID
/// </summary>
public Dictionary<ulong, Mission> AcceptedMissions { get; } = new();
public Dictionary<ulong, Location> AcceptedMissionLocation { get; } = new();
/// <summary>
/// A way to lookup a system by its system id
/// </summary>
public Dictionary<ulong, string> SystemsByID { get; } = new();
/// <summary>
/// A list of factions present in the given star system
/// </summary>
public Dictionary<string, List<Faction>> SystemFactions { get; } = new();
/// <summary>
/// To which faction a given named NPC belonged to.
/// </summary>
public Dictionary<string, string> NPCFaction { get; } = new();
/// <summary>
/// Buy costs for a given commodity
/// </summary>
public Dictionary<string, long> BuyCost = new();
public void DiscernCombatZone(TransactionList transactions, Entry e) {
string? grade = CombatZones.DifficultyLow;
string cztype;
ulong highest = HighestCombatBond ?? 0;
string? faction = LastRecordedAwardingFaction;
if (HighestCombatBond == null &&
LastRecordedAwardingFaction == null &&
HaveSeenAXWarzoneNPC == false) {
return;
}
if (OnFootKills > 0 || IsOnFoot == true) {
cztype = CombatZones.GroundCombatZone;
// High on foot combat zones have enforcers that bring 80k a pop
if (highest >= 60000) {
grade = CombatZones.DifficultyHigh;
} else if (highest >= 30000) {
// In medium conflict zones, the enforcers are worth 30k
grade = CombatZones.DifficultyMedium;
} else {
grade = CombatZones.DifficultyLow;
}
} else if (ShipKills > 0 && !IsOnFoot) {
// Ship combat zones can be identified by the amount of kills
if (ShipKills > 20) {
grade = CombatZones.DifficultyHigh;
} else if (ShipKills > 10) {
grade = CombatZones.DifficultyMedium;
}
// Cap ship, means a high conflict zone
if (HaveSeenCapShip) {
grade = CombatZones.DifficultyHigh;
} else {
int warzoneNpcs = new List<bool>() { HaveSeenCaptain, HaveSeenCorrespondent, HaveSeenSpecOps }
.Where(x => x == true)
.Count()
;
if (warzoneNpcs >= 1 && grade == CombatZones.DifficultyLow) {
grade = CombatZones.DifficultyMedium;
}
}
cztype = CombatZones.ShipCombatZone;
} else if ((ThargoidScoutKills > 0 && ThargoidInterceptorKills > 0) ||
HaveSeenAXWarzoneNPC == true) {
// Could be a thargoid combat zones if interceptors and scouts are there
cztype = CombatZones.AXCombatZone;
// Still unknown
grade = null;
} else {
transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type", e);
return;
}
CombatZone zone = new CombatZone() {
System = CurrentSystem,
Faction = faction,
IsLegacy = IsLegacy,
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,
Correspondent = HaveSeenCorrespondent ? true : null,
Captain = HaveSeenCaptain ? true : null,
};
zone.Entries.Add(e);
transactions.Add(zone);
}
public void RecordCombatBond(FactionKillBondEntry e) {
if (HighestCombatBond == null || e.Reward > HighestCombatBond) {
HighestCombatBond = e.Reward;
}
LastRecordedAwardingFaction = e.AwardingFaction;
if (IsOnFoot) {
++OnFootKills;
} else {
++ShipKills;
}
}
public void ResetCombatZone() {
HighestCombatBond = null;
HaveSeenCapShip = false;
HaveSeenCaptain = false;
HaveSeenCorrespondent = false;
HaveSeenSpecOps = false;
LastRecordedAwardingFaction = null;
OnFootKills = 0;
ShipKills = 0;
ThargoidInterceptorKills = 0;
ThargoidScoutKills = 0;
HaveSeenAXWarzoneNPC = false;
}
public void BoughtCargo(string? cargo, long? cost) {
if (cargo == null || cost == null) {
return;
}
BuyCost[cargo] = cost.Value;
}
public List<Faction>? GetFactions(string? system) {
if (system == null || !SystemFactions.ContainsKey(system)) {
return null;
}
return SystemFactions[system];
}
public void MissionAccepted(MissionAcceptedEntry? entry) {
if (entry == null) {
return;
}
MissionAccepted(entry.Mission);
}
public void MissionAccepted(Mission? mission) {
if (CurrentSystem == null || CurrentSystemAddress == null) {
throw new Exception("Mission accepted without knowing where.");
}
if (mission == null) {
throw new Exception("Mission is null");
}
AcceptedMissions.TryAdd(mission.MissionID, mission);
Location location = new() {
StarSystem = CurrentSystem,
SystemAddress = CurrentSystemAddress.Value,
Station = (CurrentStation ?? ""),
};
AcceptedMissionLocation.TryAdd(mission.MissionID, location);
}
}

View File

@@ -0,0 +1,19 @@
using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS;
internal interface TransactionParserPart {
/// <summary>
/// Parse a given entry of the entry type specified when declaring to implement this
/// interface. You must add your transaction to the passed list in case you did have
/// enough information to parse one or more. You may update the parser context
/// with new information in case the entry yielded new information.
/// Throw an exception if there was an error or a malformed entry. If you have an
/// incomplete entry, i.e. not enough information to complete one, add an
/// IncompleteTransaction to the list
/// </summary>
/// <param name="entry">The entry to parse</param>
/// <param name="context">Parsing context that may contain useful information</param>
/// <param name="transactions">List of parsed transactions</param>
public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions);
}

View File

@@ -43,7 +43,7 @@ public class CombatZones {
/// Returns the given combat zone difficulty as an integer, so it can be sorted. /// Returns the given combat zone difficulty as an integer, so it can be sorted.
/// 0 = lowest difficulty, 1 = medium and so forth. /// 0 = lowest difficulty, 1 = medium and so forth.
/// </summary> /// </summary>
public static int? DifficultyRank(string difficulty) { public static int? DifficultyRank(string? difficulty) {
Dictionary<string, int> ranks = new() { Dictionary<string, int> ranks = new() {
{ DifficultyLow, 0 }, { DifficultyLow, 0 },
{ DifficultyMedium, 1 }, { DifficultyMedium, 1 },
@@ -51,6 +51,10 @@ public class CombatZones {
{ DifficultyVeryHigh, 3 } { DifficultyVeryHigh, 3 }
}; };
if (difficulty == null ) {
return null;
}
if (ranks.TryGetValue(difficulty, out int rank)) { if (ranks.TryGetValue(difficulty, out int rank)) {
return rank; return rank;
} }

View File

@@ -15,6 +15,7 @@ public class EnglishMissionNames {
{"Mission_AltruismCredits_name", "Donate Credits"}, {"Mission_AltruismCredits_name", "Donate Credits"},
{"Mission_AltruismCredits_Outbreak_name", "Donate Credits (Outbreak)" }, {"Mission_AltruismCredits_Outbreak_name", "Donate Credits (Outbreak)" },
{"Mission_Assassinate_Illegal_BLOPS_name", "Assassination (Illegal)"}, {"Mission_Assassinate_Illegal_BLOPS_name", "Assassination (Illegal)"},
{"MISSION_assassinate_Illegal_Planetary_name", "Assassination (Illegal, Planetary)" },
{"Mission_Assassinate_Legal_Bust_name", "Assassination (Bust, Legal)" }, {"Mission_Assassinate_Legal_Bust_name", "Assassination (Bust, Legal)" },
{"MISSION_assassinate_legal_CivilUnrest_name", "Assassination (Civil Unrest, Legal)" }, {"MISSION_assassinate_legal_CivilUnrest_name", "Assassination (Civil Unrest, Legal)" },
{"Mission_Assassinate_Legal_Communism_name", "Assassination (Communism, Legal)" }, {"Mission_Assassinate_Legal_Communism_name", "Assassination (Communism, Legal)" },
@@ -51,7 +52,9 @@ public class EnglishMissionNames {
{"Mission_Delivery_Retreat_name", "Delivery (Retreat)"}, {"Mission_Delivery_Retreat_name", "Delivery (Retreat)"},
{"Mission_DeliveryWing_name", "Delivery (Wing)"}, {"Mission_DeliveryWing_name", "Delivery (Wing)"},
{"Mission_DeliveryWing_War_name", "Delivery (Wing) (War)"}, {"Mission_DeliveryWing_War_name", "Delivery (Wing) (War)"},
{"MISSION_Disable_BLOPS_name", "Disable (Black Ops)" }, {"MISSION_Disable_name", "Disable Surface Installation" },
{"MISSION_Disable_BLOPS_name", "Disable Surface Installation (Black Ops)" },
{"MISSION_Hack_name", "Hack Surface Installation" },
{"Mission_Hack_BLOPS_Boom_name", "Hack Surface Installation (Boom)"}, {"Mission_Hack_BLOPS_Boom_name", "Hack Surface Installation (Boom)"},
{"Mission_Hack_BLOPS_Elections_name", "Hack Surface Installation (Elections)"}, {"Mission_Hack_BLOPS_Elections_name", "Hack Surface Installation (Elections)"},
{"Mission_Hack_BLOPS_Expansion_name", "Hack Surface Installation (Expansion)"}, {"Mission_Hack_BLOPS_Expansion_name", "Hack Surface Installation (Expansion)"},
@@ -100,8 +103,10 @@ public class EnglishMissionNames {
{"Mission_PassengerVIP_name", "Passenger (VIP)"}, {"Mission_PassengerVIP_name", "Passenger (VIP)"},
{"Mission_PassengerVIP_Scientist_FAMINE_name", "Passenger Scientist (VIP) (Famine)"}, {"Mission_PassengerVIP_Scientist_FAMINE_name", "Passenger Scientist (VIP) (Famine)"},
{"Mission_PassengerVIP_Tourist_BOOM_name", "Passenger Tourist (VIP) (Boom)"}, {"Mission_PassengerVIP_Tourist_BOOM_name", "Passenger Tourist (VIP) (Boom)"},
{"Mission_Rescue_Planet_name", "Planet Rescue"}, {"Mission_Rescue_Elections_name", "Liberate Hostages (Election)" },
{"Mission_Rescue_name", "Liberate Hostages" },
{"Mission_Rescue_Planet_Expansion_name", "Planet Rescue (Expansion)" }, {"Mission_Rescue_Planet_Expansion_name", "Planet Rescue (Expansion)" },
{"Mission_Rescue_Planet_name", "Planet Rescue"},
{"MISSION_Salvage_CivilUnrest_name", "Salvage (Civil Unrest)"}, {"MISSION_Salvage_CivilUnrest_name", "Salvage (Civil Unrest)"},
{"MISSION_Salvage_Expansion_name", "Salvage (Expansion)"}, {"MISSION_Salvage_Expansion_name", "Salvage (Expansion)"},
{"MISSION_Salvage_Illegal_name", "Salvage (Illegal)"}, {"MISSION_Salvage_Illegal_name", "Salvage (Illegal)"},
@@ -119,6 +124,8 @@ public class EnglishMissionNames {
{"Mission_TW_Massacre_Cyclops_Singular_name", "Kill Cyclop" }, {"Mission_TW_Massacre_Cyclops_Singular_name", "Kill Cyclop" },
{"Mission_TW_Massacre_Hydra_Plural_name", "Kill Hydras" }, {"Mission_TW_Massacre_Hydra_Plural_name", "Kill Hydras" },
{"Mission_TW_Massacre_Hydra_Singular_name", "Kill Hydra" }, {"Mission_TW_Massacre_Hydra_Singular_name", "Kill Hydra" },
{"Mission_TW_Massacre_Medusa_Plural_name", "Kill Medusas" },
{"Mission_TW_Massacre_Medusa_Singular_name", "Kill Medusa" },
{"Mission_TW_Massacre_Scout_Plural_name", "Kill Scouts" }, {"Mission_TW_Massacre_Scout_Plural_name", "Kill Scouts" },
{"Mission_TW_PassengerEvacuation_Burning_name", "Passenger Evacuation (Significant Damage)" }, {"Mission_TW_PassengerEvacuation_Burning_name", "Passenger Evacuation (Significant Damage)" },
{"Mission_TW_PassengerEvacuation_UnderAttack_name", "Passenger Evacuation (Thargoid Invasion)" }, {"Mission_TW_PassengerEvacuation_UnderAttack_name", "Passenger Evacuation (Thargoid Invasion)" },

View File

@@ -1,18 +1,47 @@
using System; using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace EDPlayerJournal.Entries; namespace EDPlayerJournal.Entries;
public class LocationEntry : Entry { public class LocationEntry : Entry {
/// <summary>
/// Current star system.
/// </summary>
public string? StarSystem { get; set; } public string? StarSystem { get; set; }
/// <summary>
/// Faction in control of the current star system. Empty for unpopulated
/// systems.
/// </summary>
public string? SystemFaction { get; set; } public string? SystemFaction { get; set; }
public string? StationName { get; set; }
/// <summary>
/// 64bit system address.
/// </summary>
public ulong SystemAddress { get; set; } public ulong SystemAddress { get; set; }
/// <summary>
/// Station name if docked at a station.
/// </summary>
public string? StationName { get; set; }
/// <summary>
/// Faction in control of the current station, if docked.
/// </summary>
public string? StationFaction { get; set; }
/// <summary>
/// Body within the system, might be null.
/// </summary>
public string? Body { get; set; } public string? Body { get; set; }
/// <summary>
/// Returns true if the player is docked somewhere.
/// </summary>
public bool Docked { get; set; } public bool Docked { get; set; }
/// <summary>
/// Position of the star system.
/// </summary>
public long[]? StarPos { get; set; } public long[]? StarPos { get; set; }
public List<Faction> SystemFactions { get; set; } = new List<Faction>(); public List<Faction> SystemFactions { get; set; } = new List<Faction>();
@@ -30,7 +59,12 @@ public class LocationEntry : Entry {
JObject? systemfaction = JSON.Value<JObject>("SystemFaction"); JObject? systemfaction = JSON.Value<JObject>("SystemFaction");
if (systemfaction != null) { if (systemfaction != null) {
SystemFaction = systemfaction.Value<string>("Name") ?? ""; SystemFaction = systemfaction.Value<string>("Name");
}
JObject? stationfaction = JSON.Value<JObject>("StationFaction");
if (stationfaction != null) {
StationFaction = stationfaction.Value<string>("Name");
} }
JArray? factions = JSON.Value<JArray>("Factions"); JArray? factions = JSON.Value<JArray>("Factions");

View File

@@ -19,20 +19,22 @@ public class Thargoid {
{ 75000, ThargoidVessel.Scout }, { 75000, ThargoidVessel.Scout },
{ 6500000, ThargoidVessel.Cyclops }, { 6500000, ThargoidVessel.Cyclops },
{ 20000000, ThargoidVessel.Basilisk }, { 20000000, ThargoidVessel.Basilisk },
{ 25000000, ThargoidVessel.Orthrus }, //{ 25000000, ThargoidVessel.Orthrus },
{ 34000000, ThargoidVessel.Medusa }, { 34000000, ThargoidVessel.Medusa },
// March, 16th 2023 the Orthrus payout was buffed again.
{ 40000000, ThargoidVessel.Orthrus },
{ 50000000, ThargoidVessel.Hydra }, { 50000000, ThargoidVessel.Hydra },
// These are the old values pre Update 14.02 // These are the old values pre Update 14.02
{ 80000, ThargoidVessel.Scout }, //{ 80000, ThargoidVessel.Scout },
{ 8000000, ThargoidVessel.Cyclops }, //{ 8000000, ThargoidVessel.Cyclops },
{ 24000000, ThargoidVessel.Basilisk }, //{ 24000000, ThargoidVessel.Basilisk },
// In Update 14.1 the payout for Orthrus has been rebalanced. // In Update 14.1 the payout for Orthrus has been rebalanced.
{ 30000000, ThargoidVessel.Orthrus }, //{ 30000000, ThargoidVessel.Orthrus },
{ 40000000, ThargoidVessel.Medusa }, //{ 40000000, ThargoidVessel.Medusa },
// This used to be the old payout value for Orthrus, it now conflicts // This used to be the old payout value for Orthrus, it now conflicts
// with Post Update 14.02 Hydra values // with Post Update 14.02 Hydra values
//{ 50000000, ThargoidVessel.Orthrus }, //{ 50000000, ThargoidVessel.Orthrus },
{ 60000000, ThargoidVessel.Hydra }, //{ 60000000, ThargoidVessel.Hydra },
}; };
public static Dictionary<ThargoidVessel, string?> VesselNames { get; } = new() { public static Dictionary<ThargoidVessel, string?> VesselNames { get; } = new() {

View File

@@ -19,8 +19,7 @@ public class DiscordLogGenerator {
new MicroResourcesFormat(), new MicroResourcesFormat(),
new MarketBuyFormat(), new MarketBuyFormat(),
new CargoSoldFormatter(), new CargoSoldFormatter(),
/* As of this moment, Update 14.02 organics do not affect BGS at all */ new VistaGenomicsFormat(),
//new VistaGenomicsFormat(),
new SearchAndRescueFormat(), new SearchAndRescueFormat(),
}; };
@@ -40,7 +39,7 @@ public class DiscordLogGenerator {
} }
if (sb.Length > 0) { if (sb.Length > 0) {
sb.Append(", "); sb.Append("; ");
} }
sb.Append(summary); sb.Append(summary);

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net7.0-windows</TargetFramework>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<Version>0.3.0</Version> <Version>0.3.2</Version>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
@@ -54,12 +54,6 @@
<ItemGroup> <ItemGroup>
<Resource Include="Salus.ico" /> <Resource Include="Salus.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Resource Include="Resources\EliteBGS.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="EliteBGS.ico" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MahApps.Metro" Version="2.4.9" /> <PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
@@ -85,4 +79,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
</Project> </Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

View File

@@ -58,11 +58,20 @@ public class CargoSoldFormatter : LogFormatter {
public string GenerateSummary(Objective objective) { public string GenerateSummary(Objective objective) {
SellCargo[] sold = objective.EnabledOfType<SellCargo>().ToArray(); SellCargo[] sold = objective.EnabledOfType<SellCargo>().ToArray();
long totalProfit = sold.Sum(x => x.Profit); long totalProfit = sold.Sum(x => x.Profit);
long tons = sold.Sum(x => x.Amount);
if (totalProfit >= 100000) { if (tons <= 0) {
return string.Format("Trade: {0}", Credits.FormatMillions(totalProfit));
}
return ""; return "";
} }
StringBuilder builder = new();
builder.Append("Sold: ");
builder.AppendFormat("{0}t", tons);
if (totalProfit >= 100000) {
builder.AppendFormat(", {0} profit", Credits.FormatMillions(totalProfit));
}
return builder.ToString();
}
} }

View File

@@ -9,7 +9,7 @@ class CombatZoneFormat : LogFormatter {
public string GenerateLog(Objective objective) { public string GenerateLog(Objective objective) {
var logs = objective var logs = objective
.EnabledOfType<CombatZone>() .EnabledOfType<CombatZone>()
.OrderBy(x => CombatZones.DifficultyRank(x.Grade)) .OrderBy(x => (CombatZones.DifficultyRank(x.Grade) ?? 0))
.GroupBy(x => new { x.Type, x.Grade }) .GroupBy(x => new { x.Type, x.Grade })
.ToDictionary(x => x.Key, x => x.ToList()) .ToDictionary(x => x.Key, x => x.ToList())
; ;
@@ -48,7 +48,7 @@ class CombatZoneFormat : LogFormatter {
public string GenerateSummary(Objective objective) { public string GenerateSummary(Objective objective) {
var logs = objective var logs = objective
.EnabledOfType<CombatZone>() .EnabledOfType<CombatZone>()
.OrderBy(x => CombatZones.DifficultyRank(x.Grade)) .OrderBy(x => (CombatZones.DifficultyRank(x.Grade) ?? 0))
.GroupBy(x => new { x.Type, x.Grade }) .GroupBy(x => new { x.Type, x.Grade })
.ToDictionary(x => x.Key, x => x.ToList()) .ToDictionary(x => x.Key, x => x.ToList())
; ;
@@ -72,7 +72,7 @@ class CombatZoneFormat : LogFormatter {
} }
builder.AppendFormat("CZ: {0}x{1}{2}", builder.AppendFormat("CZ: {0}x{1}{2}",
log.Value.Count, log.Value.Count,
log.Key.Grade.Substring(0, 1), grade,
log.Key.Type.Substring(0, 1) log.Key.Type.Substring(0, 1)
); );
} else { } else {

View File

@@ -43,12 +43,13 @@ public class FailedMissionFormat : LogFormatter {
int onFootFails = missions.Where(x => x.Mission.IsOnFoot).Count(); int onFootFails = missions.Where(x => x.Mission.IsOnFoot).Count();
int shipFails = missions.Where(x => !x.Mission.IsOnFoot).Count(); int shipFails = missions.Where(x => !x.Mission.IsOnFoot).Count();
sb.Append("Fails: ");
if (onFootFails > 0) { if (onFootFails > 0) {
sb.AppendFormat("Fails: {0} Ground", onFootFails); sb.AppendFormat("{0} Ground", onFootFails);
} }
if (shipFails > 0) { if (shipFails > 0) {
if (sb.Length> 0) { if (onFootFails > 0) {
sb.Append(", "); sb.Append(", ");
} }
sb.AppendFormat("{0} Ship", shipFails); sb.AppendFormat("{0} Ship", shipFails);

View File

@@ -26,7 +26,7 @@ public class GenericFormat<Type> : LogFormatter where Type : Transaction {
return builder.ToString(); return builder.ToString();
} }
public string GenerateSummary(Objective objective) { public virtual string GenerateSummary(Objective objective) {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
} }

View File

@@ -1,6 +1,38 @@
using EDPlayerJournal.BGS; using EDPlayerJournal;
using EDPlayerJournal.BGS;
using System.Linq;
using System.Text;
namespace EliteBGS.LogGenerator; namespace EliteBGS.LogGenerator;
public class KillBondsFormat : GenericFormat<FactionKillBonds> { public class KillBondsFormat : GenericFormat<FactionKillBonds> {
public override string GenerateSummary(Objective objective) {
StringBuilder builder = new StringBuilder();
var bonds = objective
.EnabledOfType<FactionKillBonds>()
.GroupBy(x => x.VictimFaction)
.ToDictionary(x => x.Key, x => x.ToList())
;
if (bonds.Count <= 0) {
return "";
}
builder.Append("Killbonds: ");
foreach (var entry in bonds) {
long sum = (long)entry.Value.Sum(x => (decimal)x.TotalSum);
builder.AppendFormat("{0} against {1}, ",
Credits.FormatMillions(sum),
entry.Key
);
}
if (builder.Length > 2) {
// Remove trailing comma
builder.Remove(builder.Length - 2, 2);
}
return builder.ToString();
}
} }

View File

@@ -1,6 +1,17 @@
using EDPlayerJournal.BGS; using EDPlayerJournal.BGS;
using System.Linq;
namespace EliteBGS.LogGenerator; namespace EliteBGS.LogGenerator;
public class MarketBuyFormat : GenericFormat<BuyCargo> { public class MarketBuyFormat : GenericFormat<BuyCargo> {
public override string GenerateSummary(Objective objective) {
long tons = objective
.EnabledOfType<BuyCargo>()
.Sum(x => x.Amount)
;
if (tons <= 0) {
return "";
}
return string.Format("Bought: {0}t bought", tons);
}
} }

View File

@@ -1,6 +1,22 @@
using EDPlayerJournal.BGS; using EDPlayerJournal;
using EDPlayerJournal.BGS;
using System.Linq;
namespace EliteBGS.LogGenerator; namespace EliteBGS.LogGenerator;
public class SearchAndRescueFormat : GenericFormat<SearchAndRescue> { public class SearchAndRescueFormat : GenericFormat<SearchAndRescue> {
public override string GenerateSummary(Objective objective) {
long tons = objective
.EnabledOfType<SearchAndRescue>()
.Sum(x => x.Count)
;
long profit = objective
.EnabledOfType<SearchAndRescue>()
.Sum(x => x.Reward)
;
if (tons <= 0) {
return "";
}
return string.Format("S&R: {0}t, {1} profit", tons, Credits.FormatMillions(profit));
}
} }

View File

@@ -47,8 +47,8 @@ public class ThargoidFormatter : LogFormatter {
builder.AppendFormat("{0} INT", interceptors); builder.AppendFormat("{0} INT", interceptors);
} }
if (scouts > 0) { if (scouts > 0) {
if (builder.Length> 0) { if (interceptors > 0) {
builder.Append(", "); builder.Append(" + ");
} }
builder.AppendFormat("{0} SCT", scouts); builder.AppendFormat("{0} SCT", scouts);
} }

View File

@@ -1,6 +1,18 @@
using EDPlayerJournal.BGS; using EDPlayerJournal;
using EDPlayerJournal.BGS;
using System.Linq;
namespace EliteBGS.LogGenerator; namespace EliteBGS.LogGenerator;
class VistaGenomicsFormat : GenericFormat<OrganicData> { class VistaGenomicsFormat : GenericFormat<OrganicData> {
public override string GenerateSummary(Objective objective) {
long profit = objective
.EnabledOfType<OrganicData>()
.Sum(x => x.TotalValue)
;
if (profit <= 0) {
return "";
}
return string.Format("Organic: {0} Profit", Credits.FormatMillions(profit));
}
} }

View File

@@ -19,8 +19,8 @@ public class VoucherFormat : LogFormatter {
} }
foreach (var m in missions) { foreach (var m in missions) {
ulong total = (ulong)m.Value.Sum(x => (decimal)x.TotalSum); long total = (long)m.Value.Sum(x => (decimal)x.TotalSum);
builder.AppendFormat("Handed in {0} vouchers: {1}\n", m.Key, Credits.FormatCredits(total)); builder.AppendFormat("Handed in {0} vouchers: {1}\n", m.Key, Credits.FormatMillions(total));
} }
return builder.ToString().Trim(); return builder.ToString().Trim();

View File

@@ -163,6 +163,7 @@
<TabItem Header="Settings"> <TabItem Header="Settings">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
@@ -201,6 +202,22 @@
<ComboBox x:Name="Colour" IsEditable="False" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Width="Auto" SelectionChanged="Colour_SelectionChanged"/> <ComboBox x:Name="Colour" IsEditable="False" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Width="Auto" SelectionChanged="Colour_SelectionChanged"/>
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Advanced Parsing Options" Grid.Row="2" VerticalAlignment="Top" Width="Auto" Grid.ColumnSpan="3" Margin="0,5,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<mah:ToggleSwitch x:Name="NoInfluenceSupport" Grid.Row="1" Grid.ColumnSpan="2" Content="Ignore secondary influence support given out by certain missions" Toggled="NoInfluenceSupport_Toggled"/>
<mah:ToggleSwitch x:Name="NoMarketBuy" Grid.Row="2" Grid.ColumnSpan="2" Content="Ignore commodities bought at stations" Toggled="NoMarketBuy_Toggled"/>
</Grid>
</GroupBox>
</Grid> </Grid>
</TabItem> </TabItem>
<TabItem Header="Event Log"> <TabItem Header="Event Log">

View File

@@ -58,6 +58,9 @@ public partial class MainWindow : MetroWindow {
LogType.SelectedIndex = 0; LogType.SelectedIndex = 0;
} }
this.NoInfluenceSupport.IsOn = Config.Global.IgnoreInfluenceSupport;
this.NoMarketBuy.IsOn = Config.Global.IgnoreMarketBuy;
// Apply theme // Apply theme
try { try {
AddCustomThemes(); AddCustomThemes();
@@ -165,8 +168,13 @@ public partial class MainWindow : MetroWindow {
private void HandleEntries(List<Entry> entries, DateTime start, DateTime end) { private void HandleEntries(List<Entry> entries, DateTime start, DateTime end) {
try { try {
TransactionParser parser = new TransactionParser(); TransactionParser parser = new();
List<Transaction> transactions = parser.Parse(entries); TransactionParserOptions options = new();
options.IgnoreInfluenceSupport = Config.Global.IgnoreInfluenceSupport;
options.IgnoreMarketBuy = Config.Global.IgnoreMarketBuy;
List<Transaction> transactions = parser.Parse(entries, options);
// Filter the transactions down to the given time frame // Filter the transactions down to the given time frame
transactions = transactions transactions = transactions
@@ -271,7 +279,7 @@ public partial class MainWindow : MetroWindow {
} }
} }
private void entries_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) { private void entries_KeyUp(object sender, KeyEventArgs e) {
if (e.Key == Key.Delete) { if (e.Key == Key.Delete) {
RemoveCurrentObjective(); RemoveCurrentObjective();
} }
@@ -290,7 +298,7 @@ public partial class MainWindow : MetroWindow {
} }
private Objective GetObjectiveFromControl(object sender) { private Objective GetObjectiveFromControl(object sender) {
System.Windows.Controls.Control control = sender as System.Windows.Controls.Control; Control control = sender as Control;
if (control == null || control.DataContext == null) { if (control == null || control.DataContext == null) {
return null; return null;
} }
@@ -355,7 +363,7 @@ public partial class MainWindow : MetroWindow {
try { try {
Config.SaveGlobal(); Config.SaveGlobal();
} catch (Exception error) { } catch (Exception error) {
System.Windows.MessageBox.Show("There was an error saving your settings: " + error.Message); MessageBox.Show("There was an error saving your settings: " + error.Message);
} }
} }
@@ -363,7 +371,7 @@ public partial class MainWindow : MetroWindow {
} }
private TransactionType GetTransaction<TransactionType>(object sender) where TransactionType : Transaction { private TransactionType GetTransaction<TransactionType>(object sender) where TransactionType : Transaction {
System.Windows.Controls.Control button = sender as System.Windows.Controls.Control; Control button = sender as Control;
if (button == null || button.DataContext == null) { if (button == null || button.DataContext == null) {
return null; return null;
} }
@@ -520,4 +528,12 @@ public partial class MainWindow : MetroWindow {
Process.Start(info); Process.Start(info);
e.Handled = true; e.Handled = true;
} }
private void NoInfluenceSupport_Toggled(object sender, RoutedEventArgs e) {
Config.Global.IgnoreInfluenceSupport = this.NoInfluenceSupport.IsOn;
}
private void NoMarketBuy_Toggled(object sender, RoutedEventArgs e) {
Config.Global.IgnoreMarketBuy = this.NoMarketBuy.IsOn;
}
} }

View File

@@ -1,4 +1,8 @@
namespace EliteBGS; using EliteBGS.LogGenerator;
using System.Linq;
using System.Text;
namespace EliteBGS;
public class OneLineDiscordLog : DiscordLogGenerator { public class OneLineDiscordLog : DiscordLogGenerator {
protected override string GenerateObjectiveHeader(Objective objective) { protected override string GenerateObjectiveHeader(Objective objective) {
@@ -10,7 +14,7 @@ public class OneLineDiscordLog : DiscordLogGenerator {
} }
protected override string GenerateObjectiveFooter(Objective objective) { protected override string GenerateObjectiveFooter(Objective objective) {
return ""; return "\n";
} }
protected override string GenerateFooter() { protected override string GenerateFooter() {
@@ -21,9 +25,38 @@ public class OneLineDiscordLog : DiscordLogGenerator {
return ""; return "";
} }
protected override string TransformFinalLogForObjective(Objective objective, string log) { public override string GenerateDiscordLog(Report report) {
string[] lines = log.Split("\n", System.StringSplitOptions.RemoveEmptyEntries); StringBuilder log = new StringBuilder();
return string.Join(", ", lines);
if (report == null) {
return "";
}
var objectives = report.Objectives
.Where(x => x.IsEnabled && x.Transactions.Count() > 0)
;
if (objectives == null || objectives.Count() <= 0) {
return "";
}
foreach (Objective objective in objectives) {
log.AppendFormat("{0}", GenerateObjectiveHeader(objective));
foreach (LogFormatter formatter in formatters) {
string text = formatter.GenerateSummary(objective);
text = text.Trim();
if (!string.IsNullOrEmpty(text)) {
log.AppendFormat("{0}; ", text);
}
}
log.AppendFormat("{0}", GenerateObjectiveFooter(objective));
}
log.AppendFormat("{0}", GenerateFooter());
return log.ToString().Trim();
} }
public override string ToString() { public override string ToString() {

View File

@@ -117,8 +117,4 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="EliteBGS" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\EliteBGS.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

View File

@@ -60,16 +60,6 @@ namespace EliteBGS {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon EliteBGS {
get {
object obj = ResourceManager.GetObject("EliteBGS", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>

View File

@@ -118,9 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="EliteBGS" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>EliteBGS.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="logo_v5" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="logo_v5" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>logo_v5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>logo_v5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -48,6 +48,16 @@ namespace EliteBGS.Util {
} }
} }
/// <summary>
/// Whether we ignore influence support scenarios form parsing.
/// </summary>
public bool IgnoreInfluenceSupport { get; set; } = false;
/// <summary>
/// Whether we ignore market buy entries during parsing.
/// </summary>
public bool IgnoreMarketBuy { get; set; } = false;
[JsonIgnore] [JsonIgnore]
public string FullTheme { public string FullTheme {
get { return Theme + "." + Colour; } get { return Theme + "." + Colour; }

View File

@@ -36,6 +36,7 @@ namespace EliteBGS.Util {
filestream.Flush(); filestream.Flush();
using (StreamWriter file = new StreamWriter(filestream, Encoding.UTF8)) { using (StreamWriter file = new StreamWriter(filestream, Encoding.UTF8)) {
var stream = new JsonTextWriter(file); var stream = new JsonTextWriter(file);
stream.Formatting = Formatting.Indented;
serializer.Serialize(stream, global_config); serializer.Serialize(stream, global_config);
} }
} }

View File

@@ -1,5 +1,27 @@
# EliteBGS changelog # EliteBGS changelog
## 0.3.2 on 19.04.2023
* Orthrus payout has been adapted to 14.02 values.
* Old Thargoid payout values have been removed, so very old logs now no
longer parse correctly. The old value clashed with new ones, making
detection of interceptor kills difficult.
* Fixed a problem regarding the proper detection of station owner, and
thus for whom the tool attributed market buy and market sell.
* Added GUI options to ignore some less important BGS entries.
* One line report has changed to show summaries
* Summaries have been streamlined:
* semi-colons now separate entries
* missing BGS actions (like S&R) have received a summary
* Trade has been renamed to "Sold" and "Bought"
* Sold now shows tons of cargo sold, plus profit if available
* Bought shows tons of cargo bought
## 0.3.1 on 26.02.2023
* Fixed: AX combat zones caused crashes with the summary.
* Fixed: Summaries for thargoid kills didn't render probably.
## 0.3.0 on 26.02.2023 ## 0.3.0 on 26.02.2023
* Move to MahApps toolkit, which replaces extended toolkit. * Move to MahApps toolkit, which replaces extended toolkit.

View File

@@ -20,13 +20,13 @@ command line:
winget install Microsoft.DotNet.DesktopRuntime.7 winget install Microsoft.DotNet.DesktopRuntime.7
``` ```
You can download the **latest** version **0.3.0** at CodeBerg: You can download the **latest** version **0.3.2** at CodeBerg:
* [https://codeberg.org/nola/EDBGS/releases](https://codeberg.org/nola/EDBGS/releases) * [https://codeberg.org/nola/EDBGS/releases](https://codeberg.org/nola/EDBGS/releases)
Or alternatively from my server: Or alternatively from my server:
* [https://bgs.n0la.org/elitebgs-0.3.0.zip](https://bgs.n0la.org/elitebgs-0.3.0.zip) * [https://bgs.n0la.org/elitebgs-0.3.2.zip](https://bgs.n0la.org/elitebgs-0.3.2.zip)
## Old Versions ## Old Versions