| | | 1 | | using System.Globalization; |
| | | 2 | | using Microsoft.Extensions.Logging; |
| | | 3 | | using NodaTime; |
| | | 4 | | using Orchestrator.Infrastructure; |
| | | 5 | | using Orchestrator.Infrastructure.Factories; |
| | | 6 | | using Spectre.Console; |
| | | 7 | | using Spectre.Console.Cli; |
| | | 8 | | |
| | | 9 | | namespace Orchestrator.Commands.Operations.Wm26RecentHistory; |
| | | 10 | | |
| | | 11 | | public sealed class Wm26RecentHistoryProbePredictionLookupCommand |
| | | 12 | | : AsyncCommand<Wm26RecentHistoryProbePredictionLookupSettings> |
| | | 13 | | { |
| | 1 | 14 | | private static readonly DateTimeZone BerlinTimeZone = DateTimeZoneProviders.Tzdb["Europe/Berlin"]; |
| | | 15 | | |
| | | 16 | | private readonly IAnsiConsole _console; |
| | | 17 | | private readonly IFirebaseServiceFactory _firebaseServiceFactory; |
| | | 18 | | private readonly ILogger<Wm26RecentHistoryProbePredictionLookupCommand> _logger; |
| | | 19 | | |
| | 1 | 20 | | public Wm26RecentHistoryProbePredictionLookupCommand( |
| | 1 | 21 | | IAnsiConsole console, |
| | 1 | 22 | | IFirebaseServiceFactory firebaseServiceFactory, |
| | 1 | 23 | | ILogger<Wm26RecentHistoryProbePredictionLookupCommand> logger) |
| | | 24 | | { |
| | 1 | 25 | | _console = console; |
| | 1 | 26 | | _firebaseServiceFactory = firebaseServiceFactory; |
| | 1 | 27 | | _logger = logger; |
| | 1 | 28 | | } |
| | | 29 | | |
| | | 30 | | protected override async Task<int> ExecuteAsync( |
| | | 31 | | CommandContext context, |
| | | 32 | | Wm26RecentHistoryProbePredictionLookupSettings settings, |
| | | 33 | | CancellationToken cancellationToken) |
| | | 34 | | { |
| | | 35 | | try |
| | | 36 | | { |
| | 1 | 37 | | var competition = CompetitionResolver.ResolveCompetition( |
| | 1 | 38 | | settings.Competition, |
| | 1 | 39 | | communityContext: settings.CommunityContext); |
| | 1 | 40 | | var repositoryCompetition = CompetitionResolver.ToRepositoryCompetitionArgument(competition); |
| | 1 | 41 | | var predictionRepository = _firebaseServiceFactory.CreatePredictionRepository(repositoryCompetition); |
| | | 42 | | |
| | 1 | 43 | | _console.MarkupLine("[green]Probing latest predicted match lookup[/]"); |
| | 1 | 44 | | _console.MarkupLine($"[blue]Using community context:[/] [yellow]{Markup.Escape(settings.CommunityContext)}[/ |
| | 1 | 45 | | _console.MarkupLine($"[blue]Using competition:[/] [yellow]{Markup.Escape(competition)}[/]"); |
| | 1 | 46 | | _console.MarkupLine( |
| | 1 | 47 | | $"[blue]Query:[/] [yellow]{Markup.Escape(settings.HomeTeam.Trim())}[/] vs [yellow]{Markup.Escape(setting |
| | | 48 | | |
| | 1 | 49 | | if (settings.Verbose) |
| | | 50 | | { |
| | 1 | 51 | | _console.MarkupLine( |
| | 1 | 52 | | "[dim]Firestore query filters match-predictions by competition, communityContext, homeTeam, awayTeam |
| | | 53 | | } |
| | | 54 | | |
| | 1 | 55 | | var match = await predictionRepository.GetLatestPredictedMatchByTeamsAsync( |
| | 1 | 56 | | settings.HomeTeam, |
| | 1 | 57 | | settings.AwayTeam, |
| | 1 | 58 | | settings.CommunityContext, |
| | 1 | 59 | | cancellationToken); |
| | | 60 | | |
| | 1 | 61 | | if (match is null) |
| | | 62 | | { |
| | 0 | 63 | | _console.MarkupLine("[yellow]No matching prediction found[/]"); |
| | 0 | 64 | | return 1; |
| | | 65 | | } |
| | | 66 | | |
| | 1 | 67 | | _console.MarkupLine( |
| | 1 | 68 | | "[green]Found latest predicted match:[/] " + |
| | 1 | 69 | | $"{Markup.Escape(match.HomeTeam)} vs {Markup.Escape(match.AwayTeam)}, " + |
| | 1 | 70 | | $"matchday {match.Matchday}, starts at {FormatPlayedAt(match.StartsAt)}"); |
| | | 71 | | |
| | 1 | 72 | | return 0; |
| | | 73 | | } |
| | 0 | 74 | | catch (Exception ex) |
| | | 75 | | { |
| | 0 | 76 | | _logger.LogError(ex, "Failed to probe WM26 prediction lookup"); |
| | 0 | 77 | | _console.MarkupLine($"[red]Error:[/] {Markup.Escape(ex.Message)}"); |
| | 0 | 78 | | return 1; |
| | | 79 | | } |
| | 1 | 80 | | } |
| | | 81 | | |
| | | 82 | | private static string FormatPlayedAt(ZonedDateTime startsAt) |
| | | 83 | | { |
| | 1 | 84 | | var local = startsAt.WithZone(BerlinTimeZone); |
| | 1 | 85 | | var dateTimeOffset = new DateTimeOffset( |
| | 1 | 86 | | local.LocalDateTime.ToDateTimeUnspecified(), |
| | 1 | 87 | | local.Offset.ToTimeSpan()); |
| | | 88 | | |
| | 1 | 89 | | return dateTimeOffset.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture); |
| | | 90 | | } |
| | | 91 | | } |