Files
step3/api/QuestionsApi/Models/CreditModels.cs
T
2026-07-29 18:34:54 -05:00

112 lines
3.5 KiB
C#

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace QuestionsApi.Models;
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
{
public string OperationId { get; set; } = "";
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]
[BsonRepresentation(BsonType.ObjectId)]
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;
}
public sealed class CreditStatusResponse
{
public int Credits { get; set; }
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();
}