Files
Operation-Blue-Laminate-v2/BlueLaminate/BlueLaminate.EFCore/Entities/SkinInstance.cs
2026-06-01 10:52:06 -05:00

53 lines
2.4 KiB
C#

namespace BlueLaminate.EFCore.Entities;
/// <summary>
/// One physical CS2 item, identified by its fingerprint
/// (Skin + FloatValue + PaintSeed + StatTrak + Souvenir) rather than its Steam
/// asset id, which changes on every trade. Decoupled from Steam inventories on
/// purpose: an instance exists from market observation alone, and the optional
/// <see cref="InventoryItem"/> bridge ties it to a <c>SteamUser</c> only once we
/// crawl inventories.
///
/// Duping note: a duplicated item is a byte-for-byte copy with an identical
/// fingerprint, so a fingerprint is NOT guaranteed unique to one physical item.
/// We treat the fingerprint as the item, and flag <see cref="SuspectedDupe"/>
/// when the same fingerprint is seen live under two or more different asset ids
/// at once (see the sweep's dupe detection).
/// </summary>
public class SkinInstance
{
public int Id { get; set; }
public int SkinId { get; set; }
public Skin Skin { get; set; } = null!;
// Nullable: market observation gives a float but not a derived wear bucket.
// Condition can be backfilled later from the float without blocking ingest.
public int? ConditionId { get; set; }
public SkinCondition? Condition { get; set; }
// The fingerprint. FloatValue is stored at full precision (see config) so
// that exact-match dupe detection isn't fooled by rounding. An instance is
// only created for items that have a float + paint seed (skins), so both are
// non-null here even though some listings (e.g. vanilla knives) lack them.
public decimal FloatValue { get; set; }
public int PaintSeed { get; set; }
public bool StatTrak { get; set; }
public bool Souvenir { get; set; }
public DateTimeOffset FirstSeenAt { get; set; }
public DateTimeOffset LastSeenAt { get; set; }
/// <summary>
/// True once this fingerprint was observed live under 2+ distinct asset ids
/// simultaneously — the signature of duplication.
/// </summary>
public bool SuspectedDupe { get; set; }
/// <summary>When the dupe condition was first detected. Null until then.</summary>
public DateTimeOffset? DupeFirstSeenAt { get; set; }
/// <summary>Every market listing observed for this physical item over time.</summary>
public ICollection<Listing> Listings { get; set; } = new List<Listing>();
public ICollection<InventoryItem> InventoryItems { get; set; } = new List<InventoryItem>();
}