From 8ea18f10966ed5940c17d65f9a385896e38e6b92 Mon Sep 17 00:00:00 2001 From: Nikolai Papin Date: Sat, 20 Sep 2025 22:42:33 +0300 Subject: [PATCH] chore: removed everything related to instructions --- Controllers/InstructionController.cs | 166 ---------- Controllers/InstructionTestController.cs | 278 ----------------- Database/ApplicationContext.cs | 18 -- Database/Repositories/UnitOfWork.cs | 81 ----- .../Instruction/CategoryNotFoundException.cs | 25 -- .../Instruction/InstructionAccessException.cs | 24 -- .../InstructionCreationException.cs | 24 -- .../InstructionDeletionException.cs | 25 -- .../InstructionNotFoundException.cs | 25 -- .../Instruction/InstructionUpdateException.cs | 25 -- .../InstructionTestConflictException.cs | 26 -- .../InstructionTestCreationException.cs | 26 -- .../InstructionTestDeletionException.cs | 25 -- .../InstructionTestNotFoundException.cs | 27 -- .../InstructionTestSubmissionException.cs | 27 -- .../InstructionTestUpdateException.cs | 0 Extensions/DependencyInjectionExtensions.cs | 4 - ...ckend.csproj => GamificationService.csproj | 0 Mapper/MappingProfile.cs | 118 ------- Models/DTO/InstructionCategoryCreateDTO.cs | 14 - Models/DTO/InstructionCategoryDTO.cs | 10 - Models/DTO/InstructionCreateDTO.cs | 38 --- Models/DTO/InstructionDTO.cs | 21 -- Models/DTO/InstructionParagraphCreateDTO.cs | 25 -- Models/DTO/InstructionParagraphDTO.cs | 21 -- Models/DTO/InstructionTestCreateDTO.cs | 20 -- Models/DTO/InstructionTestDTO.cs | 23 -- .../DTO/InstructionTestQuestionCreateDTO.cs | 26 -- Models/DTO/InstructionTestQuestionDTO.cs | 25 -- Models/DTO/InstructionTestResultDTO.cs | 12 - Models/DTO/InstructionTestSubmissionDTO.cs | 12 - Models/Database/Instruction.cs | 29 -- Models/Database/InstructionCategory.cs | 13 - Models/Database/InstructionParagraph.cs | 21 -- Models/Database/InstructionTest.cs | 23 -- Models/Database/InstructionTestQuestion.cs | 26 -- Models/Database/InstructionTestResult.cs | 20 -- .../CreateInstructionTestRequest.cs | 6 - .../CreateInstructionTestResponse.cs | 6 - .../UpdateInstructionTestRequest.cs | 6 - .../UpdateInstructionTestResponse.cs | 6 - .../Instructions/CreateInstructionRequest.cs | 37 --- .../Instructions/CreateInstructionResponse.cs | 6 - .../Instructions/UpdateInstructionRequest.cs | 40 --- .../Instructions/UpdateInstructionResponse.cs | 6 - Program.cs | 6 - .../IInstructionTestsService.cs | 22 -- .../InstructionTestsService.cs | 294 ------------------ Services/Instructions/IInstructionService.cs | 21 -- Services/Instructions/InstructionService.cs | 174 ----------- 50 files changed, 1953 deletions(-) delete mode 100644 Controllers/InstructionController.cs delete mode 100644 Controllers/InstructionTestController.cs delete mode 100644 Exceptions/Services/Instruction/CategoryNotFoundException.cs delete mode 100644 Exceptions/Services/Instruction/InstructionAccessException.cs delete mode 100644 Exceptions/Services/Instruction/InstructionCreationException.cs delete mode 100644 Exceptions/Services/Instruction/InstructionDeletionException.cs delete mode 100644 Exceptions/Services/Instruction/InstructionNotFoundException.cs delete mode 100644 Exceptions/Services/Instruction/InstructionUpdateException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestConflictException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestCreationException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestDeletionException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestNotFoundException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestSubmissionException.cs delete mode 100644 Exceptions/Services/InstructionTest/InstructionTestUpdateException.cs rename MDSBackend.csproj => GamificationService.csproj (100%) delete mode 100644 Models/DTO/InstructionCategoryCreateDTO.cs delete mode 100644 Models/DTO/InstructionCategoryDTO.cs delete mode 100644 Models/DTO/InstructionCreateDTO.cs delete mode 100644 Models/DTO/InstructionDTO.cs delete mode 100644 Models/DTO/InstructionParagraphCreateDTO.cs delete mode 100644 Models/DTO/InstructionParagraphDTO.cs delete mode 100644 Models/DTO/InstructionTestCreateDTO.cs delete mode 100644 Models/DTO/InstructionTestDTO.cs delete mode 100644 Models/DTO/InstructionTestQuestionCreateDTO.cs delete mode 100644 Models/DTO/InstructionTestQuestionDTO.cs delete mode 100644 Models/DTO/InstructionTestResultDTO.cs delete mode 100644 Models/DTO/InstructionTestSubmissionDTO.cs delete mode 100644 Models/Database/Instruction.cs delete mode 100644 Models/Database/InstructionCategory.cs delete mode 100644 Models/Database/InstructionParagraph.cs delete mode 100644 Models/Database/InstructionTest.cs delete mode 100644 Models/Database/InstructionTestQuestion.cs delete mode 100644 Models/Database/InstructionTestResult.cs delete mode 100644 Models/Messages/InstructionTests/CreateInstructionTestRequest.cs delete mode 100644 Models/Messages/InstructionTests/CreateInstructionTestResponse.cs delete mode 100644 Models/Messages/InstructionTests/UpdateInstructionTestRequest.cs delete mode 100644 Models/Messages/InstructionTests/UpdateInstructionTestResponse.cs delete mode 100644 Models/Messages/Instructions/CreateInstructionRequest.cs delete mode 100644 Models/Messages/Instructions/CreateInstructionResponse.cs delete mode 100644 Models/Messages/Instructions/UpdateInstructionRequest.cs delete mode 100644 Models/Messages/Instructions/UpdateInstructionResponse.cs delete mode 100644 Services/InstructionTests/IInstructionTestsService.cs delete mode 100644 Services/InstructionTests/InstructionTestsService.cs delete mode 100644 Services/Instructions/IInstructionService.cs delete mode 100644 Services/Instructions/InstructionService.cs diff --git a/Controllers/InstructionController.cs b/Controllers/InstructionController.cs deleted file mode 100644 index c3fa8dc..0000000 --- a/Controllers/InstructionController.cs +++ /dev/null @@ -1,166 +0,0 @@ -using GamificationService.Exceptions.Services.Instruction; -using GamificationService.Models.Database; -using GamificationService.Models.DTO; -using GamificationService.Models.Messages.Instructions; -using GamificationService.Services.Instructions; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; - -namespace GamificationService.Controllers; - -[ApiController] -[Route("api/[controller]")] -[Authorize(Policy = "User")] -public class InstructionController : ControllerBase -{ - private readonly IInstructionService _instructionService; - private readonly UserManager _userManager; - private readonly ILogger _logger; - - public InstructionController(IInstructionService instructionService, UserManager userManager, ILogger logger) - { - _instructionService = instructionService; - _userManager = userManager; - _logger = logger; - } - - /// - /// Create a new instruction. - /// - /// The instruction model. - /// which was created - /// Returns the created instruction - [HttpPost] - [Authorize(Policy = "Admin")] - public async Task CreateInstruction([FromBody] CreateInstructionRequest model) - { - var instruction = await _instructionService.CreateInstruction(model); - return Ok(instruction); - } - - /// - /// Update an existing instruction. - /// - /// The instruction model. Id must match the object which is being updated. - /// - /// - /// If the instruction is not found - [HttpPut] - [Authorize(Policy = "Admin")] - public async Task UpdateInstruction([FromBody] UpdateInstructionRequest model) - { - var instruction = await _instructionService.UpdateInstructionById(model); - return Ok(instruction); - } - - /// - /// Delete an existing instruction. - /// - /// The ID of the instruction to delete. - /// - /// - /// If the instruction is not found - [HttpDelete] - [Authorize(Policy = "Admin")] - public async Task DeleteInstruction(long id) - { - try - { - return Ok(await _instructionService.DeleteInstructionById(id)); - } - catch (InstructionNotFoundException) - { - return NotFound(); - } - } - - /// - /// Retrieve all instructions for the authenticated user. - /// - /// A list of for the user. - /// Returns the list of all instructions - [HttpGet("all")] - public async Task GetAllInstructions() - { - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - return Ok(_instructionService.GetAllInstructions(userId)); - } - - /// - /// Retrieve all completed instructions for the authenticated user. - /// - /// A list of that are completed for the user. - /// Returns the list of completed instructions - [HttpGet("completed")] - public async Task GetCompletedInstructions() - { - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - return Ok(_instructionService.GetCompletedInstructions(userId)); - } - - /// - /// Retrieve all unfinished instructions for the authenticated user. - /// - /// A list of that are unfinished for the user. - /// Returns the list of unfinished instructions - [HttpGet("unfinished")] - public async Task GetUnfinishedInstructions() - { - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - return Ok(_instructionService.GetUnfinishedInstructions(userId)); - } - - /// - /// Retrieve instructions by category ID for the authenticated user. - /// - /// The ID of the category to filter instructions. - /// A list of for the specified category. - /// Returns the list of instructions for the specified category - /// If the category is not found - [HttpGet("category/{id}")] - public async Task GetInstructionsByCategoryId(long id) - { - try - { - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - return Ok(_instructionService.GetInstructionsByCategoryId(userId, id)); - } - catch (CategoryNotFoundException) - { - return NotFound(); - } - } - - /// - /// Retrieve a specific instruction by its ID for the authenticated user. - /// - /// The ID of the instruction to retrieve. - /// for the specified instruction. - /// Returns the instruction with the specified ID - /// If the instruction is not found - [HttpGet("{id}")] - public async Task GetInstructionById(long id) - { - try - { - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - return Ok(_instructionService.GetInstructionById(userId, id)); - } - catch(InstructionNotFoundException) - { - return NotFound(); - } - } -} - diff --git a/Controllers/InstructionTestController.cs b/Controllers/InstructionTestController.cs deleted file mode 100644 index 38123a4..0000000 --- a/Controllers/InstructionTestController.cs +++ /dev/null @@ -1,278 +0,0 @@ -using AutoMapper; -using GamificationService.Exceptions.Services.Instruction; -using GamificationService.Exceptions.Services.InstructionTest; -using GamificationService.Models.BasicResponses; -using GamificationService.Models.Database; -using GamificationService.Models.DTO; -using GamificationService.Services.InstructionTests; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; - -namespace GamificationService.Controllers; - -[ApiController] -[Route("api/[controller]")] -[Authorize(Policy = "User")] -public class InstructionTestController : ControllerBase -{ - private readonly IInstructionTestsService _instructionTestsService; - private readonly UserManager _userManager; - private readonly ILogger _logger; - private readonly IMapper _mapper; - - public InstructionTestController(IInstructionTestsService instructionTestsService, UserManager userManager, ILogger logger, IMapper mapper) - { - _instructionTestsService = instructionTestsService; - _userManager = userManager; - _logger = logger; - _mapper = mapper; - } - - /// - /// Gets an instruction test by its ID. - /// - /// The ID of the instruction test. - /// An containing the instruction test DTO if found, or a 404 Not Found if not found. - /// Returns the instruction test DTO - /// If the instruction test is not found - [HttpGet("{id}")] - public IActionResult GetInstructionTestById(long id) - { - // TODO: verify admin access / user ownership - try - { - var instructionTest = _instructionTestsService.GetInstructionTestById(id); - return Ok(_mapper.Map(instructionTest)); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Gets an instruction test by its instruction ID. - /// - /// The ID of the instruction. - /// An containing the instruction test DTO if found, or a 404 Not Found if not found. - /// Returns the instruction test DTO - /// If the instruction is not found - [HttpGet("instruction/{id}")] - public IActionResult GetInstructionTestsByInstructionId(long id) - { - // TODO: verify admin access / user ownership - try - { - var instructionTest = _instructionTestsService.GetInstructionTestsByInstructionId(id); - return Ok(_mapper.Map(instructionTest)); - } - catch (InstructionTestNotFoundException) - { - return Ok(new List()); - } - catch (InstructionNotFoundException) - { - return NotFound(new BasicResponse() - { - Code = 404, - Message = "Instruction not found" - }); - } - } - - /// - /// Gets all instruction test questions by instruction test ID. - /// - /// The ID of the instruction test. - /// A list of containing the instruction test questions if found, or a 404 Not Found if not found. - /// Returns the instruction test questions - /// If the instruction test questions are not found - [HttpGet("{instructionTestId}/questions")] - public IActionResult GetInstructionTestQuestionsByInstructionTestId(long instructionTestId) - { - // TODO: verify admin access / user ownership - try - { - var instructionTestQuestions = _instructionTestsService.GetInstructionTestQuestionsByInstructionTestId(instructionTestId); - return Ok(instructionTestQuestions); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Gets all instruction test results for authorized user by instruction ID. - /// - /// The ID of the instruction. - /// A list of containing the instruction test results if found, or a 404 Not Found if not found. - /// Returns the instruction test results - /// If the instruction test results are not found - [HttpGet("/{instructionTestId}/results")] - public async Task GetUserInstructionTestResultsByInstructionTestId(long instructionTestId) - { - // TODO: verify user ownership - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - try - { - var instructionTestResults = _instructionTestsService.GetUserInstructionTestResultsByInstructionTestId(userId, instructionTestId); - return Ok(instructionTestResults); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Gets all instruction test results for a specific user by instruction test ID (admin access). - /// - /// The ID of the user whose results are being requested. - /// The ID of the instruction. - /// A list of containing the instruction test results if found, or a 404 Not Found if not found. - /// Returns the instruction test results - /// If the instruction test results are not found - /// If the user is not an admin - [HttpGet("{instructionTestId}/user/{userId}/results")] - [Authorize(Roles = "Admin")] - public IActionResult GetInstructionTestResultsForUserByInstructionTestId(long userId, long instructionTestId) - { - try - { - var instructionTestResults = _instructionTestsService.GetUserInstructionTestResultsByInstructionTestId(userId, instructionTestId); - return Ok(instructionTestResults); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Gets all instruction test results for a user by user ID. - /// - /// The ID of the user. - /// A list of containing the instruction test results if found, or a 404 Not Found if not found. - /// Returns the instruction test results - /// If the instruction test results are not found - [HttpGet("user/{id}/results")] - public IActionResult GetInstructionTestResultsByUserId(long id) - { - // TODO: verify admin access / user ownership - try - { - var instructionTestResults = _instructionTestsService.GetInstructionTestResultsByUserId(id); - return Ok(instructionTestResults); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Gets all completed instruction test results for a user by user ID. - /// - /// The ID of the user. - /// A list of containing the instruction test results if found, or a 404 Not Found if not found. - /// Returns the instruction test results - /// If the instruction test results are not found - [HttpGet("user/{id}/completed")] - public IActionResult GetCompletedInstructionTestsByUserId(long id) - { - // TODO: verify admin access / user ownership - try - { - var instructionTestResults = _instructionTestsService.GetCompletedInstructionTestsByUserId(id); - return Ok(instructionTestResults); - } - catch (InstructionTestNotFoundException) - { - return NotFound(); - } - } - - /// - /// Creates a new instruction test. - /// - /// The instruction test model. - /// A containing the created instruction test if successful, or a 500 Internal Server Error if not successful. - /// Returns the created instruction test - [HttpPost] - public async Task CreateInstructionTest([FromBody] InstructionTestCreateDTO model) - { - try - { - var instructionTest = await _instructionTestsService.CreateInstructionTest(model); - return Ok(instructionTest); - } - catch (Exception) - { - return StatusCode(500, "Failed to create instruction test"); - } - } - - /// - /// Updates an existing instruction test. - /// - /// The instruction test model. - /// A containing the updated instruction test if successful, or a 500 Internal Server Error if not successful. - /// Returns the updated instruction test - [HttpPut] - [Authorize(Policy = "Admin")] - public async Task UpdateInstructionTest([FromBody] InstructionTestCreateDTO model) - { - try - { - var instructionTest = await _instructionTestsService.UpdateInstructionTest(model); - return Ok(instructionTest); - } - catch (Exception) - { - return StatusCode(500, "Failed to update instruction test"); - } - } - - /// - /// Deletes an existing instruction test. - /// - /// The ID of the instruction test to delete. - /// A - /// Returns the deletion status. - [HttpDelete("{id}")] - [Authorize(Policy = "Admin")] - public async Task DeleteInstructionTest(long id) - { - try - { - await _instructionTestsService.DeleteInstructionTestByIdAsync(id); - return Ok(); - } - catch (Exception) - { - return StatusCode(500, "Failed to delete instruction test"); - } - } - - [HttpPost("submit")] - public async Task SubmitInstructionTest([FromBody] InstructionTestSubmissionDTO model) - { - // TODO: verify user access - string username = User.Claims.First(c => c.Type == "username").Value; - long userId = (await _userManager.FindByNameAsync(username))!.Id; - - try - { - await _instructionTestsService.SubmitInstructionTestAsync(userId, model); - return Ok(); - } - catch (Exception) - { - return StatusCode(500, "Failed to submit instruction test"); - } - } -} diff --git a/Database/ApplicationContext.cs b/Database/ApplicationContext.cs index f87e48b..c49d4d7 100755 --- a/Database/ApplicationContext.cs +++ b/Database/ApplicationContext.cs @@ -18,12 +18,6 @@ public class ApplicationContext : IdentityDbContext UserRoles { get; set; } public DbSet RoleRights { get; set; } public DbSet UserProfiles { get; set; } - public DbSet Instructions { get; set; } - public DbSet InstructionCategories { get; set; } - public DbSet InstructionParagraphs { get; set; } - public DbSet InstructionTests { get; set; } - public DbSet InstructionTestQuestions { get; set; } - public DbSet InstructionTestResults { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -34,17 +28,5 @@ public class ApplicationContext : IdentityDbContext() .HasKey(rr => new { rr.RoleId, rr.RightId }); - - modelBuilder.Entity() - .HasMany(itq => itq.Questions); - - modelBuilder.Entity() - .HasOne(itr => itr.InstructionTest); - - modelBuilder.Entity() - .HasOne(i => i.Category); - - modelBuilder.Entity() - .HasMany(i => i.Paragraphs); } } diff --git a/Database/Repositories/UnitOfWork.cs b/Database/Repositories/UnitOfWork.cs index eeee6a4..be6e308 100755 --- a/Database/Repositories/UnitOfWork.cs +++ b/Database/Repositories/UnitOfWork.cs @@ -14,12 +14,6 @@ public class UnitOfWork : IDisposable private GenericRepository _refreshTokenRepository; private GenericRepository _roleRightRepository; private GenericRepository _userRoleRepository; - private GenericRepository _instructionRepository; - private GenericRepository _instructionParagraphRepository; - private GenericRepository _instructionCategoryRepository; - private GenericRepository _instructionTestRepository; - private GenericRepository _instructionTestQuestionRepository; - private GenericRepository _instructionTestResultRepository; #endregion @@ -105,83 +99,8 @@ public class UnitOfWork : IDisposable return _userRoleRepository; } } - - public GenericRepository InstructionRepository - { - get - { - if (this._instructionRepository == null) - { - this._instructionRepository = new GenericRepository(_context); - } - return _instructionRepository; - } - } - - public GenericRepository InstructionParagraphRepository - { - get - { - if (this._instructionParagraphRepository == null) - { - this._instructionParagraphRepository = new GenericRepository(_context); - } - return _instructionParagraphRepository; - } - } - - public GenericRepository InstructionCategoryRepository - { - get - { - if (this._instructionCategoryRepository == null) - { - this._instructionCategoryRepository = new GenericRepository(_context); - } - return _instructionCategoryRepository; - } - } - - public GenericRepository InstructionTestRepository - { - get - { - if (this._instructionTestRepository == null) - { - this._instructionTestRepository = new GenericRepository(_context); - } - return _instructionTestRepository; - } - } - - public GenericRepository InstructionTestQuestionRepository - { - get - { - if (this._instructionTestQuestionRepository == null) - { - this._instructionTestQuestionRepository = new GenericRepository(_context); - } - return _instructionTestQuestionRepository; - } - } - - public GenericRepository InstructionTestResultRepository - { - get - { - if (this._instructionTestResultRepository == null) - { - this._instructionTestResultRepository = new GenericRepository(_context); - } - return _instructionTestResultRepository; - } - } #endregion - - - public bool Save() { diff --git a/Exceptions/Services/Instruction/CategoryNotFoundException.cs b/Exceptions/Services/Instruction/CategoryNotFoundException.cs deleted file mode 100644 index 343e5f4..0000000 --- a/Exceptions/Services/Instruction/CategoryNotFoundException.cs +++ /dev/null @@ -1,25 +0,0 @@ - -namespace GamificationService.Exceptions.Services.Instruction; - -public class CategoryNotFoundException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public CategoryNotFoundException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public CategoryNotFoundException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public CategoryNotFoundException(string message, Exception innerException) : base(message, innerException) { } -} - - diff --git a/Exceptions/Services/Instruction/InstructionAccessException.cs b/Exceptions/Services/Instruction/InstructionAccessException.cs deleted file mode 100644 index 52ba9c5..0000000 --- a/Exceptions/Services/Instruction/InstructionAccessException.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace GamificationService.Exceptions.Services.Instruction; - -public class InstructionAccessException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionAccessException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionAccessException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionAccessException(string message, Exception innerException) : base(message, innerException) { } -} - - diff --git a/Exceptions/Services/Instruction/InstructionCreationException.cs b/Exceptions/Services/Instruction/InstructionCreationException.cs deleted file mode 100644 index a577386..0000000 --- a/Exceptions/Services/Instruction/InstructionCreationException.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace GamificationService.Exceptions.Services.Instruction; - -public class InstructionCreationException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionCreationException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionCreationException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionCreationException(string message, Exception innerException) : base(message, innerException) { } -} - - diff --git a/Exceptions/Services/Instruction/InstructionDeletionException.cs b/Exceptions/Services/Instruction/InstructionDeletionException.cs deleted file mode 100644 index ee54a05..0000000 --- a/Exceptions/Services/Instruction/InstructionDeletionException.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace GamificationService.Exceptions.Services.Instruction; - -public class InstructionDeletionException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionDeletionException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionDeletionException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionDeletionException(string message, Exception innerException) : base(message, innerException) { } -} - - - diff --git a/Exceptions/Services/Instruction/InstructionNotFoundException.cs b/Exceptions/Services/Instruction/InstructionNotFoundException.cs deleted file mode 100644 index d035514..0000000 --- a/Exceptions/Services/Instruction/InstructionNotFoundException.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace GamificationService.Exceptions.Services.Instruction; - -public class InstructionNotFoundException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionNotFoundException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionNotFoundException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionNotFoundException(string message, Exception innerException) : base(message, innerException) { } -} - - - diff --git a/Exceptions/Services/Instruction/InstructionUpdateException.cs b/Exceptions/Services/Instruction/InstructionUpdateException.cs deleted file mode 100644 index f68552e..0000000 --- a/Exceptions/Services/Instruction/InstructionUpdateException.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace GamificationService.Exceptions.Services.Instruction; - -public class InstructionUpdateException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionUpdateException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionUpdateException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionUpdateException(string message, Exception innerException) : base(message, innerException) { } -} - - - diff --git a/Exceptions/Services/InstructionTest/InstructionTestConflictException.cs b/Exceptions/Services/InstructionTest/InstructionTestConflictException.cs deleted file mode 100644 index 711451d..0000000 --- a/Exceptions/Services/InstructionTest/InstructionTestConflictException.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace GamificationService.Exceptions.Services.InstructionTest; - -/// -/// Represents an exception that occurs when there is a conflict in instruction test operations. -/// -public class InstructionTestConflictException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionTestConflictException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionTestConflictException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionTestConflictException(string message, Exception innerException) : base(message, innerException) { } -} - diff --git a/Exceptions/Services/InstructionTest/InstructionTestCreationException.cs b/Exceptions/Services/InstructionTest/InstructionTestCreationException.cs deleted file mode 100644 index 8d78560..0000000 --- a/Exceptions/Services/InstructionTest/InstructionTestCreationException.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace GamificationService.Exceptions.Services.InstructionTest; - -/// -/// Represents an exception that occurs during the creation of an instruction test. -/// -public class InstructionTestCreationException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionTestCreationException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionTestCreationException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionTestCreationException(string message, Exception innerException) : base(message, innerException) { } -} - diff --git a/Exceptions/Services/InstructionTest/InstructionTestDeletionException.cs b/Exceptions/Services/InstructionTest/InstructionTestDeletionException.cs deleted file mode 100644 index bb7f6bf..0000000 --- a/Exceptions/Services/InstructionTest/InstructionTestDeletionException.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace GamificationService.Exceptions.Services.InstructionTest; - -/// -/// Represents an exception that occurs during the deletion of an instruction test. -/// -public class InstructionTestDeletionException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionTestDeletionException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public InstructionTestDeletionException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionTestDeletionException(string message, Exception innerException) : base(message, innerException) { } -} diff --git a/Exceptions/Services/InstructionTest/InstructionTestNotFoundException.cs b/Exceptions/Services/InstructionTest/InstructionTestNotFoundException.cs deleted file mode 100644 index b436799..0000000 --- a/Exceptions/Services/InstructionTest/InstructionTestNotFoundException.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace GamificationService.Exceptions.Services.InstructionTest; - -/// -/// Represents an exception that occurs when an instruction test is not found. -/// -public class InstructionTestNotFoundException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionTestNotFoundException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - - /// The message that describes the error. - public InstructionTestNotFoundException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionTestNotFoundException(string message, Exception innerException) : base(message, innerException) { } -} - diff --git a/Exceptions/Services/InstructionTest/InstructionTestSubmissionException.cs b/Exceptions/Services/InstructionTest/InstructionTestSubmissionException.cs deleted file mode 100644 index fb2c90d..0000000 --- a/Exceptions/Services/InstructionTest/InstructionTestSubmissionException.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace GamificationService.Exceptions.Services.InstructionTest; - -/// -/// Represents an exception that occurs when an instruction test submission is failed. -/// -public class InstructionTestSubmissionException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public InstructionTestSubmissionException() : base() { } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - - /// The message that describes the error. - public InstructionTestSubmissionException(string message) : base(message) { } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InstructionTestSubmissionException(string message, Exception innerException) : base(message, innerException) { } -} - diff --git a/Exceptions/Services/InstructionTest/InstructionTestUpdateException.cs b/Exceptions/Services/InstructionTest/InstructionTestUpdateException.cs deleted file mode 100644 index e69de29..0000000 diff --git a/Extensions/DependencyInjectionExtensions.cs b/Extensions/DependencyInjectionExtensions.cs index 11532aa..f9bdac6 100755 --- a/Extensions/DependencyInjectionExtensions.cs +++ b/Extensions/DependencyInjectionExtensions.cs @@ -8,12 +8,10 @@ using GamificationService.Logs; using GamificationService.Mapper; using GamificationService.Services.Cookies; using GamificationService.Services.CurrentUsers; -using GamificationService.Services.InstructionTests; using GamificationService.Services.JWT; using GamificationService.Services.NotificationService; using GamificationService.Services.Rights; using GamificationService.Services.Roles; -using GamificationService.Services.UsersProfile; using GamificationService.Utils; using GamificationService.Utils.Factory; using Microsoft.AspNetCore.Authentication.JwtBearer; @@ -129,8 +127,6 @@ public static class BackendServicesExtensions { public static IServiceCollection AddBackendServices(this IServiceCollection services) { - services.AddScoped(); - services.AddScoped(); return services; } } diff --git a/MDSBackend.csproj b/GamificationService.csproj similarity index 100% rename from MDSBackend.csproj rename to GamificationService.csproj diff --git a/Mapper/MappingProfile.cs b/Mapper/MappingProfile.cs index eb7b21f..f69ec5d 100755 --- a/Mapper/MappingProfile.cs +++ b/Mapper/MappingProfile.cs @@ -46,124 +46,6 @@ public class MappingProfile : Profile .ForMember(x => x.ProfilePicture, opt => opt.MapFrom(src => src.ProfilePicture)); #endregion - - #region InstructionParagraphMapping - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Text, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.InstructionId, opt => opt.MapFrom(src => src.InstructionId)) - .ForMember(x => x.Order, opt => opt.MapFrom(src => src.Order)) - .ForMember(x => x.ImageUrl, opt => opt.MapFrom(src => src.ImageUrl)) - .ForMember(x => x.VideoUrl, opt => opt.MapFrom(src => src.VideoUrl)); - - #endregion - - #region InstructionMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)) - .ForMember(x => x.Description, opt => opt.MapFrom(src => src.Description)) - .ForMember(x => x.CategoryId, opt => opt.MapFrom(src => src.CategoryId)) - .ForMember(x => x.AssignDate, opt => opt.MapFrom(src => src.AssignDate)) - .ForMember(x => x.AssignDate, opt => opt.MapFrom(src => src.DeadlineDate)) - .ForMember(x => x.IsEnabled, opt => opt.MapFrom(src => src.IsEnabled)) - .ForMember(x => x.Paragraphs, opt => opt.MapFrom(src => src.Paragraphs)); - - #endregion - - #region InstructionCreateMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)) - .ForMember(x => x.Description, opt => opt.MapFrom(src => src.Description)) - .ForMember(x => x.Paragraphs, opt => opt.MapFrom(src => src.Paragraphs)) - .ForMember(x => x.CategoryId, opt => opt.MapFrom(src => src.CategoryId)) - .ForMember(x => x.AssignDate, opt => opt.MapFrom(src => src.AssignDate)) - .ForMember(x => x.DeadlineDate, opt => opt.MapFrom(src => src.DeadlineDate)) - .ForMember(x => x.IsEnabled, opt => opt.MapFrom(src => src.IsEnabled)); - #endregion - - #region InstructionParagraphCreateMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Text, opt => opt.MapFrom(src => src.Text)) - .ForMember(x => x.InstructionId, opt => opt.MapFrom(src => src.InstructionId)) - .ForMember(x => x.Order, opt => opt.MapFrom(src => src.Order)) - .ForMember(x => x.ImageUrl, opt => opt.MapFrom(src => src.ImageUrl)) - .ForMember(x => x.VideoUrl, opt => opt.MapFrom(src => src.VideoUrl)); - - #endregion - - #region InstructionCategoryMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)); - - #endregion - - #region InstructionCategoryCreateMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)); - - #endregion - - #region InstructionTestMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)) - .ForMember(x => x.Questions, opt => opt.MapFrom(src => src.Questions)) - .ForMember(x => x.ScoreCalcMethod, opt => opt.MapFrom(src => src.ScoreCalcMethod)) - .ForMember(x => x.MinScore, opt => opt.MapFrom(src => src.MinScore)) - .ForMember(x => x.MaxAttempts, opt => opt.MapFrom(src => src.MaxAttempts)); - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Title, opt => opt.MapFrom(src => src.Title)) - .ForMember(x => x.ScoreCalcMethod, opt => opt.MapFrom(src => src.ScoreCalcMethod)) - .ForMember(x => x.MinScore, opt => opt.MapFrom(src => src.MinScore)) - .ForMember(x => x.MaxAttempts, opt => opt.MapFrom(src => src.MaxAttempts)) - .ForMember(x => x.Questions, opt => opt.MapFrom(src => src.Questions)); - - #endregion - - #region InstructionTestQuestionCreateMapping - - CreateMap() - .ForMember(x => x.Question, opt => opt.MapFrom(src => src.Question)) - .ForMember(x => x.Answers, opt => opt.MapFrom(src => src.Answers)) - .ForMember(x => x.Order, opt => opt.MapFrom(src => src.Order)) - .ForMember(x => x.IsMultipleAnswer, opt => opt.MapFrom(src => src.IsMultipleAnswer)) - .ForMember(x => x.CorrectAnswers, opt => opt.MapFrom(src => src.CorrectAnswers)); - - #endregion - - #region InstructionTestQuestionMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.Question, opt => opt.MapFrom(src => src.Question)) - .ForMember(x => x.Answers, opt => opt.MapFrom(src => src.Answers)) - .ForMember(x => x.Order, opt => opt.MapFrom(src => src.Order)) - .ForMember(x => x.IsMultipleAnswer, opt => opt.MapFrom(src => src.IsMultipleAnswer)); - - #endregion - - #region InstructionTestResultMapping - - CreateMap() - .ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id)) - .ForMember(x => x.UserId, opt => opt.MapFrom(src => src.UserId)) - .ForMember(x => x.InstructionTestId, opt => opt.MapFrom(src => src.InstructionTestId)) - .ForMember(x => x.Score, opt => opt.MapFrom(src => src.Score)); - - #endregion } } diff --git a/Models/DTO/InstructionCategoryCreateDTO.cs b/Models/DTO/InstructionCategoryCreateDTO.cs deleted file mode 100644 index aa03952..0000000 --- a/Models/DTO/InstructionCategoryCreateDTO.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionCategoryCreateDTO -{ - public long? Id { get; set; } - - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; -} - - - diff --git a/Models/DTO/InstructionCategoryDTO.cs b/Models/DTO/InstructionCategoryDTO.cs deleted file mode 100644 index c3482e5..0000000 --- a/Models/DTO/InstructionCategoryDTO.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace GamificationService.Models.DTO; - -public class InstructionCategoryDTO -{ - public long? Id { get; set; } - - public string? Title { get; set; } = null!; -} - - diff --git a/Models/DTO/InstructionCreateDTO.cs b/Models/DTO/InstructionCreateDTO.cs deleted file mode 100644 index 4f645f0..0000000 --- a/Models/DTO/InstructionCreateDTO.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionCreateDTO -{ - public long? Id { get; set; } - - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; - - public string? Description { get; set; } - - [Required(ErrorMessage = "Paragraphs are required")] - public List Paragraphs { get; set; } = null!; - - [Required(ErrorMessage = "Category id is required")] - public long CategoryId { get; set; } - - /// - /// If AssignDate is set, the instruction will be automatically enabled - /// when the date is reached. If it's not set, the test will automatically - /// obtain the current date as its AssignDate as soon as the instruction - /// will be enabled by the IsEnabled parameter. - /// - public DateTime? AssignDate { get; set; } - - /// - /// When deadline is reached, no more submissions are allowed for this instruction. - /// - public DateTime? DeadlineDate { get; set; } - - /// - /// Disabled instructions cannot be seen by users. - /// Tests for such instructions cannot be submitted either. - /// - public bool IsEnabled { get; set; } = false; -} diff --git a/Models/DTO/InstructionDTO.cs b/Models/DTO/InstructionDTO.cs deleted file mode 100644 index 04b4ba6..0000000 --- a/Models/DTO/InstructionDTO.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace GamificationService.Models.DTO; - -public class InstructionDTO -{ - public long? Id { get; set; } - - public string? Title { get; set; } - - public string? Description { get; set; } - - public List Paragraphs { get; set; } = new List(); - - public long? CategoryId { get; set; } - - public DateTime? AssignDate { get; set; } - - public DateTime? DeadlineDate { get; set; } - - public bool IsEnabled { get; set; } -} - diff --git a/Models/DTO/InstructionParagraphCreateDTO.cs b/Models/DTO/InstructionParagraphCreateDTO.cs deleted file mode 100644 index 10ea234..0000000 --- a/Models/DTO/InstructionParagraphCreateDTO.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionParagraphCreateDTO -{ - public long? Id { get; set; } - - public long? InstructionId { get; set; } - - /// - /// Order defines the order of the paragraphs inside the instruction. - /// There must not be two paragraphs with the same order. - /// - public int Order { get; set; } - - [Required(ErrorMessage = "Text is required")] - public string Text { get; set; } = null!; - - public string? ImageUrl { get; set; } - - public string? VideoUrl { get; set; } -} - - diff --git a/Models/DTO/InstructionParagraphDTO.cs b/Models/DTO/InstructionParagraphDTO.cs deleted file mode 100644 index 29bf0ba..0000000 --- a/Models/DTO/InstructionParagraphDTO.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace GamificationService.Models.DTO; - -public class InstructionParagraphDTO -{ - public long? Id { get; set; } - - public long? InstructionId { get; set; } - - /// - /// Order defines the order of the paragraphs inside the instruction. - /// There must not be two paragraphs with the same order. - /// - public int Order { get; set; } - - public string? Text { get; set; } = null!; - - public string? ImageUrl { get; set; } - - public string? VideoUrl { get; set; } -} - diff --git a/Models/DTO/InstructionTestCreateDTO.cs b/Models/DTO/InstructionTestCreateDTO.cs deleted file mode 100644 index b0800a4..0000000 --- a/Models/DTO/InstructionTestCreateDTO.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using GamificationService.Utils.Enums; - -namespace GamificationService.Models.DTO; - -public class InstructionTestCreateDTO -{ - public long? Id { get; set; } - public string? Title { get; set; } - - [Required(ErrorMessage = "Questions must be specified")] - public ICollection Questions { get; set; } = null!; - - public int MaxAttempts { get; set; } = 10; - - [Range(0, 1.0, ErrorMessage = "Minimum score must be between 0.6 and 1.0")] - public double MinScore { get; set; } = 0.6; - - public InstructionTestScoreCalcMethod ScoreCalcMethod { get; set; } = InstructionTestScoreCalcMethod.MaxGrade; -} diff --git a/Models/DTO/InstructionTestDTO.cs b/Models/DTO/InstructionTestDTO.cs deleted file mode 100644 index 76b0267..0000000 --- a/Models/DTO/InstructionTestDTO.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using GamificationService.Utils.Enums; - -namespace GamificationService.Models.DTO; - -public class InstructionTestDTO -{ - public long? Id { get; set; } - - // Reserved just in case - [StringLength(300, ErrorMessage = "Title cannot be longer than 300 characters")] - public string? Title { get; set; } - - public int MaxAttempts { get; set; } = 10; - - public double MinScore { get; set; } = 0.6; - - public List Questions { get; set; } = new List(); - - public InstructionTestScoreCalcMethod ScoreCalcMethod { get; set; } = InstructionTestScoreCalcMethod.MaxGrade; - -} - diff --git a/Models/DTO/InstructionTestQuestionCreateDTO.cs b/Models/DTO/InstructionTestQuestionCreateDTO.cs deleted file mode 100644 index 9da71cf..0000000 --- a/Models/DTO/InstructionTestQuestionCreateDTO.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionTestQuestionCreateDTO -{ - public long? Id { get; set; } - - public bool IsMultipleAnswer { get; set; } - - /// - /// Question will be displayed in the paragraph with the same order number. - /// There can be multiple questions attached to the same paragraph. - /// - public int Order { get; set; } - - [Required(ErrorMessage = "Must have question text")] - public string Question { get; set; } = null!; - - [Required(ErrorMessage = "Must have answer options")] - public ICollection Answers { get; set; } = null!; - - [Required(ErrorMessage = "Must have correct answers")] - public ICollection CorrectAnswers { get; set; } = null!; -} - diff --git a/Models/DTO/InstructionTestQuestionDTO.cs b/Models/DTO/InstructionTestQuestionDTO.cs deleted file mode 100644 index fe144bd..0000000 --- a/Models/DTO/InstructionTestQuestionDTO.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionTestQuestionDTO -{ - public long? Id { get; set; } - - public bool IsMultipleAnswer { get; set; } - - /// - /// Question will be displayed in the paragraph with the same order number. - /// There can be multiple questions attached to the same paragraph. - /// - public int Order { get; set; } - - [Required(ErrorMessage = "Must have question text")] - public string Question { get; set; } = null!; - - [Required(ErrorMessage = "Must have answer options")] - public ICollection Answers { get; set; } = null!; - - public ICollection? CorrectAnswers { get; set; } -} - diff --git a/Models/DTO/InstructionTestResultDTO.cs b/Models/DTO/InstructionTestResultDTO.cs deleted file mode 100644 index ceb7277..0000000 --- a/Models/DTO/InstructionTestResultDTO.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace GamificationService.Models.DTO; - -public class InstructionTestResultDTO -{ - public long? Id { get; set; } - - public long? InstructionTestId { get; set; } - - public long? UserId { get; set; } - - public int Score { get; set; } -} diff --git a/Models/DTO/InstructionTestSubmissionDTO.cs b/Models/DTO/InstructionTestSubmissionDTO.cs deleted file mode 100644 index 42a3e71..0000000 --- a/Models/DTO/InstructionTestSubmissionDTO.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.DTO; - -public class InstructionTestSubmissionDTO -{ - [Required(ErrorMessage = "InstructionTestId is required")] - public int InstructionTestId { get; set; } - - [Required(ErrorMessage = "Answers must be provided")] - public List> Answers { get; set; } = null!; -} diff --git a/Models/Database/Instruction.cs b/Models/Database/Instruction.cs deleted file mode 100644 index ed7f422..0000000 --- a/Models/Database/Instruction.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.Database; - -public class Instruction -{ - [Key] - public long Id { get; set; } - - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; - - public string? Description { get; set; } - - public long CategoryId { get; set; } - [Required(ErrorMessage = "Category must be specified")] - public InstructionCategory Category { get; set; } = null!; - - public virtual ICollection Paragraphs { get; set; } - - public long? InstructionTestId { get; set; } - public InstructionTest? InstructionTest { get; set; } - - public DateTime? AssignDate { get; set; } = DateTime.UtcNow; - - public DateTime? DeadlineDate { get; set; } - - public bool IsEnabled { get; set; } -} diff --git a/Models/Database/InstructionCategory.cs b/Models/Database/InstructionCategory.cs deleted file mode 100644 index ce29bfd..0000000 --- a/Models/Database/InstructionCategory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.Database; - -public class InstructionCategory -{ - [Key] - public long Id { get; set; } - - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; -} - diff --git a/Models/Database/InstructionParagraph.cs b/Models/Database/InstructionParagraph.cs deleted file mode 100644 index 59c8be2..0000000 --- a/Models/Database/InstructionParagraph.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.Database; - -public class InstructionParagraph -{ - [Key] - public long Id { get; set; } - - public long InstructionId { get; set; } - [Required(ErrorMessage = "Must be linked to instruction")] - - public int Order { get; set; } - - [Required(ErrorMessage = "Paragraph text is required")] - public string Text { get; set; } = null!; - - public string? ImageUrl { get; set; } - - public string? VideoUrl { get; set; } -} diff --git a/Models/Database/InstructionTest.cs b/Models/Database/InstructionTest.cs deleted file mode 100644 index 4b3ea51..0000000 --- a/Models/Database/InstructionTest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using GamificationService.Utils.Enums; - -namespace GamificationService.Models.Database; - -public class InstructionTest -{ - [Key] - public long Id { get; set; } - - // Reserved just in case - [MaxLength(300, ErrorMessage = "Title cannot be longer than 300 characters")] - public string? Title { get; set; } - - public virtual ICollection Questions { get; set; } - - public int MaxAttempts { get; set; } = 10; - - public double MinScore { get; set; } = 0.6; - - public InstructionTestScoreCalcMethod ScoreCalcMethod { get; set; } = InstructionTestScoreCalcMethod.MaxGrade; - -} diff --git a/Models/Database/InstructionTestQuestion.cs b/Models/Database/InstructionTestQuestion.cs deleted file mode 100644 index 44d1ed4..0000000 --- a/Models/Database/InstructionTestQuestion.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.Database; - -public class InstructionTestQuestion -{ - [Key] - public long Id { get; set; } - - [Required(ErrorMessage = "Must be tied to an instruction test")] - public InstructionTest InstructionTest { get; set; } = null!; - public long InstructionTestId { get; set; } - - public int Order { get; set; } - - public bool IsMultipleAnswer { get; set; } - - [Required(ErrorMessage = "Must have question text")] - public string Question { get; set; } = null!; - - [Required(ErrorMessage = "Must have answer options")] - public ICollection Answers { get; set; } = null!; - - [Required(ErrorMessage = "Must have correct answer ids")] - public ICollection CorrectAnswers { get; set; } = null!; -} diff --git a/Models/Database/InstructionTestResult.cs b/Models/Database/InstructionTestResult.cs deleted file mode 100644 index 8017553..0000000 --- a/Models/Database/InstructionTestResult.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace GamificationService.Models.Database; - -public class InstructionTestResult -{ - [Key] - public long Id { get; set; } - - public long InstructionTestId { get; set; } - [Required(ErrorMessage = "Instruction test is required")] - public virtual InstructionTest InstructionTest { get; set; } = null!; - - public long UserId { get; set; } - [Required(ErrorMessage = "User is required")] - public ApplicationUser User { get; set; } = null!; - - [Range(0, 100, ErrorMessage = "Score must be a number from 0 to 100")] - public int Score { get; set; } -} diff --git a/Models/Messages/InstructionTests/CreateInstructionTestRequest.cs b/Models/Messages/InstructionTests/CreateInstructionTestRequest.cs deleted file mode 100644 index 1a7256b..0000000 --- a/Models/Messages/InstructionTests/CreateInstructionTestRequest.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.InstructionTests; - -public class CreateInstructionTestRequest -{ - -} diff --git a/Models/Messages/InstructionTests/CreateInstructionTestResponse.cs b/Models/Messages/InstructionTests/CreateInstructionTestResponse.cs deleted file mode 100644 index 53b8088..0000000 --- a/Models/Messages/InstructionTests/CreateInstructionTestResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.InstructionTests; - -public class CreateInstructionTestResponse -{ - -} diff --git a/Models/Messages/InstructionTests/UpdateInstructionTestRequest.cs b/Models/Messages/InstructionTests/UpdateInstructionTestRequest.cs deleted file mode 100644 index 7053768..0000000 --- a/Models/Messages/InstructionTests/UpdateInstructionTestRequest.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.InstructionTests; - -public class UpdateInstructionTestRequest -{ - -} diff --git a/Models/Messages/InstructionTests/UpdateInstructionTestResponse.cs b/Models/Messages/InstructionTests/UpdateInstructionTestResponse.cs deleted file mode 100644 index 7552973..0000000 --- a/Models/Messages/InstructionTests/UpdateInstructionTestResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.InstructionTests; - -public class UpdateInstructionTestResponse -{ - -} diff --git a/Models/Messages/Instructions/CreateInstructionRequest.cs b/Models/Messages/Instructions/CreateInstructionRequest.cs deleted file mode 100644 index d32445c..0000000 --- a/Models/Messages/Instructions/CreateInstructionRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using GamificationService.Models.DTO; - -namespace GamificationService.Models.Messages.Instructions; - -public class CreateInstructionRequest -{ - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; - - public string? Description { get; set; } - - [Required(ErrorMessage = "Paragraphs are required")] - public List Paragraphs { get; set; } = null!; - - [Required(ErrorMessage = "Category id is required")] - public long CategoryId { get; set; } - - /// - /// If AssignDate is set, the instruction will be automatically enabled - /// when the date is reached. If it's not set, the test will automatically - /// obtain the current date as its AssignDate as soon as the instruction - /// will be enabled by the IsEnabled parameter. - /// - public DateTime? AssignDate { get; set; } - - /// - /// When deadline is reached, no more submissions are allowed for this instruction. - /// - public DateTime? DeadlineDate { get; set; } - - /// - /// Disabled instructions cannot be seen by users. - /// Tests for such instructions cannot be submitted either. - /// - public bool IsEnabled { get; set; } = false; -} diff --git a/Models/Messages/Instructions/CreateInstructionResponse.cs b/Models/Messages/Instructions/CreateInstructionResponse.cs deleted file mode 100644 index dd73918..0000000 --- a/Models/Messages/Instructions/CreateInstructionResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.Instructions; - -public class CreateInstructionResponse -{ - -} diff --git a/Models/Messages/Instructions/UpdateInstructionRequest.cs b/Models/Messages/Instructions/UpdateInstructionRequest.cs deleted file mode 100644 index 32b5df8..0000000 --- a/Models/Messages/Instructions/UpdateInstructionRequest.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using GamificationService.Models.DTO; - -namespace GamificationService.Models.Messages.Instructions; - -public class UpdateInstructionRequest -{ - public long Id { get; set; } - - [Required(ErrorMessage = "Title is required")] - public string Title { get; set; } = null!; - - public string? Description { get; set; } - - [Required(ErrorMessage = "Paragraphs are required")] - public List Paragraphs { get; set; } = null!; - - [Required(ErrorMessage = "Category id is required")] - public long CategoryId { get; set; } - - /// - /// If AssignDate is set, the instruction will be automatically enabled - /// when the date is reached. If it's not set, the test will automatically - /// obtain the current date as its AssignDate as soon as the instruction - /// will be enabled by the IsEnabled parameter. - /// - public DateTime? AssignDate { get; set; } - - /// - /// When deadline is reached, no more submissions are allowed for this instruction. - /// - public DateTime? DeadlineDate { get; set; } - - /// - /// Disabled instructions cannot be seen by users. - /// Tests for such instructions cannot be submitted either. - /// - public bool IsEnabled { get; set; } = false; -} - diff --git a/Models/Messages/Instructions/UpdateInstructionResponse.cs b/Models/Messages/Instructions/UpdateInstructionResponse.cs deleted file mode 100644 index e58c5ed..0000000 --- a/Models/Messages/Instructions/UpdateInstructionResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GamificationService.Models.Messages.Instructions; - -public class UpdateInstructionResponse -{ - -} diff --git a/Program.cs b/Program.cs index c759c1a..705fc27 100755 --- a/Program.cs +++ b/Program.cs @@ -29,12 +29,6 @@ builder.Services.AddLogging(); #endregion -#region SMTP - -builder.Services.AddEmail(builder.Configuration); - -#endregion - #region Database builder.Services.AddDatabase(builder.Configuration); diff --git a/Services/InstructionTests/IInstructionTestsService.cs b/Services/InstructionTests/IInstructionTestsService.cs deleted file mode 100644 index c06939b..0000000 --- a/Services/InstructionTests/IInstructionTestsService.cs +++ /dev/null @@ -1,22 +0,0 @@ -using GamificationService.Models.Database; -using GamificationService.Models.DTO; - -namespace GamificationService.Services.InstructionTests; - -public interface IInstructionTestsService -{ - public Task CreateInstructionTest(InstructionTest instructionTest); - public Task CreateInstructionTest(InstructionTestCreateDTO instructionTest); - public Task UpdateInstructionTest(InstructionTest instructionTest); - public Task UpdateInstructionTest(InstructionTestCreateDTO instructionTest); - public Task DeleteInstructionTestByIdAsync(long id); - - public Task SubmitInstructionTestAsync(long userId, InstructionTestSubmissionDTO submission); - - public InstructionTestDTO GetInstructionTestById(long id); - public List GetInstructionTestsByInstructionId(long instructionId); - public List GetInstructionTestQuestionsByInstructionTestId(long instructionTestId); - public List GetUserInstructionTestResultsByInstructionTestId(long userId, long instructionId); - public List GetInstructionTestResultsByUserId(long userId); - public List GetCompletedInstructionTestsByUserId(long userId); -} diff --git a/Services/InstructionTests/InstructionTestsService.cs b/Services/InstructionTests/InstructionTestsService.cs deleted file mode 100644 index c102111..0000000 --- a/Services/InstructionTests/InstructionTestsService.cs +++ /dev/null @@ -1,294 +0,0 @@ -using AutoMapper; -using GamificationService.Database.Repositories; -using GamificationService.Exceptions.Services.Instruction; -using GamificationService.Exceptions.Services.InstructionTest; -using GamificationService.Models.Database; -using GamificationService.Models.DTO; -using GamificationService.Utils.Enums; - -namespace GamificationService.Services.InstructionTests; - -public class InstructionTestsService : IInstructionTestsService -{ - private readonly ILogger _logger; - private readonly UnitOfWork _unitOfWork; - private readonly IMapper _mapper; - - public InstructionTestsService(ILogger logger, UnitOfWork unitOfWork, IMapper mapper) - { - _logger = logger; - _unitOfWork = unitOfWork; - _mapper = mapper; - } - - public async Task CreateInstructionTest(InstructionTestCreateDTO instructionTest) - { - return _mapper.Map(await CreateInstructionTest(_mapper.Map(instructionTest))); - } - - public async Task DeleteInstructionTestByIdAsync(long id) - { - var instructionTest = _unitOfWork.InstructionTestRepository.GetByID(id); - - if (instructionTest == null) - { - _logger.LogError("Instruction test with id {Id} not found", id); - throw new InstructionTestNotFoundException(); - } - - // Find all questions - var questions = _unitOfWork.InstructionTestQuestionRepository.Get(q => q.InstructionTestId == id); - - // Start transaction - await _unitOfWork.BeginTransactionAsync(); - - foreach (var question in questions) - { - _unitOfWork.InstructionTestQuestionRepository.Delete(question); - } - - // Delete instruction test - _unitOfWork.InstructionTestRepository.Delete(instructionTest); - - if (await _unitOfWork.SaveAsync()) - { - await _unitOfWork.CommitAsync(); - _logger.LogInformation("Instruction test deleted ({Id})", id); - return true; - } - else - { - _logger.LogError("Failed to delete instruction test ({Id})", id); - throw new InstructionTestDeletionException(); - } - - } - - public List GetCompletedInstructionTestsByUserId(long userId) - { - var userTestAttempts = _unitOfWork.InstructionTestResultRepository.Get( - q => q.UserId == userId).ToList(); - - var userInstructionTests = _unitOfWork.InstructionTestRepository.Get( - q => userTestAttempts.Any(a => a.InstructionTestId == q.Id)).ToList(); - - var conclusiveUserTestResults = new List(); - foreach (var instructionTest in userInstructionTests) - { - var scoreCalcMethod = instructionTest.ScoreCalcMethod; - int maxScore = 0; - - if (scoreCalcMethod == InstructionTestScoreCalcMethod.AverageGrade) - { - maxScore = (int)Math.Round(userTestAttempts.Where(q => q.InstructionTestId == instructionTest.Id).Average(q => q.Score)); - } - else - { - maxScore = userTestAttempts.Where(q => q.InstructionTestId == instructionTest.Id).Max(q => q.Score); - } - - if (maxScore >= instructionTest.MinScore) - { - conclusiveUserTestResults.Add(_mapper.Map(userTestAttempts.First(q => q.InstructionTestId == instructionTest.Id))); - } - } - - return conclusiveUserTestResults; - } - - public InstructionTestDTO GetInstructionTestById(long id) - { - var instructionTest = _unitOfWork.InstructionTestRepository.GetByID(id); - if (instructionTest == null) - { - _logger.LogError("Instruction test with id {Id} not found", id); - throw new InstructionTestNotFoundException(); - } - return _mapper.Map(instructionTest); - } - - public List GetInstructionTestQuestionsByInstructionTestId(long instructionTestId) - { - var questions = _unitOfWork.InstructionTestQuestionRepository.Get(q => q.InstructionTestId == instructionTestId); - return _mapper.Map>(questions); - } - - public List GetUserInstructionTestResultsByInstructionTestId(long userId, long instructionTestId) - { - var userTestResults = _unitOfWork.InstructionTestResultRepository.Get( - q => q.UserId == userId && q.InstructionTestId == instructionTestId).ToList(); - return _mapper.Map>(userTestResults); - } - - public List GetInstructionTestResultsByUserId(long userId) - { - var userTestResults = _unitOfWork.InstructionTestResultRepository.Get( - q => q.UserId == userId).ToList(); - return _mapper.Map>(userTestResults); - } - - public List GetInstructionTestsByInstructionId(long instructionId) - { - var instructionTest = (_unitOfWork.InstructionRepository.GetByID(instructionId) - ?? throw new InstructionNotFoundException()) - .InstructionTest ?? throw new InstructionTestNotFoundException(); - - return _mapper.Map>(new List() {instructionTest}); - } - - public async Task SubmitInstructionTestAsync(long userId, InstructionTestSubmissionDTO submission) - { - // Retrieve the test and questions - var instructionTest = _unitOfWork.InstructionTestRepository.GetByID(submission.InstructionTestId); - - if (instructionTest == null) - { - _logger.LogError("Instruction test with id {Id} not found", submission.InstructionTestId); - throw new InstructionTestNotFoundException(); - } - - // Check remaining attempts - var userTestAttempts = _unitOfWork.InstructionTestResultRepository.Get( - q => q.UserId == userId && q.InstructionTestId == submission.InstructionTestId).ToList(); - - if (userTestAttempts.Count >= instructionTest.MaxAttempts) - { - _logger.LogWarning("User {UserId}: denied submission for test {InstructionTestId}: max attempts reached", userId, submission.InstructionTestId); - throw new InstructionTestSubmissionException(); - } - - var questions = _unitOfWork.InstructionTestQuestionRepository.Get(q => q.InstructionTestId == submission.InstructionTestId).ToList(); - - // Verify answers amount - if (questions.Count != submission.Answers.Count) - { - _logger.LogWarning("User {UserId}: denied submission for test {InstructionTestId}: wrong number of answers", userId, submission.InstructionTestId); - throw new InstructionTestSubmissionException(); - } - - // Evaluate answers - double score = 0; - int maxErrorPerQuestion = 1; - for (int i = 0; i < questions.Count; i++) - { - var question = questions[i]; - - // User answers for the question without duplicate options - var answer = submission.Answers[i].Distinct(); - - if (question.IsMultipleAnswer) - { - int correctUserAnswersCount = 0; - int incorrectUserAnswersCount = 0; - int correctAnswersCount = question.CorrectAnswers.Count; - - foreach (var option in answer) - { - if (question.CorrectAnswers.Contains(option)) - { - correctUserAnswersCount++; - } - else - { - incorrectUserAnswersCount++; - } - } - - if (incorrectUserAnswersCount > maxErrorPerQuestion || correctUserAnswersCount == 0) - { - // Nothing scored for the question - continue; - } - - // One question is worth 1 point max - double questionScore = correctUserAnswersCount / (double)correctAnswersCount; - - // Add the question score, or half of it if an error is present - score += incorrectUserAnswersCount > 0 ? questionScore /= 2 : questionScore; - } - else - { - score += question.CorrectAnswers.Contains(answer.First()) ? 1 : 0; - } - } - - score = Math.Round(score / questions.Count)*100; - - // Add test result - await _unitOfWork.BeginTransactionAsync(); - - InstructionTestResult newTestResult = new InstructionTestResult() - { - UserId = userId, - InstructionTestId = submission.InstructionTestId, - Score = (int)score - }; - - _unitOfWork.InstructionTestResultRepository.Insert(newTestResult); - - if (!await _unitOfWork.SaveAsync()) - { - _logger.LogError("Failed to save test result for user {UserId} and test {InstructionTestId}", userId, submission.InstructionTestId); - throw new InstructionTestSubmissionException(); - } - - await _unitOfWork.CommitAsync(); - return _mapper.Map(newTestResult); - } - - public async Task UpdateInstructionTest(InstructionTestCreateDTO instructionTest) - { - return await UpdateInstructionTest(_mapper.Map(instructionTest)); - } - - public async Task CreateInstructionTest(InstructionTest instructionTest) - { - instructionTest.Id = 0; - - await _unitOfWork.BeginTransactionAsync(); - - await _unitOfWork.InstructionTestRepository.InsertAsync(instructionTest); - - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError("Failure to create instruction test"); - throw new InstructionTestCreationException(); - } - - await _unitOfWork.CommitAsync(); - - _logger.LogInformation($"Created instruction test {instructionTest.Id}"); - return instructionTest; - } - - public async Task UpdateInstructionTest(InstructionTest instructionTest) - { - var existingInstructionTest = _unitOfWork.InstructionTestRepository.GetByID(instructionTest.Id); - if (existingInstructionTest == null) - { - throw new InstructionTestNotFoundException(); - } - - await _unitOfWork.BeginTransactionAsync(); - - _unitOfWork.InstructionTestQuestionRepository.DeleteRange(existingInstructionTest.Questions); - - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Failure to create existing questions for instruction test {instructionTest.Id} during update"); - throw new InstructionTestCreationException(); - } - - _unitOfWork.InstructionTestRepository.Update(instructionTest); - - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Failure to update instruction test {instructionTest.Id}"); - } - - await _unitOfWork.CommitAsync(); - - return true; - } -} - diff --git a/Services/Instructions/IInstructionService.cs b/Services/Instructions/IInstructionService.cs deleted file mode 100644 index 6db499c..0000000 --- a/Services/Instructions/IInstructionService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using GamificationService.Models.Database; -using GamificationService.Models.DTO; -using GamificationService.Models.Messages.Instructions; - -namespace GamificationService.Services.Instructions; - -public interface IInstructionService -{ - public Task CreateInstruction(Instruction model); - public Task UpdateInstructionById(Instruction model); - public Task DeleteInstructionById(long instructionId); - - public Task CreateInstruction(CreateInstructionRequest model); - public Task UpdateInstructionById(UpdateInstructionRequest model); - - public List GetAllInstructions(long userId); - public List GetInstructionsByCategoryId(long userId, long categoryId); - public List GetCompletedInstructions(long userId); - public List GetUnfinishedInstructions(long userId); - public List GetInstructionById(long userId, long instructionId); -} diff --git a/Services/Instructions/InstructionService.cs b/Services/Instructions/InstructionService.cs deleted file mode 100644 index 8fd56f1..0000000 --- a/Services/Instructions/InstructionService.cs +++ /dev/null @@ -1,174 +0,0 @@ -using AutoMapper; -using GamificationService.Database.Repositories; -using GamificationService.Exceptions.Services.Instruction; -using GamificationService.Models.Database; -using GamificationService.Models.DTO; -using GamificationService.Models.Messages.Instructions; -using GamificationService.Services.InstructionTests; - -namespace GamificationService.Services.Instructions; - -public class InstructionService : IInstructionService -{ - private readonly UnitOfWork _unitOfWork; - private readonly IMapper _mapper; - private readonly ILogger _logger; - private readonly IInstructionTestsService _instructionTestService; - - public InstructionService(UnitOfWork unitOfWork, IMapper mapper, ILogger logger, IInstructionTestsService instructionTestService) - { - _unitOfWork = unitOfWork; - _mapper = mapper; - _logger = logger; - _instructionTestService = instructionTestService; - } - - public async Task CreateInstruction(Instruction model) - { - model.Id = 0; - - await _unitOfWork.BeginTransactionAsync(); - - await _unitOfWork.InstructionRepository.InsertAsync(model); - - if(await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Instruction {model.Id} could not be created"); - throw new InstructionCreationException(); - } - - await _unitOfWork.CommitAsync(); - - _logger.LogInformation($"Instruction {model.Id} created"); - return model; - } - - public async Task CreateInstruction(CreateInstructionRequest model) - { - Instruction newInstruction = new Instruction() - { - Title = model.Title, - Description = model.Description, - CategoryId = model.CategoryId, - Paragraphs = _mapper.Map>(model.Paragraphs), - AssignDate = model.AssignDate, - DeadlineDate = model.DeadlineDate, - IsEnabled = model.IsEnabled - }; - - return _mapper.Map(await CreateInstruction(newInstruction)); - } - - public async Task DeleteInstructionById(long instructionId) - { - Instruction? instruction = _unitOfWork.InstructionRepository.GetByID(instructionId); - if (instruction == null) - { - throw new InstructionNotFoundException(); - } - _unitOfWork.InstructionRepository.Delete(instruction); - - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Instruction {instructionId} could not be deleted"); - throw new InstructionDeletionException(); - } - - _logger.LogInformation($"Instruction {instructionId} deleted"); - return true; - } - - public List GetAllInstructions(long userId) - { - // TODO: select accessible only - var instructions = _unitOfWork.InstructionRepository.Get().ToList(); - return _mapper.Map>(instructions); - } - - public List GetCompletedInstructions(long userId) - { - var completedTests = _instructionTestService.GetCompletedInstructionTestsByUserId(userId); - var instructions = _unitOfWork.InstructionRepository.Get() - .Where(i => completedTests.Any(t => i.InstructionTestId == t.Id)); - - return _mapper.Map>(instructions); - } - - public List GetInstructionById(long userId, long instructionId) - { - // TODO: select accessible only - var instruction = _unitOfWork.InstructionRepository.GetByID(instructionId); - return _mapper.Map>(instruction); - } - - public List GetInstructionsByCategoryId(long userId, long categoryId) - { - var category = _unitOfWork.InstructionCategoryRepository.GetByID(categoryId); - if (category == null) - { - throw new CategoryNotFoundException(); - } - - var instructions = _unitOfWork.InstructionRepository.Get().Where(i => i.CategoryId == categoryId); - return _mapper.Map>(instructions); - } - - public List GetUnfinishedInstructions(long userId) - { - // TODO: only show accessible - var completedTests = _instructionTestService.GetCompletedInstructionTestsByUserId(userId); - - var instructions = _unitOfWork.InstructionRepository.Get() - .Where(i => !completedTests.Any(t => i.InstructionTestId == t.Id)); - - return _mapper.Map>(instructions); - } - - public async Task UpdateInstructionById(Instruction model) - { - var existingInstruction = _unitOfWork.InstructionRepository.GetByID(model.Id); - if (existingInstruction == null) - { - throw new InstructionNotFoundException(); - } - - await _unitOfWork.BeginTransactionAsync(); - - _unitOfWork.InstructionParagraphRepository.DeleteRange(existingInstruction.Paragraphs); - - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Failure to delete older paragraphs for instruction {model.Id} during update"); - throw new InstructionUpdateException(); - } - - _unitOfWork.InstructionRepository.Update(model); - if (await _unitOfWork.SaveAsync() == false) - { - _logger.LogError($"Instruction {model.Id} could not be updated"); - throw new InstructionUpdateException(); - } - _logger.LogInformation($"Instruction {model.Id} updated"); - return true; - } - - public async Task UpdateInstructionById(UpdateInstructionRequest model) - { - Instruction? existingInstruction = _unitOfWork.InstructionRepository.GetByID(model.Id); - - if (existingInstruction == null) - { - throw new InstructionNotFoundException(); - } - - existingInstruction.Title = model.Title; - existingInstruction.Description = model.Description; - existingInstruction.CategoryId = model.CategoryId; - existingInstruction.Paragraphs = _mapper.Map>(model.Paragraphs); - existingInstruction.AssignDate = model.AssignDate; - existingInstruction.DeadlineDate = model.DeadlineDate; - existingInstruction.IsEnabled = model.IsEnabled; - - return await UpdateInstructionById(_mapper.Map(model)); - } -}