public async ValueTask AddTypingResultAsync(string userSessionId, TextTypingResult textTypingResult)
    {
        var userSession = await _userSessionRepository.FindAsync(userSessionId)
                          .ConfigureAwait(false);

        if (userSession == null)
        {
            throw new InvalidOperationException("User session does not exist.");
        }

        // TODO: Validate that it is currently active session.

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

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

        // TODO: Validate that it is type-able (active, etc).

        var typingSessionText = typingSession.GetTypingSessionTextAtIndexOrDefault(
            textTypingResult.TypingSessionTextIndex);

        if (typingSessionText == null)
        {
            throw new InvalidOperationException("Typing session text with this index does not exist in typing session.");
        }

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

        if (text == null)
        {
            throw new InvalidOperationException("Text with such ID does not exist.");
        }

        if (typingSessionText.Value != text.Value)
        {
            throw new InvalidOperationException("Typing session text value differs from the one from the text store. Corrupted state.");
        }

        // If this doesn't throw - validation succeeded.
        await _textTypingResultValidator.ValidateAsync(text.Value, textTypingResult)
        .ConfigureAwait(false);

        userSession.LogResult(textTypingResult);
        await _userSessionRepository.SaveAsync(userSession)
        .ConfigureAwait(false);
    }
예제 #2
0
    public async ValueTask <ActionResult <UserSessionDto> > GetById(string userSessionId)
    {
        var userSession = await _userSessionRepository.FindAsync(userSessionId);

        if (userSession == null)
        {
            return(NotFound());
        }

        // TODO: Validate that user session belongs to this user.

        return(Ok(new UserSessionDto
        {
            UserSessionId = userSessionId,
            TypingSessionId = userSession.TypingSessionId
        }));
    }
예제 #3
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));
    }