< Summary

Information
Class: FirebaseAdapter.Models.FirestoreContextDocument
Assembly: FirebaseAdapter
File(s): /home/runner/work/KicktippAi/KicktippAi/src/FirebaseAdapter/Models/FirestoreModels.cs
Line coverage
100%
Covered lines: 7
Uncovered lines: 0
Coverable lines: 7
Total lines: 410
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_DocumentName()100%11100%
set_DocumentName(...)100%11100%
.ctor()100%11100%
get_Content()100%11100%
set_Content(...)100%11100%
get_Version()100%11100%
set_Version(...)100%11100%
get_CreatedAt()100%11100%
set_CreatedAt(...)100%11100%
get_Competition()100%11100%
set_Competition(...)100%11100%
get_CommunityContext()100%11100%
set_CommunityContext(...)100%11100%

File(s)

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

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