public async Task <IActionResult> Answer([FromRoute] CommonAPI_TestSectionIdDTO sectionIdDTO, [FromRoute] CommonAPI_TestQuestionIdDTO questionIdDTO, [FromBody] MemberAPI_CommonTestAnswerDTO answerDTO)
        {
            var(errorCode, response) = await _attemptService.MemberAPI_Answer(sectionIdDTO, questionIdDTO, answerDTO);

            return(this.ResultResponse(errorCode, response));
        }
        public static (bool, OperationErrorMessages, object) ApplyAnswer(Dictionary <string, AttemptsDB_SectionDTO> sections, string sectionId, string questionId, MemberAPI_CommonTestAnswerDTO testAnswerDTO)
        {
            if (!sections.ContainsKey(sectionId))
            {
                return(false, OperationErrorMessages.SectionNotFound, null);
            }

            var questions = sections[sectionId].Questions;

            if (!questions.ContainsKey(questionId))
            {
                return(false, OperationErrorMessages.QuestionNotFound, null);
            }

            var question = questions[questionId];

            if (question.Type == QuestionTypes.SingleChoice)
            {
                var selectedOption = testAnswerDTO.SelectedOption;
                if (selectedOption != null)
                {
                    var optionsContainer = BsonSerializer.Deserialize <AttemptsDB_ChoiceOptionsContainer>(question.Options);

                    if (selectedOption >= optionsContainer.Options.Length)
                    {
                        return(false, OperationErrorMessages.SelectedOptionOutOfRange, null);
                    }

                    for (var i = 0; i < optionsContainer.Options.Length; i++)
                    {
                        optionsContainer.Options[i].Chosen = i == selectedOption;
                    }

                    question.Options = optionsContainer.ToBsonDocument();
                }
            }
            else if (question.Type == QuestionTypes.MultipleChoice)
            {
                var selectedOptions = testAnswerDTO.SelectedOptions;
                if (selectedOptions != null)
                {
                    var optionsContainer = BsonSerializer.Deserialize <AttemptsDB_ChoiceOptionsContainer>(question.Options);
                    var optionsCount     = optionsContainer.Options.Length;

                    var uniques = new HashSet <int>();
                    for (var i = 0; i < selectedOptions.Length; i++)
                    {
                        if (selectedOptions[i] >= optionsCount)
                        {
                            return(false, OperationErrorMessages.SelectedOptionOutOfRange, null);
                        }

                        if (!uniques.Add(selectedOptions[i]))
                        {
                            return(false, OperationErrorMessages.NonUniqueOption, new CommonAPI_ErrorDTO {
                                ErrorSubject = selectedOptions[i]
                            });
                        }
                    }

                    for (var i = 0; i < optionsCount; i++)
                    {
                        optionsContainer.Options[i].Chosen = selectedOptions.Contains(i);
                    }

                    question.Options = optionsContainer.ToBsonDocument();
                }
            }
            else if (question.Type == QuestionTypes.Matching)
            {
                var leftSequence  = testAnswerDTO.LeftSequence;
                var rightSequence = testAnswerDTO.RightSequence;
                if (leftSequence != null && rightSequence != null)
                {
                    var optionsContainer = BsonSerializer.Deserialize <AttemptsDB_MatchingOptionsContainer>(question.Options);
                    var optionsCount     = optionsContainer.LeftSequence.Length;

                    if (leftSequence.Length != optionsCount)
                    {
                        return(false, OperationErrorMessages.WrongOptionsCount, new CommonAPI_ErrorDTO {
                            ErrorSubject = "left"
                        });
                    }

                    if (rightSequence.Length != optionsCount)
                    {
                        return(false, OperationErrorMessages.WrongOptionsCount, new CommonAPI_ErrorDTO {
                            ErrorSubject = "right"
                        });
                    }

                    var leftUniques  = new HashSet <int>();
                    var rightUniques = new HashSet <int>();
                    for (var i = 0; i < leftSequence.Length; i++)
                    {
                        if (leftSequence[i] >= optionsCount)
                        {
                            return(false, OperationErrorMessages.SelectedOptionOutOfRange, new CommonAPI_ErrorDTO {
                                ErrorSubject = new object[] { "left", leftSequence[i] }
                            });
                        }
                        if (rightSequence[i] >= optionsCount)
                        {
                            return(false, OperationErrorMessages.SelectedOptionOutOfRange, new CommonAPI_ErrorDTO {
                                ErrorSubject = new object[] { "right", rightSequence[i] }
                            });
                        }

                        if (!leftUniques.Add(leftSequence[i]))
                        {
                            return(false, OperationErrorMessages.NonUniqueOption, new CommonAPI_ErrorDTO {
                                ErrorSubject = new object[] { "left", leftSequence[i] }
                            });
                        }
                        if (!rightUniques.Add(rightSequence[i]))
                        {
                            return(false, OperationErrorMessages.NonUniqueOption, new CommonAPI_ErrorDTO {
                                ErrorSubject = new object[] { "right", rightSequence[i] }
                            });
                        }
                    }

                    var tempLeftSequence  = new AttemptsDB_PositionalOption[optionsCount];
                    var tempRightSequence = new AttemptsDB_PositionalOption[optionsCount];
                    for (var i = 0; i < optionsCount; i++)
                    {
                        tempLeftSequence[i]  = optionsContainer.LeftSequence[leftSequence[i]];
                        tempRightSequence[i] = optionsContainer.RightSequence[rightSequence[i]];
                    }
                    optionsContainer.LeftSequence  = tempLeftSequence;
                    optionsContainer.RightSequence = tempRightSequence;

                    question.Options = optionsContainer.ToBsonDocument();
                }
            }
            else if (question.Type == QuestionTypes.Sequence)
            {
                var sequence = testAnswerDTO.Sequence;
                if (sequence != null)
                {
                    var optionsContainer = BsonSerializer.Deserialize <AttemptsDB_SequenceOptionsContainer>(question.Options);
                    var optionsCount     = optionsContainer.Sequence.Length;

                    if (sequence.Length != optionsCount)
                    {
                        return(false, OperationErrorMessages.WrongOptionsCount, null);
                    }

                    var uniques = new HashSet <int>();
                    for (var i = 0; i < sequence.Length; i++)
                    {
                        if (sequence[i] >= optionsCount)
                        {
                            return(false, OperationErrorMessages.SelectedOptionOutOfRange, new CommonAPI_ErrorDTO {
                                ErrorSubject = sequence[i]
                            });
                        }

                        if (!uniques.Add(sequence[i]))
                        {
                            return(false, OperationErrorMessages.NonUniqueOption, new CommonAPI_ErrorDTO {
                                ErrorSubject = sequence[i]
                            });
                        }
                    }

                    for (var i = 0; i < optionsCount; i++)
                    {
                        optionsContainer.Sequence[i] = optionsContainer.Sequence[sequence[i]];
                    }

                    question.Options = optionsContainer.ToBsonDocument();
                }
            }
            else if (question.Type == QuestionTypes.FillIn)
            {
                var fills = testAnswerDTO.Fills;
                if (fills != null)
                {
                    var optionsContainer = BsonSerializer.Deserialize <AttemptsDB_FillInOptionsContainer>(question.Options);
                    var options          = optionsContainer.Options;
                    var blanksCount      = optionsContainer.Options
                                           .Where(option =>
                                                  option.IsBlank
                                                  ).ToArray()
                                           .Length;

                    if (fills.Length != blanksCount)
                    {
                        return(false, OperationErrorMessages.WrongOptionsCount, null);
                    }

                    var j = 0;
                    for (var i = 0; i < optionsContainer.Options.Length; i++)
                    {
                        if (optionsContainer.Options[i].IsBlank)
                        {
                            optionsContainer.Options[i].Text = fills[j];
                            j++;
                        }
                    }

                    question.Options = optionsContainer.ToBsonDocument();
                }
            }

            question.Touched    = true;
            question.BlurTime  += testAnswerDTO.BlurTimeAddition.Value;
            question.TotalTime += testAnswerDTO.TotalTimeAddition.Value;

            sections[sectionId].Questions[questionId] = question;

            return(true, OperationErrorMessages.NoError, sections);
        }