示例#1
0
    public async ValueTask <ActionResult <TypingReport> > GetTypingReportForUserSession(string userSessionId, TextGenerationType textGenerationType = TextGenerationType.GeneratedStardardText)
    {
        var report = await _typingReportGenerator.GenerateReportForUserSessionAsync(userSessionId, textGenerationType);

        return(Ok(report));
    }
示例#2
0
    public async ValueTask SaveAsync(string userId, UserTypingStatistics userTypingStatistics, string language, TextGenerationType textGenerationType)
    {
        var stringData = JsonSerializer.Serialize(userTypingStatistics);

        await _cache.SetStringAsync($"typingrealm-data-user-statistics-{userId}_{language}_{textGenerationType}", stringData)
        .ConfigureAwait(false);
    }
示例#3
0
    public async ValueTask <ActionResult <TypingReport> > GetTypingReport(string?language = "en", TextGenerationType textGenerationType = TextGenerationType.GeneratedStardardText)
    {
        if (language == null)
        {
            language = "en";
        }

        var report = await _typingReportGenerator.GenerateReportAsync(ProfileId, language, textGenerationType);

        return(Ok(report));
    }
示例#4
0
    public async ValueTask <UserTypingStatistics?> GetUserTypingStatisticsAsync(string userId, string language, TextGenerationType textGenerationType)
    {
        var stringData = await _cache.GetStringAsync($"typingrealm-data-user-statistics-{userId}_{language}_{textGenerationType}")
                         .ConfigureAwait(false);

        if (stringData == null || stringData.Length == 0)
        {
            return(null);
        }

        return(JsonSerializer.Deserialize <UserTypingStatistics>(stringData));
    }
 public ValueTask SaveAsync(string userId, UserTypingStatistics userTypingStatistics, string language, TextGenerationType textGenerationType)
 {
     if (_userTypingStatistics.ContainsKey(GetKey(userId, language, textGenerationType)))
     {
         _userTypingStatistics[userId] = userTypingStatistics;
         return(default);
    public async ValueTask <UserTypingStatistics?> GetUserTypingStatisticsAsync(string userId, string language, TextGenerationType textGenerationType)
    {
        if (!_userTypingStatistics.ContainsKey(GetKey(userId, language, textGenerationType)))
        {
            return(null);
        }

        return(_userTypingStatistics[GetKey(userId, language, textGenerationType)]);
    }
示例#7
0
    public async ValueTask <UserTypingStatistics> GenerateUserStatisticsAsync(string userId, string language, TextGenerationType textGenerationType)
    {
        var existingStatistics = await _userTypingStatisticsStore.GetUserTypingStatisticsAsync(userId, language, textGenerationType)
                                 .ConfigureAwait(false);

        var userSessions = Enumerable.Empty <UserSession>();

        userSessions = existingStatistics != null
            ? await _userSessionRepository.FindAllForUserFromTypingResultsAsync(userId, existingStatistics.LastHandledResultUtc)
                       .ConfigureAwait(false)
            : await _userSessionRepository.FindAllForUserAsync(userId)
                       .ConfigureAwait(false);

        var      results              = new List <TextAnalysisResult>();
        var      textsTypedCount      = 0;
        DateTime lastHandledResultUtc = default;

        foreach (var userSession in userSessions)
        {
            var typingSession = await _typingSessionRepository.FindAsync(userSession.TypingSessionId)
                                .ConfigureAwait(false);

            if (typingSession == null)
            {
                throw new InvalidOperationException("Typing session is not found.");
            }

            foreach (var textTypingResult in userSession.GetTextTypingResults())
            {
                textsTypedCount++;
                if (textTypingResult.SubmittedResultsUtc > lastHandledResultUtc)
                {
                    lastHandledResultUtc = textTypingResult.SubmittedResultsUtc;
                }

                var text = typingSession.GetTypingSessionTextAtIndexOrDefault(textTypingResult.TypingSessionTextIndex);
                if (text == null)
                {
                    throw new InvalidOperationException("Text is not found in typing session.");
                }

                var textEntity = await _textRepository.FindAsync(text.TextId)
                                 .ConfigureAwait(false);

                if (textEntity == null)
                {
                    throw new InvalidOperationException("Text is not found.");
                }

                if (textEntity.Language != language)
                {
                    continue;
                }

                if (textEntity.TextGenerationType != textGenerationType)
                {
                    continue; // Generate statistics only for requested text generation type.
                }
                var textAnalysisResult = await _textTypingResultValidator.ValidateAsync(text.Value, textTypingResult)
                                         .ConfigureAwait(false);

                results.Add(textAnalysisResult);
            }
        }

        if (results.Count == 0)
        {
            if (existingStatistics != null)
            {
                // No new data yet.
                return(existingStatistics);
            }

            return(new UserTypingStatistics(0, 0, Enumerable.Empty <KeyPairAggregatedData>(), DateTime.UtcNow));
        }

        var aggregatedResult = new TextAnalysisResult(
            results.Sum(x => x.SpeedCpm) / results.Count,
            results.SelectMany(x => x.KeyPairs));

        var specificKeys   = aggregatedResult.KeyPairs.GroupBy(x => new { x.FromKey, x.ShouldBeKey });
        var aggregatedData = specificKeys.Select(x => new KeyPairAggregatedData(
                                                     x.Key.FromKey, x.Key.ShouldBeKey,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Average(y => y.Delay)
                : 0,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Min(y => y.Delay)
                : 0,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Max(y => y.Delay)
                : 0,
                                                     x.Count(y => y.Type == KeyPairType.Correct),
                                                     x.Count(y => y.Type == KeyPairType.Mistake)));

        var result = MergeAndReturnNew(existingStatistics, new TypingReport(aggregatedResult, aggregatedData), textsTypedCount, lastHandledResultUtc);
        await _userTypingStatisticsStore.SaveAsync(userId, result, language, textGenerationType)
        .ConfigureAwait(false);

        return(result);
    }
示例#8
0
    public async ValueTask <TypingReport> GenerateReportForUserSessionAsync(string userSessionId, TextGenerationType textGenerationType)
    {
        var results = new List <TextAnalysisResult>();

        var userSession = await _userSessionRepository.FindAsync(userSessionId)
                          .ConfigureAwait(false);

        if (userSession == null)
        {
            throw new InvalidOperationException("Could not find user session.");
        }

        var typingSession = await _typingSessionRepository.FindAsync(userSession.TypingSessionId)
                            .ConfigureAwait(false);

        if (typingSession == null)
        {
            throw new InvalidOperationException("Typing session is not found.");
        }

        foreach (var textTypingResult in userSession.GetTextTypingResults())
        {
            var text = typingSession.GetTypingSessionTextAtIndexOrDefault(textTypingResult.TypingSessionTextIndex);
            if (text == null)
            {
                throw new InvalidOperationException("Text is not found in typing session.");
            }

            var textEntity = await _textRepository.FindAsync(text.TextId)
                             .ConfigureAwait(false);

            if (textEntity == null)
            {
                throw new InvalidOperationException("Text is not found.");
            }

            if (textGenerationType != textEntity.TextGenerationType)
            {
                continue;
            }

            var textAnalysisResult = await _textTypingResultValidator.ValidateAsync(text.Value, textTypingResult)
                                     .ConfigureAwait(false);

            results.Add(textAnalysisResult);
        }

        if (results.Count == 0)
        {
            // No data yet.
            return(new TypingReport(new TextAnalysisResult(0, Enumerable.Empty <KeyPair>()), Enumerable.Empty <KeyPairAggregatedData>()));
        }

        var aggregatedResult = new TextAnalysisResult(
            results.Sum(x => x.SpeedCpm) / results.Count,
            results.SelectMany(x => x.KeyPairs));

        var specificKeys   = aggregatedResult.KeyPairs.GroupBy(x => new { x.FromKey, x.ShouldBeKey });
        var aggregatedData = specificKeys.Select(x => new KeyPairAggregatedData(
                                                     x.Key.FromKey, x.Key.ShouldBeKey,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Average(y => y.Delay)
                : 0,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Min(y => y.Delay)
                : 0,
                                                     x.Where(y => y.Type == KeyPairType.Correct).Any()
                ? x.Where(y => y.Type == KeyPairType.Correct).Max(y => y.Delay)
                : 0,
                                                     x.Count(y => y.Type == KeyPairType.Correct),
                                                     x.Count(y => y.Type == KeyPairType.Mistake)));

        return(new TypingReport(aggregatedResult, aggregatedData));
    }