public async Task <InGameQuote?> GetQuoteForUserAsync(int userId, bool withMultipleChoices = true) { InGameQuote?gameQuote = null; var quotesWithAuthorIds = await _quotesRepo.GetIdsAndAuthorsForUserAsync(userId, new DateTime(DateTime.Now.Ticks - _maxedAllowedIntervalForQuote)); if (quotesWithAuthorIds.Count == 0) { return(gameQuote); } var authorNames = await _authorsRepo.GetAuthorsWithNames(); var random = new Random(); gameQuote = new InGameQuote { Id = quotesWithAuthorIds.ElementAt(random.Next(0, quotesWithAuthorIds.Count)).Key }; await AddRandomAnswers(gameQuote); gameQuote.Answers.Shuffle(); return(gameQuote); async Task AddRandomAnswers(InGameQuote quote) { var dbQuote = withMultipleChoices ? await _quotesRepo.GetDetailedAsync(quote.Id) : await _quotesRepo.GetAsync(quote.Id); quote.Text = dbQuote.Text; if (!withMultipleChoices) { var ans = new InGameAnswer(); (ans.AuthorId, ans.AuthorName) = (random.Next(0, 2) == 1 ? (quotesWithAuthorIds[quote.Id], authorNames[quotesWithAuthorIds[quote.Id]]) : PickAnyAuthorExcept(quotesWithAuthorIds[quote.Id])); quote.Answers.Add(ans); } else { quote.Answers.AddRange(dbQuote.QuoteAnswers.ToInGameAnswers()); var authorIds = quote.Answers.Select(ans => ans.AuthorId).ToList(); //todo it may loop forever //if this question has not multiple answers while (quote.AnswersCount != 3) { var ans = new InGameAnswer(); (ans.AuthorId, ans.AuthorName) = PickAnyAuthorExcept(authorIds.ToArray()); authorIds.Add(ans.AuthorId); quote.Answers.Add(ans); } } } (int, string) PickAnyAuthorExcept(params int[] authorIds) { int authId; do { authId = authorNames.ElementAt(random.Next(0, authorNames.Count)).Key; } while (authorIds.Contains(authId)); return(authId, authorNames[authId]);