< Summary

Information
Class: FirebaseAdapter.Models.FirestoreBonusPrediction
Assembly: FirebaseAdapter
File(s): /home/runner/work/KicktippAi/KicktippAi/src/FirebaseAdapter/Models/FirestoreModels.cs
Line coverage
100%
Covered lines: 13
Uncovered lines: 0
Coverable lines: 13
Total lines: 363
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Id()100%210%
set_Id(...)100%11100%
get_QuestionText()100%11100%
set_QuestionText(...)100%11100%
.ctor()100%11100%
get_SelectedOptionIds()100%11100%
set_SelectedOptionIds(...)100%11100%
get_SelectedOptionTexts()100%11100%
set_SelectedOptionTexts(...)100%11100%
get_CreatedAt()100%11100%
set_CreatedAt(...)100%11100%
get_UpdatedAt()100%11100%
set_UpdatedAt(...)100%11100%
get_Competition()100%11100%
set_Competition(...)100%11100%
get_Model()100%11100%
set_Model(...)100%11100%
get_TokenUsage()100%11100%
set_TokenUsage(...)100%11100%
get_Cost()100%11100%
set_Cost(...)100%11100%
get_CommunityContext()100%11100%
set_CommunityContext(...)100%11100%
get_ContextDocumentNames()100%11100%
set_ContextDocumentNames(...)100%11100%
get_RepredictionIndex()100%11100%
set_RepredictionIndex(...)100%11100%

File(s)

/home/runner/work/KicktippAi/KicktippAi/src/FirebaseAdapter/Models/FirestoreModels.cs

