using System; using System.Collections.Generic; using System.Security.Claims; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using OnlineAssessment.Common; using OnlineAssessment.Data.EFCore; using OnlineAssessment.Domain.Models; using OnlineAssessment.Domain.ViewModels; namespace OnlineAssessment.V1.Controllers { [Authorize] [ApiVersion("1.0")] [Route("v{version:apiVersion}")] public class PracticeAttemptsController : BaseController { EFCorePracticeAttemptRepository _repository; string responseMessage = string.Empty; int institute_id; public PracticeAttemptsController(EFCorePracticeAttemptRepository repository) : base(repository) { _repository = repository; } #region PracticeAttempts /// /// Get all Practices /// /// /// /// /// [HttpGet("Batches/{batch_id}/LivePractices")] [ProducesResponseType(typeof(PracticeAttemptAllPracticePagedModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetLivePractices(int batch_id, [FromQuery] string module, [FromQuery] int module_id, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize) { IActionResult returnResponse; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); PracticeAttemptAllPracticePagedModel practiceListPaged = new PracticeAttemptAllPracticePagedModel(); if (pageNumber == null) pageNumber = 1; if (pageSize == null) pageSize = 20; dynamic theList = _repository.GetLivePracticesByModuleID(base.InstituteId, user_id, batch_id, module, module_id, sortBy, sortOrder); if(theList != null && theList is List) { if (pageNumber != null && pageSize != null) { PaginatedList pList = PaginatedList.CreateAsync(theList, (int)pageNumber, (int)pageSize); practiceListPaged.total_count = theList.Count; practiceListPaged.total_pages = pList.TotalPages; practiceListPaged.page_index = pList.PageIndex; practiceListPaged.next = pList.HasNextPage; practiceListPaged.previous = pList.HasPreviousPage; practiceListPaged.practices = pList; } returnResponse = Ok(ReturnResponse.GetSuccessStatus(practiceListPaged)); } else if (theList is int && theList == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else if (theList is int && theList == (int)Message.NoData) { responseMessage = _repository.GetMessageByCode(Message.NoData.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NoData, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// Get all Practices /// /// /// /// [HttpGet("Batches/{batch_id}/LiveAuthorPractices/{author_id}")] [ProducesResponseType(typeof(PracticeAttemptAllPracticePagedModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetLiveAuthorPractices(int batch_id, int author_id, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize) { IActionResult returnResponse; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); PracticeAttemptAllPracticePagedModel practiceListPaged = new PracticeAttemptAllPracticePagedModel(); if (pageNumber == null) pageNumber = 1; if (pageSize == null) pageSize = 10; dynamic theList = _repository.GetLivePracticesByAuthor(base.InstituteId, user_id, batch_id, author_id, sortBy, sortOrder); if(theList != null && theList is List) { if (pageNumber != null && pageSize != null) { PaginatedList pList = PaginatedList.CreateAsync(theList, (int)pageNumber, (int)pageSize); practiceListPaged.total_count = theList.Count; practiceListPaged.total_pages = pList.TotalPages; practiceListPaged.page_index = pList.PageIndex; practiceListPaged.next = pList.HasNextPage; practiceListPaged.previous = pList.HasPreviousPage; practiceListPaged.practices = pList; } returnResponse = Ok(ReturnResponse.GetSuccessStatus(practiceListPaged)); } else if (theList is int && theList == (int)Message.NoData) { responseMessage = _repository.GetMessageByCode(Message.NoData.ToString()); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.NoData, responseMessage)); } else if (theList is int && theList == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// Get recent attempted Practices /// /// /// /// /// [HttpGet("Batches/{batch_id}/RecentPractices")] [ProducesResponseType(typeof(PracticeAttemptsPagedModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetRecentPractices(int batch_id, [FromQuery] string sortBy, string sortOrder, [FromQuery] int? pageNumber, [FromQuery] int? pageSize) { IActionResult returnResponse; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); PracticeAttemptsPagedModel practiceListPaged = new PracticeAttemptsPagedModel(); if (pageNumber == null) pageNumber = 1; if (pageSize == null) pageSize = 10; if (sortBy == null) sortBy = "DATE"; if (sortOrder == null) sortOrder = "D"; dynamic theList = _repository.GetRecentPracticeAttempts(base.InstituteId, user_id, batch_id, sortBy, sortOrder); if(theList is List) { if (pageNumber != null && pageSize != null) { PaginatedList pList = PaginatedList.CreateAsync(theList, (int)pageNumber, (int)pageSize); practiceListPaged.total_count = theList.Count; practiceListPaged.total_pages = pList.TotalPages; practiceListPaged.page_index = pList.PageIndex; practiceListPaged.next = pList.HasNextPage; practiceListPaged.previous = pList.HasPreviousPage; practiceListPaged.practices = pList; } returnResponse = Ok(ReturnResponse.GetSuccessStatus(practiceListPaged)); } else if (theList is int && theList == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else if (theList is int && theList == (int)Message.NoData) { responseMessage = _repository.GetMessageByCode(Message.NoData.ToString()); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.NoData, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint will create a new attempt for the Practice. /// Error Conditions: Invalid Exam, Attempt limit Over, Unknown error /// /// /// /// [HttpPost("{language}/PracticeAttempts/{practice_id}/CreateAttempt")] [ProducesResponseType(typeof(PracticeAttemptAllQuestionsViewModel), 200)] [Authorize(Roles = "Student")] public IActionResult CreateNewPracticeAttempt(string language, int practice_id) { //Step1: Get Institute & User details IActionResult returnResponse = null; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); int language_id = _repository.GetLanguageIdByCode(language); if (language_id <= 0) { responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString(), Constant.PracticeAttempt); return BadRequest(ReturnResponse.GetFailureStatus((int)Message.InvalidInput, responseMessage)); } // Create an attaempt dynamic attempt = _repository.AddNewAttemptOfThePractice(base.InstituteId, user_id, language_id, practice_id); if (attempt is PracticeAttemptAllQuestionsViewModel) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(attempt)); } else if(attempt is int && attempt == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString(), Constant.PracticeAttempt); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else if(attempt is int && attempt == (int)Message.NoData) { responseMessage = _repository.GetMessageByCode(Message.NoData.ToString(), Constant.PracticeAttempt); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.NoData, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString(), Constant.PracticeAttempt); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint will return the details of the practice. /// Error Conditions: Invalid Practice, Unknown error /// /// /// /// [HttpGet("{language}/PracticeAttempts/{practice_id}")] [ProducesResponseType(typeof(PracticeDetailViewModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetPracticeDetails(string language, int practice_id) { //Step1: Get Institute & User details IActionResult returnResponse = null; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); int language_id = _repository.GetLanguageIdByCode(language); if (language_id <= 0) { responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString(), Constant.PracticeAttempt); return BadRequest(ReturnResponse.GetFailureStatus((int)Message.InvalidInput, responseMessage)); } //TBD: Get usergroup & user classes and check if the exam class belongs to user classes // Create an attaempt dynamic attempt = _repository.GetPracticeDetails(base.InstituteId, user_id, practice_id); if(attempt is PracticeDetailViewModel) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(attempt)); } else if (attempt is int && attempt == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString(), Constant.PracticeAttempt); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString(), Constant.PracticeAttempt); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// Attach Bookmark To Praactices /// /// /// [HttpPost("Batches/{batch_id}/PracticeAttempts/{practice_id}/Bookmark")] [ProducesResponseType(typeof(int), 200)] [Authorize(Roles = "Student")] public IActionResult AttachBookmarkToPractices(int batch_id, int practice_id, [FromBody] BookMarkStatus bookMarkStatus) { IActionResult returnResponse = null; string return_message = string.Empty; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); if (bookMarkStatus == null) { responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus(responseMessage)); } int recordsEffected = 0; if (bookMarkStatus.isBookmark == true) recordsEffected = _repository.AttachBookmarkToPractices(base.InstituteId, batch_id, user_id, practice_id, out return_message); else recordsEffected = _repository.DetachBookmarkFromPractices(base.InstituteId, batch_id, user_id, practice_id, out return_message); if(recordsEffected > 0) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message)); } else if (recordsEffected == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = Ok(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint returns all questions for an attempt. /// /// /// /// [HttpGet("{language}/Batches/{batch_id}/PracticeAttempts/{practice_id}/Revision")] [ProducesResponseType(typeof(PracticeAttemptAllQuestionsViewModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetPracticeAttemptRevision(string language, int batch_id, int practice_id) { //Step1: Get Institute & User details IActionResult returnResponse = null; institute_id = base.InstituteId; int user_id = int.Parse(Security.GetValueFromToken("UserId", HttpContext.User.Identity as ClaimsIdentity)); int role_id = int.Parse(Security.GetValueFromToken("RoleId", HttpContext.User.Identity as ClaimsIdentity)); int language_id = _repository.GetLanguageIdByCode(language); if (language_id <= 0) { responseMessage = _repository.GetMessageByCode(Message.InvalidInput.ToString(), Constant.PracticeAttempt); return BadRequest(ReturnResponse.GetFailureStatus((int)Message.InvalidInput, responseMessage)); } // Get an attaempt dynamic questions = _repository.GetPracticeAttemptPracticeQuestions(base.InstituteId, batch_id, user_id, language_id, practice_id); //TBD: if teacher get teacher classes and check if the exam class belongs to teacher classes if(questions is PracticeAttemptAllQuestionsViewModel) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(questions)); } if (questions is int && questions == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint returns attempted practice stats. /// /// /// [HttpGet("Batches/{batch_id}/Coverage")] [ProducesResponseType(typeof(PracticeAttemptsCoverageViewModel), 200)] [Authorize(Roles = "Student")] public IActionResult GetBatchPracticeCoverage(int batch_id) { //Step1: Get Institute & User details IActionResult returnResponse = null; institute_id = base.InstituteId; int user_id = int.Parse(Security.GetValueFromToken("UserId", HttpContext.User.Identity as ClaimsIdentity)); dynamic coverage = _repository.GetPracticeAttemptsCoverage(institute_id, batch_id, user_id); if(coverage is PracticeAttemptsCoverageViewModel) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(coverage)); } else if (coverage is int && coverage == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else if (coverage is int && coverage == (int)Message.NoData) { responseMessage = _repository.GetMessageByCode(Message.NoData.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NoData, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint saves the result of an attempt. /// /// /// /// [HttpPost("PracticeAttempts/{attempt_id}/End")] [ProducesResponseType(typeof(CorrectnessCount), 200)] [Authorize(Roles = "Student")] public IActionResult EndPracticeAttempt(int attempt_id, [FromBody] PracticeAttemptResultModel report) { //Step1: Get Institute & User details IActionResult returnResponse = null; institute_id = base.InstituteId; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); // Update answers dynamic cc = _repository.EndPractice(institute_id, user_id, attempt_id, report); if(cc is CorrectnessCount) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(cc)); } else if (cc is int && cc == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); returnResponse = BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } /// /// This endpoint raise bug in a question. /// /// /// /// [HttpPost("{language}/PracticeAttempts/{attempt_id}/Bug")] [ProducesResponseType(typeof(CorrectnessCount), 200)] [Authorize(Roles = "Student")] public IActionResult RaiseQuestionBug(int attempt_id, [FromBody] QuestionBugModel bugDetails) { //Step1: Get Institute & User details IActionResult returnResponse = null; string return_message = string.Empty; institute_id = base.InstituteId; int user_id = Security.GetIdFromJwtToken(UserClaim.UserId, HttpContext.User.Identity as ClaimsIdentity); // Update answers int bug = _repository.RaiseQuestionBug(institute_id, user_id, attempt_id, bugDetails.question_id, bugDetails.source, bugDetails.title, bugDetails.description, out return_message); if(bug > 0) { returnResponse = Ok(ReturnResponse.GetSuccessStatus(return_message)); } else if (bug == (int)Message.NotAllowedToResource) { responseMessage = _repository.GetMessageByCode(Message.NotAllowedToResource.ToString()); return BadRequest(ReturnResponse.GetFailureStatus((int)Message.NotAllowedToResource, responseMessage)); } else { responseMessage = _repository.GetMessageByCode(Message.Failure.ToString()); return BadRequest(ReturnResponse.GetFailureStatus((int)Message.Failure, responseMessage)); } return returnResponse; } #endregion } }