final
This commit is contained in:
67
BlueLaminate/BlueLaminate.Core/Tradeups/TradeupCandidate.cs
Normal file
67
BlueLaminate/BlueLaminate.Core/Tradeups/TradeupCandidate.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
namespace BlueLaminate.Core.Tradeups;
|
||||
|
||||
/// <summary>One possible result of a contract and what it would net if it lands.</summary>
|
||||
/// <param name="Probability">Chance this specific output is produced (single-collection: 1/k).</param>
|
||||
/// <param name="NetSellPrice">
|
||||
/// Realisable sale value after undercut + sell fee, or null when nothing comparable is
|
||||
/// listed (treated as unsellable for the worst-case test).
|
||||
/// </param>
|
||||
/// <param name="Liquidity">Active listings backing the price, in the same wear band.</param>
|
||||
/// <param name="PriceSource">Where the price came from: "market" (our stored listings) or
|
||||
/// "csfloat-live" (re-priced from the CSFloat API because the stored liquidity was thin).</param>
|
||||
public sealed record TradeupOutcome(
|
||||
int SkinId,
|
||||
string Name,
|
||||
decimal OutputFloat,
|
||||
WearBand Band,
|
||||
decimal Probability,
|
||||
decimal? NetSellPrice,
|
||||
int Liquidity,
|
||||
string PriceSource = "market");
|
||||
|
||||
/// <summary>
|
||||
/// One collection's share of a (possibly multi-collection) contract: how many of the ten
|
||||
/// inputs came from it, and which output tier those inputs roll into. Single-collection
|
||||
/// contracts have exactly one of these.
|
||||
/// </summary>
|
||||
public sealed record TradeupContribution(
|
||||
int CollectionId,
|
||||
string CollectionName,
|
||||
WeaponRarity OutputRarity,
|
||||
int InputCount);
|
||||
|
||||
/// <summary>
|
||||
/// A concrete, actionable tradeup: which ten copies to buy, what they cost, the output
|
||||
/// distribution, and the resulting economics. The finder returns these ranked; a frontend
|
||||
/// only formats them.
|
||||
/// <para>
|
||||
/// A contract may mix several collections (all inputs share the input rarity, but each
|
||||
/// collection rolls into its own next tier). <see cref="Composition"/> records the per-
|
||||
/// collection split; <see cref="CollectionCount"/> is its length. <see cref="OutputRarity"/>
|
||||
/// is the tier of the largest contributor (a display convenience for the common case).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public sealed record TradeupCandidate(
|
||||
int CollectionId,
|
||||
string CollectionName,
|
||||
WeaponRarity InputRarity,
|
||||
WeaponRarity OutputRarity,
|
||||
bool StatTrak,
|
||||
decimal AverageFraction,
|
||||
decimal InputCost,
|
||||
decimal ExpectedNet,
|
||||
decimal WorstCaseNet,
|
||||
bool Guaranteed,
|
||||
IReadOnlyList<InputListing> Inputs,
|
||||
IReadOnlyList<TradeupOutcome> Outcomes,
|
||||
IReadOnlyList<TradeupContribution> Composition)
|
||||
{
|
||||
/// <summary>Number of distinct collections the inputs are drawn from (1 = single-collection).</summary>
|
||||
public int CollectionCount => Composition.Count;
|
||||
|
||||
/// <summary>Expected profit across the output distribution, net of cost.</summary>
|
||||
public decimal ExpectedProfit => ExpectedNet - InputCost;
|
||||
|
||||
/// <summary>Profit if the worst (lowest-value) output lands — negative unless guaranteed.</summary>
|
||||
public decimal WorstCaseProfit => WorstCaseNet - InputCost;
|
||||
}
|
||||
Reference in New Issue
Block a user