public async Task <IActionResult> GetAssignedQuestionAsync(string challengeId, string assignedQuestionId) { var result = await assignedQuestionProvider.GetItemAsync(assignedQuestionId); if (result.Item1.Success) { var question = new VM.AssignedQuestion() { Answers = result.Item2.Answers .Select(p => new VM.AssignedQuestion.AnswerList() { AnswerParameters = p.AnswerParameters == null ? new List <VM.AssignedQuestion.KVPair>() : p.AnswerParameters.Select(q => new VM.AssignedQuestion.KVPair() { Key = q.Key, Value = q.Value, ErrorMessage = q.ErrorMessage }).ToList(), AssociatedQuestionId = p.AssociatedQuestionId, ResponseType = p.ResponseType }).ToList(), AssociatedQuestionId = result.Item2.AssociatedQuestionId, QuestionType = result.Item2.QuestionType, Description = result.Item2.Description, Difficulty = result.Item2.Difficulty, Id = result.Item2.QuestionId, Name = result.Item2.Name, TargettedAzureService = result.Item2.TargettedAzureService, Text = result.Item2.Text, TextParameters = result.Item2.TextParameters.Select(p => new VM.AssignedQuestion.KVPair { Key = p.Key, Value = p.Value }).ToList(), ChallengeId = result.Item2.ChallengeId, Uris = result.Item2.Uris? .Select(p => new VM.AssignedQuestion.UriList { CallType = p.CallType, Id = p.Id, Uri = p.Uri, UriParameters = p.UriParameters.Select(q => new VM.AssignedQuestion.KVPair { Key = q.Key, Value = q.Value }).ToList(), RequiresContributorAccess = p.RequiresContributorAccess }).ToList(), Justification = result.Item2.Justification, UsefulLinks = result.Item2.UsefulLinks ?? new List <string>() }; return(Ok(question)); } else { return(StatusCode(500)); } }
public async Task <IActionResult> ShowQuestion(string challengeId, string questionId) { var model = new QuestionViewModel() { Choices = new List <(string Text, bool Value, bool Selected)>() }; var user = await _userManager.GetUserAsync(User); var userChallengeResponse = await userChallengesProvider.GetItemAsync(user.Id); // Get the challenge var challengeResponse = await challengesProvider.GetItemAsync(challengeId); // If the challenge is not registered for the user (never registered) if (!userChallengeResponse.Item1.Success) { return(RedirectToAction("Index")); } var userChallenge = userChallengeResponse.Item2.Challenges.Where(p => p.ChallengeId == challengeId).FirstOrDefault(); // If the user is not registered for this challenge if (userChallenge == null) { return(RedirectToAction("Index")); } else if (userChallenge.CurrentQuestion != questionId && challengeResponse.Item2.Questions.Where(p => p.Id == questionId).Select(p => p.Index).FirstOrDefault() > userChallenge.CurrentIndex) { // Redirect the user to the current question (don't allow skipping) return(RedirectToAction("ShowQuestion", new { challengeId = challengeId, questionId = userChallenge.CurrentQuestion })); } else if (userChallenge.CurrentIndex == 0) { var startTime = DateTime.Now.ToUniversalTime(); userChallenge.StartTimeUTC = startTime; // Before doing anything, if the user is on the first question, always reset their start time (in case we are in a timed Challenge) userChallengeResponse.Item2.Challenges[userChallengeResponse.Item2.Challenges.IndexOf(userChallenge)].StartTimeUTC = startTime; await userChallengesProvider.AddItemAsync(userChallengeResponse.Item2); } else if (challengeResponse.Item2.Duration > 0 && userChallenge.StartTimeUTC > userChallenge.StartTimeUTC.AddMinutes(challengeResponse.Item2.Duration)) { // If the user exceeded the time limit return(RedirectToAction("TimeLimitReached", new { challengeId = challengeId })); } // Get the associated question var assignedQuestionRespnose = await assignedQuestionProvider.GetItemAsync(questionId); // Get the global challenge parameters var globalChallengeParametersResponse = await parametersProvider.GetItemAsync(challengeId); // Get the profile parameters var profileParameters = mapper.Map <AzureChallenge.Models.Profile.UserProfile>(user).GetKeyValuePairs().ToDictionary(p => p.Key, p => p.Value); var parameters = new Dictionary <string, string>(); foreach (var gp in globalChallengeParametersResponse.Item2.Parameters) { parameters.Add($"Global_{gp.Key}", gp.Value); } parameters = parameters.Concat(profileParameters).ToDictionary(p => p.Key, p => p.Value); if (assignedQuestionRespnose.Item1.Success) { // Find the question id var question = assignedQuestionRespnose.Item2; if (question == null) { return(StatusCode(500)); } parameters = parameters.Concat(question.TextParameters.Where(p => !p.Key.StartsWith("Profile.") && !p.Key.StartsWith("Global.")).ToDictionary(p => p.Key, p => p.Value == "null" ? "" : p.Value)).ToDictionary(p => p.Key, p => p.Value); var challengeQuestion = challengeResponse.Item2.Questions.Where(q => q.Id == questionId).FirstOrDefault(); var previousChallengeQuestion = challengeResponse.Item2.Questions.Where(q => q.NextQuestionId == questionId).FirstOrDefault(); model.QuestionType = question.QuestionType; model.Difficulty = question.Difficulty; model.QuestionIndex = challengeQuestion.Index; model.ThisQuestionDone = userChallenge.CurrentIndex > challengeQuestion.Index; model.HelpfulLinks = question.UsefulLinks; model.Justification = question.Justification; model.PreviousQuestionId = previousChallengeQuestion?.Id; model.NextQuestionId = challengeQuestion.NextQuestionId; model.QuestionId = questionId; model.QuestionText = SmartFormat.Smart.Format(question.Text.Replace("{Global.", "{Global_").Replace("{Profile.", "{Profile_"), parameters); model.QuestionName = challengeQuestion.Name; model.TournamentName = challengeResponse.Item2.Name; model.ChallengeId = challengeId; model.TimeLeftInSeconds = challengeResponse.Item2.Duration == 0 ? 0 : challengeResponse.Item2.Duration * 60 - (int)((DateTime.Now.ToUniversalTime() - userChallenge.StartTimeUTC).TotalSeconds); if (question.QuestionType == "MultiChoice") { model.Choices = question.Answers[0].AnswerParameters.Select(a => (a.Key, bool.Parse(a.Value), false)).ToList(); } if (question.Uris != null && question.Uris.Any(u => u.RequiresContributorAccess)) { model.ShowWarning = true; model.WarningMessage = "This question requires that the Service Principal you have created has Contributor access to the below Resource(s)."; } } else { return(StatusCode(404)); } return(View(model)); }