Пример #1
0
    public async Task <ActionResult <int> > ImportChallengeAsync(ChallengeImportDto dto)
    {
        _ = dto ?? throw new ArgumentNullException(nameof(dto));

        try
        {
            return(await _challengeService.ImportChallengeAsync(dto));
        }
        catch (HttpRequestException e)
        {
            return(BadRequest(e.Message));
        }
        catch (InvalidOperationException e)
        {
            return(BadRequest(e.Message));
        }
    }
Пример #2
0
    public async Task <int> ImportChallengeAsync(ChallengeImportDto dto, int gameId)
    {
        _ = dto ?? throw new ArgumentNullException(nameof(dto));

        (GeoGuessrChallenge challenge, IList <GeoGuessrChallengeResult> results) = await _geoGuessrService.ImportChallengeAsync(dto.GeoGuessrId);

        var        locations    = new List <Location>();
        HttpClient googleClient = _clientFactory.CreateClient("google");

        for (int i = 0; i < results[0].Game.Rounds.Count; i++)
        {
            GeoGuessrRound round   = results[0].Game.Rounds[i];
            string         query   = $"geocode/json?latlng={round.Lat.ToString(CultureInfo.InvariantCulture)},{round.Lng.ToString(CultureInfo.InvariantCulture)}&key={_options.GoogleApiKey}";
            GoogleGeocode? geocode = await googleClient.GetFromJsonAsync <GoogleGeocode>(query);

            if (geocode?.Results?.Count > 0)
            {
                GoogleGeocodeResult result = geocode.Results[0];
                var location = new Location()
                {
                    DisplayName = result.FormattedAddress,
                    Locality    = result.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"))?.Name,
                    AdministrativeAreaLevel2 = result.AddressComponents.FirstOrDefault(x => x.Types.Contains("administrative_area_level_2"))?.Name,
                    AdministrativeAreaLevel1 = result.AddressComponents.FirstOrDefault(x => x.Types.Contains("administrative_area_level_1"))?.Name,
                    Country     = result.AddressComponents.FirstOrDefault(x => x.Types.Contains("country"))?.Name,
                    Latitude    = round.Lat,
                    Longitude   = round.Lng,
                    RoundNumber = i + 1,
                };

                locations.Add(location);
            }
        }

        var playerScores = new List <PlayerScore>();

        foreach (GeoGuessrPlayer geoChallengeGamePlayer in results.Select(g => g.Game.Player))
        {
            bool   isMainPlayer = true;
            Player player       = await _context.Players.FindAsync(geoChallengeGamePlayer.Id) ?? new Player
            {
                Id   = geoChallengeGamePlayer.Id,
                Name = geoChallengeGamePlayer.Nick,
            };

            if (player.AssociatedPlayerId is not null)
            {
                player       = (await _context.Players.FindAsync(player.AssociatedPlayerId)) !;
                isMainPlayer = false;
            }

            // Update icon in order to have the most recent one.
            if (!string.IsNullOrWhiteSpace(geoChallengeGamePlayer.Pin.Url.ToString()))
            {
                player.IconUrl = new Uri($"https://www.geoguessr.com/images/auto/144/144/ce/0/plain/{geoChallengeGamePlayer.Pin.Url}");
            }
            else
            {
                player.IconUrl = Constants.BaseAvatarUrl;
            }

            var playerScore = new PlayerScore
            {
                PlayerId      = player.Id,
                Player        = player,
                PlayerGuesses = geoChallengeGamePlayer.Guesses.Select((p, i) => new PlayerGuess
                {
                    Score             = p.RoundScoreInPoints,
                    RoundNumber       = i + 1,
                    Time              = p.Time,
                    TimedOut          = p.TimedOut,
                    TimedOutWithGuess = p.TimedOutWithGuess,
                    Distance          = p.DistanceInMeters,
                }).ToList(),
            };

            if (isMainPlayer && playerScores.Any(ps => ps.PlayerId == playerScore.PlayerId))
            {
                playerScores.RemoveAll(ps => ps.PlayerId == playerScore.PlayerId);
            }

            if (!playerScores.Any(ps => ps.PlayerId == playerScore.PlayerId))
            {
                playerScores.Add(playerScore);
            }
        }

        Map map = await _context.Maps.FindAsync(challenge.Map.Id) ?? new Map
        {
            Id   = challenge.Map.Id,
            Name = challenge.Map.Name,
        };

        Player?creator = await _context.Players.FindAsync(challenge.Creator.Id);

        if (creator is null)
        {
            throw new InvalidOperationException($"Cannot import challenges created by {challenge.Creator.Nick}.");
        }

        var newChallenge = new Challenge()
        {
            GameId       = gameId,
            MapId        = map.Id,
            Map          = map,
            GeoGuessrId  = dto.GeoGuessrId,
            PlayerScores = playerScores,
            TimeLimit    = challenge.Challenge.TimeLimit,
            Locations    = locations,
            CreatorId    = creator.Id,
            UpdatedAt    = DateTime.UtcNow,
        };

        Challenge?existingChallenge = await _context
                                      .Challenges
                                      .Include(c => c.Map)
                                      .Include(c => c.PlayerScores).ThenInclude(c => c.PlayerGuesses)
                                      .Include(c => c.Locations)
                                      .SingleOrDefaultAsync(c => c.GeoGuessrId == dto.GeoGuessrId);

        int challengeId;

        if (existingChallenge is not null)
        {
            if (existingChallenge.GameId != gameId)
            {
                throw new InvalidOperationException($"The challenge with GeoGuessr Id '{dto.GeoGuessrId}' is already linked to a game and cannot be updated.");
            }

            if (!dto.OverrideData)
            {
                throw new InvalidOperationException($"The challenge with GeoGuessr Id '{dto.GeoGuessrId}' already exists.");
            }

            existingChallenge.PlayerScores = newChallenge.PlayerScores;
            existingChallenge.MapId        = newChallenge.MapId;
            existingChallenge.Map          = newChallenge.Map;
            existingChallenge.TimeLimit    = newChallenge.TimeLimit;
            existingChallenge.Locations    = newChallenge.Locations;
            existingChallenge.CreatorId    = newChallenge.CreatorId;
            existingChallenge.UpdatedAt    = newChallenge.UpdatedAt;

            challengeId = existingChallenge.Id;
            await _context.SaveChangesAsync();
        }
        else
        {
            EntityEntry <Challenge>?newChallengeEntity = _context.Challenges.Add(newChallenge);
            await _context.SaveChangesAsync();

            challengeId = newChallengeEntity.Entity.Id;
        }

        _cache.Remove(CacheKeys.PlayerServiceGetAllAsync);
        _cache.Remove(CacheKeys.MapServiceGetAllAsync);
        return(challengeId);
    }
Пример #3
0
 public Task <int> ImportChallengeAsync(ChallengeImportDto dto)
 {
     return(ImportChallengeAsync(dto, -1));
 }