Add Rz Coin utility store

This commit is contained in:
hz
2026-07-29 18:34:54 -05:00
parent c14ac1d65b
commit da641a8d1d
21 changed files with 656 additions and 21 deletions
+76
View File
@@ -7,6 +7,44 @@ public static class CreditEconomy
{
public const int RollingEarningLimit = 20;
public static readonly TimeSpan EarningWindow = TimeSpan.FromHours(24);
public const string ExamTokenSku = "exam_token_1";
public const string QBankResetTokenSku = "qbank_reset_1";
public const int ExamTokenPrice = 100;
public const int QBankResetTokenPrice = 300;
public static readonly IReadOnlyList<RzStoreProduct> Products =
[
new()
{
Sku = ExamTokenSku,
Name = "Exam Simulation Token",
Description = "Starts one new full exam simulation.",
CoinPrice = ExamTokenPrice,
Grant = RzStoreGrant.ExamToken
},
new()
{
Sku = QBankResetTokenSku,
Name = "QBank Reset Token",
Description = "Makes every QBank question eligible again without erasing progress.",
CoinPrice = QBankResetTokenPrice,
Grant = RzStoreGrant.QBankResetToken
}
];
public static RzStoreProduct? FindProduct(string sku) =>
Products.FirstOrDefault(value => value.Sku.Equals(sku, StringComparison.Ordinal));
}
public enum RzStoreGrant { ExamToken, QBankResetToken }
public sealed class RzStoreProduct
{
public string Sku { get; set; } = "";
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public int CoinPrice { get; set; }
public RzStoreGrant Grant { get; set; }
}
public sealed class CreditEvent
@@ -15,6 +53,14 @@ public sealed class CreditEvent
public DateTime CreatedUtc { get; set; }
}
public sealed class CreditPurchaseEvent
{
public string OperationId { get; set; } = "";
public string Sku { get; set; } = "";
public int CoinCost { get; set; }
public DateTime CreatedUtc { get; set; }
}
public sealed class UserCreditAccount
{
[BsonId]
@@ -22,7 +68,13 @@ public sealed class UserCreditAccount
public string? Id { get; set; }
public string UserId { get; set; } = "";
public int Credits { get; set; }
public int ExamTokens { get; set; }
public int QBankResetTokens { get; set; }
public int BankCycle { get; set; }
public bool InitialExamGrantApplied { get; set; }
public List<CreditEvent> RecentEarnings { get; set; } = [];
public List<CreditPurchaseEvent> Purchases { get; set; } = [];
public List<string> AppliedOperations { get; set; } = [];
public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow;
}
@@ -32,4 +84,28 @@ public sealed class CreditStatusResponse
public int EarnedInRollingWindow { get; set; }
public int RemainingEarningCapacity { get; set; }
public int RollingWindowHours { get; set; } = 24;
public int ExamTokens { get; set; }
public int QBankResetTokens { get; set; }
public int BankCycle { get; set; }
public IReadOnlyList<RzStoreProduct> Products { get; set; } = CreditEconomy.Products;
}
public sealed class CreditPurchaseRequest
{
public string Sku { get; set; } = "";
public string OperationId { get; set; } = "";
}
public sealed class QBankResetRequest
{
public string Confirmation { get; set; } = "";
public string OperationId { get; set; } = "";
}
public enum CreditOperationResult { Succeeded, InsufficientCredits, InsufficientTokens, OperationConflict }
public sealed class CreditOperationResponse
{
public CreditOperationResult Result { get; set; }
public CreditStatusResponse Status { get; set; } = new();
}
@@ -11,6 +11,7 @@ public class QuestionAttempt
public string QuestionExternalId { get; set; } = "";
public string UserId { get; set; } = "";
public int BankCycle { get; set; }
public string ChoiceId { get; set; } = "";
public List<string> PresentedChoiceIds { get; set; } = [];
public bool TracksPresentation { get; set; }