#LineLine coverage
 1using Google.Cloud.Firestore;
 2using NodaTime;
 3
 4namespace FirebaseAdapter.Models;
 5
 6/// <summary>
 7/// Firestore document model for storing match predictions.
 8/// </summary>
 9[FirestoreData]
 10public class FirestoreMatchPrediction
 11{
 12    /// <summary>
 13    /// Document ID constructed from match details for uniqueness.
 14    /// Format: "{homeTeam}_{awayTeam}_{startsAtTicks}_{matchday}"
 15    /// </summary>
 16    [FirestoreDocumentId]
 17    public string? Id { get; set; }
 18
 19    /// <summary>
 20    /// Home team name.
 21    /// </summary>
 22    [FirestoreProperty("homeTeam")]
 23    public string HomeTeam { get; set; } = string.Empty;
 24
 25    /// <summary>
 26    /// Away team name.
 27    /// </summary>
 28    [FirestoreProperty("awayTeam")]
 29    public string AwayTeam { get; set; } = string.Empty;
 30
 31    /// <summary>
 32    /// Match start time as UTC timestamp.
 33    /// </summary>
 34    [FirestoreProperty("startsAt")]
 35    public Timestamp StartsAt { get; set; }
 36
 37    /// <summary>
 38    /// Match day number (1-34 for Bundesliga).
 39    /// </summary>
 40    [FirestoreProperty("matchday")]
 41    public int Matchday { get; set; }
 42
 43    /// <summary>
 44    /// Predicted home team goals.
 45    /// </summary>
 46    [FirestoreProperty("homeGoals")]
 47    public int HomeGoals { get; set; }
 48
 49    /// <summary>
 50    /// Predicted away team goals.
 51    /// </summary>
 52    [FirestoreProperty("awayGoals")]
 53    public int AwayGoals { get; set; }
 54
 55    /// <summary>
 56    /// Optional structured justification payload (stored as JSON string) explaining the predicted outcome.
 57    /// </summary>
 58    [FirestoreProperty("justification")]
 59    public string? Justification { get; set; }
 60
 61    /// <summary>
 62    /// When the prediction was created (UTC timestamp).
 63    /// </summary>
 64    [FirestoreProperty("createdAt")]
 65    public Timestamp CreatedAt { get; set; }
 66
 67    /// <summary>
 68    /// When the prediction was last updated (UTC timestamp).
 69    /// </summary>
 70    [FirestoreProperty("updatedAt")]
 71    public Timestamp UpdatedAt { get; set; }
 72
 73    /// <summary>
 74    /// Competition/season identifier (e.g., "bundesliga-2025-26").
 75    /// </summary>
 76    [FirestoreProperty("competition")]
 77    public string Competition { get; set; } = "bundesliga-2025-26";
 78
 79    /// <summary>
 80    /// The AI model used to generate this prediction (e.g., "gpt-4o", "o1-mini").
 81    /// </summary>
 82    [FirestoreProperty("model")]
 83    public string Model { get; set; } = string.Empty;
 84
 85    /// <summary>
 86    /// JSON string containing the token usage object from the API (e.g., completion_tokens, prompt_tokens, total_tokens
 87    /// </summary>
 88    [FirestoreProperty("tokenUsage")]
 89    public string TokenUsage { get; set; } = string.Empty;
 90
 91    /// <summary>
 92    /// Cost in USD to generate this prediction.
 93    /// </summary>
 94    [FirestoreProperty("cost")]
 95    public double Cost { get; set; }
 96
 97    /// <summary>
 98    /// The community context (community rules) used to generate this prediction.
 99    /// </summary>
 100    [FirestoreProperty("communityContext")]
 101    public string CommunityContext { get; set; } = string.Empty;
 102
 103    /// <summary>
 104    /// Names of context documents that were used as input for generating this prediction.
 105    /// Used to check if prediction is outdated compared to context changes.
 106    /// </summary>
 107    [FirestoreProperty("contextDocumentNames")]
 108    public string[] ContextDocumentNames { get; set; } = [];
 109
 110    /// <summary>
 111    /// Reprediction index for tracking prediction versions.
 112    /// Starts at 0 for the first prediction, increments for each reprediction.
 113    /// </summary>
 114    [FirestoreProperty("repredictionIndex")]
 115    public int RepredictionIndex { get; set; } = 0;
 116}
 117
 118/// <summary>
 119/// Firestore document model for storing match information without predictions.
 120/// Used for managing match days and match schedules.
 121/// </summary>
 122[FirestoreData]
 123public class FirestoreMatch
 124{
 125    /// <summary>
 126    /// Document ID constructed from match details.
 127    /// </summary>
 128    [FirestoreDocumentId]
 129    public string? Id { get; set; }
 130
 131    /// <summary>
 132    /// Home team name.
 133    /// </summary>
 134    [FirestoreProperty("homeTeam")]
 135    public string HomeTeam { get; set; } = string.Empty;
 136
 137    /// <summary>
 138    /// Away team name.
 139    /// </summary>
 140    [FirestoreProperty("awayTeam")]
 141    public string AwayTeam { get; set; } = string.Empty;
 142
 143    /// <summary>
 144    /// Match start time as UTC timestamp.
 145    /// </summary>
 146    [FirestoreProperty("startsAt")]
 147    public Timestamp StartsAt { get; set; }
 148
 149    /// <summary>
 150    /// Match day number (1-34 for Bundesliga).
 151    /// </summary>
 152    [FirestoreProperty("matchday")]
 153    public int Matchday { get; set; }
 154
 155    /// <summary>
 156    /// Competition/season identifier.
 157    /// </summary>
 158    [FirestoreProperty("competition")]
 159    public string Competition { get; set; } = "bundesliga-2025-26";
 160
 161    /// <summary>
 162    /// Indicates whether the match has been cancelled.
 163    /// Cancelled matches show "Abgesagt" on Kicktipp instead of a scheduled time.
 164    /// See docs/features/cancelled-matches.md for design rationale.
 165    /// </summary>
 166    [FirestoreProperty("isCancelled")]
 167    public bool IsCancelled { get; set; } = false;
 168}
 169
 170/// <summary>
 171/// Firestore document model for storing bonus predictions.
 172/// </summary>
 173[FirestoreData]
 174public class FirestoreBonusPrediction
 175{
 176    /// <summary>
 177    /// Document ID - unique identifier for the prediction.
 178    /// </summary>
 179    [FirestoreDocumentId]
 1180    public string? Id { get; set; }
 181
 182    /// <summary>
 183    /// The bonus question text (for observability).
 184    /// </summary>
 185    [FirestoreProperty("questionText")]
 1186    public string QuestionText { get; set; } = string.Empty;
 187
 188    /// <summary>
 189    /// Selected option IDs for the bonus question.
 190    /// </summary>
 191    [FirestoreProperty("selectedOptionIds")]
 1192    public string[] SelectedOptionIds { get; set; } = [];
 193
 194    /// <summary>
 195    /// Selected option texts (for observability).
 196    /// </summary>
 197    [FirestoreProperty("selectedOptionTexts")]
 1198    public string[] SelectedOptionTexts { get; set; } = [];
 199
 200    /// <summary>
 201    /// When the bonus prediction was created (UTC timestamp).
 202    /// </summary>
 203    [FirestoreProperty("createdAt")]
 1204    public Timestamp CreatedAt { get; set; }
 205
 206    /// <summary>
 207    /// When the bonus prediction was last updated (UTC timestamp).
 208    /// </summary>
 209    [FirestoreProperty("updatedAt")]
 1210    public Timestamp UpdatedAt { get; set; }
 211
 212    /// <summary>
 213    /// Competition/season identifier (e.g., "bundesliga-2025-26").
 214    /// </summary>
 215    [FirestoreProperty("competition")]
 1216    public string Competition { get; set; } = "bundesliga-2025-26";
 217
 218    /// <summary>
 219    /// The AI model used to generate this prediction (e.g., "gpt-4o", "o1-mini").
 220    /// </summary>
 221    [FirestoreProperty("model")]
 1222    public string Model { get; set; } = string.Empty;
 223
 224    /// <summary>
 225    /// JSON string containing the token usage object from the API (e.g., completion_tokens, prompt_tokens, total_tokens
 226    /// </summary>
 227    [FirestoreProperty("tokenUsage")]
 1228    public string TokenUsage { get; set; } = string.Empty;
 229
 230    /// <summary>
 231    /// Cost in USD to generate this prediction.
 232    /// </summary>
 233    [FirestoreProperty("cost")]
 1234    public double Cost { get; set; }
 235
 236    /// <summary>
 237    /// The community context (community rules) used to generate this prediction.
 238    /// </summary>
 239    [FirestoreProperty("communityContext")]
 1240    public string CommunityContext { get; set; } = string.Empty;
 241
 242    /// <summary>
 243    /// Names of context documents that were used as input for generating this prediction.
 244    /// Used to check if prediction is outdated compared to context changes.
 245    /// </summary>
 246    [FirestoreProperty("contextDocumentNames")]
 1247    public string[] ContextDocumentNames { get; set; } = [];
 248
 249    /// <summary>
 250    /// Reprediction index for tracking prediction versions.
 251    /// Starts at 0 for the first prediction, increments for each reprediction.
 252    /// </summary>
 253    [FirestoreProperty("repredictionIndex")]
 1254    public int RepredictionIndex { get; set; } = 0;
 255}
 256
 257/// <summary>
 258/// Firestore document model for storing KPI context documents.
 259/// Used for storing contextual data for bonus predictions.
 260/// </summary>
 261[FirestoreData]
 262public class FirestoreKpiDocument
 263{
 264    /// <summary>
 265    /// Document ID - constructed from document name, community context, and version.
 266    /// Format: "{documentName}_{communityContext}_{version}"
 267    /// </summary>
 268    [FirestoreDocumentId]
 269    public string? Id { get; set; }
 270
 271    /// <summary>
 272    /// The document name (for observability and context lookup consistency).
 273    /// </summary>
 274    [FirestoreProperty("documentName")]
 275    public string DocumentName { get; set; } = string.Empty;
 276
 277    /// <summary>
 278    /// The document content (TSV format).
 279    /// </summary>
 280    [FirestoreProperty("content")]
 281    public string Content { get; set; } = string.Empty;
 282
 283    /// <summary>
 284    /// Document description.
 285    /// </summary>
 286    [FirestoreProperty("description")]
 287    public string Description { get; set; } = string.Empty;
 288
 289    /// <summary>
 290    /// Version number for this document (starts at 0).
 291    /// </summary>
 292    [FirestoreProperty("version")]
 293    public int Version { get; set; }
 294
 295    /// <summary>
 296    /// When the document was created (UTC timestamp).
 297    /// </summary>
 298    [FirestoreProperty("createdAt")]
 299    public Timestamp CreatedAt { get; set; }
 300
 301    /// <summary>
 302    /// Competition/season identifier (e.g., "bundesliga-2025-26").
 303    /// </summary>
 304    [FirestoreProperty("competition")]
 305    public string Competition { get; set; } = "bundesliga-2025-26";
 306
 307    /// <summary>
 308    /// Community context for filtering KPI documents.
 309    /// </summary>
 310    [FirestoreProperty("communityContext")]
 311    public string CommunityContext { get; set; } = string.Empty;
 312}
 313
 314/// <summary>
 315/// Firestore document model for storing versioned context documents.
 316/// Used for storing contextual data retrieved from Kicktipp for matchday predictions.
 317/// </summary>
 318[FirestoreData]
 319public class FirestoreContextDocument
 320{
 321    /// <summary>
 322    /// Document ID - constructed from document name, community context, and version.
 323    /// Format: "{documentName}_{communityContext}_{version}"
 324    /// </summary>
 325    [FirestoreDocumentId]
 326    public string? Id { get; set; }
 327
 328    /// <summary>
 329    /// The context document name (e.g., "bundesliga-standings.csv", "recent-history-fcb.csv").
 330    /// </summary>
 331    [FirestoreProperty("documentName")]
 332    public string DocumentName { get; set; } = string.Empty;
 333
 334    /// <summary>
 335    /// The document content (CSV format).
 336    /// </summary>
 337    [FirestoreProperty("content")]
 338    public string Content { get; set; } = string.Empty;
 339
 340    /// <summary>
 341    /// Version number for this document (starts at 0).
 342    /// </summary>
 343    [FirestoreProperty("version")]
 344    public int Version { get; set; }
 345
 346    /// <summary>
 347    /// When the document was created (UTC timestamp).
 348    /// </summary>
 349    [FirestoreProperty("createdAt")]
 350    public Timestamp CreatedAt { get; set; }
 351
 352    /// <summary>
 353    /// Competition/season identifier (e.g., "bundesliga-2025-26").
 354    /// </summary>
 355    [FirestoreProperty("competition")]
 356    public string Competition { get; set; } = "bundesliga-2025-26";
 357
 358    /// <summary>
 359    /// Community context for filtering context documents.
 360    /// </summary>
 361    [FirestoreProperty("communityContext")]
 362    public string CommunityContext { get; set; } = string.Empty;
 363}