diff --git a/SVSim.Database/Models/Viewer.cs b/SVSim.Database/Models/Viewer.cs index bcf49b2..03149d0 100644 --- a/SVSim.Database/Models/Viewer.cs +++ b/SVSim.Database/Models/Viewer.cs @@ -59,6 +59,12 @@ public class Viewer : BaseEntity public List BuildDeckPurchases { get; set; } = new List(); + public List Missions { get; set; } = new List(); + + public List Achievements { get; set; } = new List(); + + public List EventCounters { get; set; } = new List(); + #endregion #region Navigation Properties diff --git a/SVSim.Database/Models/ViewerAchievement.cs b/SVSim.Database/Models/ViewerAchievement.cs new file mode 100644 index 0000000..a6c5954 --- /dev/null +++ b/SVSim.Database/Models/ViewerAchievement.cs @@ -0,0 +1,17 @@ +namespace SVSim.Database.Models; + +/// +/// Per-viewer state for one achievement type. Composite PK (ViewerId, AchievementType) configured +/// in DbContext. Level is the viewer's current tier; max_level on the wire is +/// derived from catalog as MAX(Level) per type. Lazy-created at /load/index time — one row per +/// AchievementCatalogEntries.AchievementType that the viewer doesn't yet have a row for. +/// +public class ViewerAchievement +{ + public long ViewerId { get; set; } + public int AchievementType { get; set; } + public int Level { get; set; } = 1; + public int AchievementStatus { get; set; } + public int NowAchievedLevel { get; set; } + public int ResultAnnounceSawLevel { get; set; } +} diff --git a/SVSim.Database/Models/ViewerEventCounter.cs b/SVSim.Database/Models/ViewerEventCounter.cs new file mode 100644 index 0000000..cdbc803 --- /dev/null +++ b/SVSim.Database/Models/ViewerEventCounter.cs @@ -0,0 +1,15 @@ +namespace SVSim.Database.Models; + +/// +/// Per-viewer "how many times has this happened" counter. Composite PK +/// (ViewerId, EventKey, Period). Period strings: "all-time", "month:YYYY-MM", +/// "week:YYYY-W##", "day:YYYY-MM-DD" — all JST-anchored with 02:00 day-boundary. +/// Single source of truth for total_count / done_number on every wire shape. +/// +public class ViewerEventCounter +{ + public long ViewerId { get; set; } + public string EventKey { get; set; } = ""; + public string Period { get; set; } = ""; + public int Count { get; set; } +} diff --git a/SVSim.Database/Models/ViewerMission.cs b/SVSim.Database/Models/ViewerMission.cs new file mode 100644 index 0000000..1c7e4a8 --- /dev/null +++ b/SVSim.Database/Models/ViewerMission.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SVSim.Database.Common; + +namespace SVSim.Database.Models; + +/// +/// One assigned mission slot for a viewer. Id is the wire UserMission.id — echoed +/// back as the retire-request parameter, auto-generated. Slot 0 = daily (lot_type=6), +/// Slots 1..3 = weekly (lot_type=2). Progress (total_count on the wire) is NOT stored +/// here — it's read from at response-build time, keyed by the +/// catalog row's EventType. +/// +public class ViewerMission : BaseEntity +{ + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public override long Id { get; set; } + + public long ViewerId { get; set; } + public int MissionCatalogId { get; set; } + public int Slot { get; set; } + public long AssignedAt { get; set; } + public long? ClaimedAt { get; set; } + public int MissionStatus { get; set; } = 1; +}