public async Task <IActionResult> AddAssignedQuestion(EditChallengeViewModel inputModel) { if (ModelState.IsValid) { // Translate the view model to our backend model var assignedQuestion = new ACMQ.AssignedQuestion { Answers = inputModel.QuestionToAdd.Answers .Select(p => new ACMQ.AssignedQuestion.AnswerList { AnswerParameters = p.AnswerParameters?.Select(a => new ACMQ.AssignedQuestion.AnswerParameterItem() { ErrorMessage = a.ErrorMessage, Key = a.Key, Value = a.Value ?? (inputModel.QuestionToAdd.QuestionType == "MultiChoice" ? "false" : "") }).ToList(), AssociatedQuestionId = p.AssociatedQuestionId, ResponseType = p.ResponseType } ).ToList(), QuestionType = inputModel.QuestionToAdd.QuestionType, AssociatedQuestionId = inputModel.QuestionToAdd.AssociatedQuestionId, Description = inputModel.QuestionToAdd.Description, Difficulty = inputModel.QuestionToAdd.Difficulty, Name = inputModel.QuestionToAdd.Name, QuestionId = string.IsNullOrWhiteSpace(inputModel.QuestionToAdd.Id) ? Guid.NewGuid().ToString() : inputModel.QuestionToAdd.Id, TargettedAzureService = inputModel.QuestionToAdd.TargettedAzureService, Text = inputModel.QuestionToAdd.Text, TextParameters = inputModel.QuestionToAdd.TextParameters?.ToDictionary(p => p.Key, p => p.Value) ?? new Dictionary <string, string>(), ChallengeId = inputModel.QuestionToAdd.ChallengeId, Uris = inputModel.QuestionToAdd.Uris? .Select(p => new ACMQ.AssignedQuestion.UriList { CallType = p.CallType, Id = p.Id, Uri = p.Uri, UriParameters = p.UriParameters?.ToDictionary(q => q.Key, q => q.Value) ?? new Dictionary <string, string>(), RequiresContributorAccess = p.RequiresContributorAccess } ).ToList(), Justification = inputModel.QuestionToAdd.Justification, UsefulLinks = inputModel.QuestionToAdd.UsefulLinks ?? new List <string>() }; List <ACMQ.QuestionLite> challengeQuestions = null; if (inputModel.ChallengeQuestions != null) { challengeQuestions = inputModel.ChallengeQuestions .Select(p => new ACMQ.QuestionLite { Description = p.Description, Difficulty = p.Difficulty, Id = p.Id, Index = p.Index, Name = p.Name, AssociatedQuestionId = p.AssociatedQuestionId, NextQuestionId = p.NextQuestionId }).ToList(); } else { challengeQuestions = new List <ACMQ.QuestionLite>(); } // Get the existing challenge details var challenge = new ACMT.ChallengeDetails() { Description = inputModel.Description, Id = inputModel.Id, Name = inputModel.Name, Questions = challengeQuestions, AzureServiceCategory = inputModel.AzureServiceCategory, WelcomeMessage = inputModel.WelcomeMessage, Duration = inputModel.Duration, PrereqLinks = inputModel.PrereqLinks }; // Check if this is an update to an existing challenge question if (challenge.Questions.Exists(p => p.Id == assignedQuestion.QuestionId)) { // We only need to update the assigned question, not the challenge var updateQuestionResult = await assignedQuestionProvider.AddItemAsync(assignedQuestion); if (!updateQuestionResult.Success) { return(StatusCode(500)); } } else { // Create a new Challenge Question var newChallengeQuestion = new ACMQ.QuestionLite { Name = assignedQuestion.Name, Description = assignedQuestion.Description, Difficulty = assignedQuestion.Difficulty, Id = assignedQuestion.QuestionId, AssociatedQuestionId = assignedQuestion.AssociatedQuestionId, Index = challenge.Questions.Count() }; // Assign the next question value of the last question in the challenge to this one if (challenge.Questions.Count > 0) { challenge.Questions[challenge.Questions.Count - 1].NextQuestionId = assignedQuestion.QuestionId; } challenge.Questions.Add(newChallengeQuestion); // Get the global parameters for the challenge var globalParamsResponse = await challengeParameterProvider.GetItemAsync(assignedQuestion.ChallengeId); var globalParams = globalParamsResponse.Item2; // Check if the parameter is global and it exists in the global parameters list // If yes, increment the count. If no, add it foreach (var parameter in assignedQuestion.TextParameters.ToList()) { if (parameter.Key.StartsWith("Global.")) { var globalParameter = globalParams?.Parameters?.Where(p => p.Key == parameter.Key.Replace("Global.", "")).FirstOrDefault(); if (globalParameter == null) { if (globalParams == null) { globalParams = new ACMP.GlobalChallengeParameters() { ChallengeId = assignedQuestion.ChallengeId, Parameters = new List <ACMP.GlobalChallengeParameters.ParameterDefinition>() }; } else if (globalParams.Parameters == null) { globalParams.Parameters = new List <ACMP.GlobalChallengeParameters.ParameterDefinition>(); } globalParams.Parameters.Add(new ACMP.GlobalChallengeParameters.ParameterDefinition { Key = parameter.Key.Replace("Global.", ""), Value = parameter.Value, AssignedToQuestion = 1 }); } else { globalParameter.AssignedToQuestion += 1; } } } await challengeParameterProvider.AddItemAsync(globalParams); var addQuestionResult = await assignedQuestionProvider.AddItemAsync(assignedQuestion); if (addQuestionResult.Success) { var updateChallengeResult = await challengeProvider.AddItemAsync(challenge); if (!updateChallengeResult.Success) { await assignedQuestionProvider.DeleteItemAsync(assignedQuestion.QuestionId); return(StatusCode(500)); } } } } return(RedirectToAction("Edit", new { challengeId = inputModel.QuestionToAdd.ChallengeId })); }
public async Task <IActionResult> StartChallenge(string challengeId, string questionId) { var user = await _userManager.GetUserAsync(User); var userChallengeResponse = await userChallengesProvider.GetItemAsync(user.Id); var challengeResponse = await challengesProvider.GetItemAsync(challengeId); var aggregateReponse = await aggregateProvider.GetItemAsync(challengeId); if (!userChallengeResponse.Item1.IsError) { // If the challenge is not locked, lock it since the first user has started it if (!challengeResponse.Item2.IsLocked) { challengeResponse.Item2.IsLocked = true; await challengesProvider.AddItemAsync(challengeResponse.Item2); } // If this is a new challenge, we first need to show the introduction var showIntroduction = false; // New tournament if (!userChallengeResponse.Item1.Success) { var userChallenge = new UserChallenges { Id = user.Id, Challenges = new List <UserChallengeItem>() }; userChallenge.Challenges .Add(new UserChallengeItem() { AccumulatedXP = 0, ChallengeId = challengeId, Completed = false, CurrentQuestion = questionId, StartTimeUTC = DateTime.Now.ToUniversalTime(), CurrentIndex = 0, NumOfQuestions = challengeResponse.Item2.Questions.Count() }); await userChallengesProvider.AddItemAsync(userChallenge); if (aggregateReponse.Item1.Success) { var agg = aggregateReponse.Item2 ?? new ACMA.Aggregate() { Id = challengeId, ChallengeUsers = new ACMA.ChallengeAggregateUsers() { Finished = 0, Started = 0 } }; agg.ChallengeUsers.Started += 1; await aggregateProvider.AddItemAsync(agg); } else { // Doesn't exist var agg = new ACMA.Aggregate() { Id = challengeId, ChallengeUsers = new ACMA.ChallengeAggregateUsers() { Finished = 0, Started = 0 } }; agg.ChallengeUsers.Started += 1; await aggregateProvider.AddItemAsync(agg); } showIntroduction = true; } else { // The user already has done some challenges // If this is new, then add the userChallenge and update the Aggregate if (!userChallengeResponse.Item2.Challenges.Any(p => p.ChallengeId == challengeId)) { userChallengeResponse.Item2.Challenges .Add(new UserChallengeItem() { AccumulatedXP = 0, ChallengeId = challengeId, Completed = false, CurrentQuestion = questionId, StartTimeUTC = DateTime.Now.ToUniversalTime(), CurrentIndex = 0, NumOfQuestions = challengeResponse.Item2.Questions.Count() }); await userChallengesProvider.AddItemAsync(userChallengeResponse.Item2); if (aggregateReponse.Item1.Success) { var agg = aggregateReponse.Item2 ?? new ACMA.Aggregate() { Id = challengeId, ChallengeUsers = new ACMA.ChallengeAggregateUsers() { Finished = 0, Started = 0 } }; agg.ChallengeUsers.Started += 1; await aggregateProvider.AddItemAsync(agg); } else { // Doesn't exist var agg = new ACMA.Aggregate() { Id = challengeId, ChallengeUsers = new ACMA.ChallengeAggregateUsers() { Finished = 0, Started = 0 } }; agg.ChallengeUsers.Started += 1; await aggregateProvider.AddItemAsync(agg); } showIntroduction = true; } else if (userChallengeResponse.Item2.Challenges.Where(p => p.ChallengeId == challengeId).FirstOrDefault()?.CurrentIndex == 0) { // If the user already registered for the challenge but never started it showIntroduction = true; } } if (showIntroduction) { return(RedirectToAction("Introduction", new { challengeId = challengeId, questionId = questionId })); } else { return(RedirectToAction("ShowQuestion", new { challengeId = challengeId, questionId = questionId })); } } return(StatusCode(500)); }