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); }
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 })); }
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)); }