276 lines
9.2 KiB
C#
276 lines
9.2 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using DramaLing.Api.Services;
|
|
|
|
namespace DramaLing.Api.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/study/sessions")]
|
|
[Authorize]
|
|
public class StudySessionController : ControllerBase
|
|
{
|
|
private readonly IStudySessionService _studySessionService;
|
|
private readonly IAuthService _authService;
|
|
private readonly ILogger<StudySessionController> _logger;
|
|
|
|
public StudySessionController(
|
|
IStudySessionService studySessionService,
|
|
IAuthService authService,
|
|
ILogger<StudySessionController> logger)
|
|
{
|
|
_studySessionService = studySessionService;
|
|
_authService = authService;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 開始新的學習會話
|
|
/// </summary>
|
|
[HttpPost("start")]
|
|
public async Task<ActionResult> StartSession()
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
var session = await _studySessionService.StartSessionAsync(userId.Value);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = new
|
|
{
|
|
SessionId = session.Id,
|
|
TotalCards = session.TotalCards,
|
|
TotalTests = session.TotalTests,
|
|
CurrentCardIndex = session.CurrentCardIndex,
|
|
CurrentTestType = session.CurrentTestType,
|
|
StartedAt = session.StartedAt
|
|
},
|
|
Message = $"Study session started with {session.TotalCards} cards and {session.TotalTests} tests"
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error starting study session");
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to start study session",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 獲取當前測驗
|
|
/// </summary>
|
|
[HttpGet("{sessionId}/current-test")]
|
|
public async Task<ActionResult> GetCurrentTest(Guid sessionId)
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
var currentTest = await _studySessionService.GetCurrentTestAsync(sessionId);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = currentTest
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting current test for session {SessionId}", sessionId);
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to get current test",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提交測驗結果
|
|
/// </summary>
|
|
[HttpPost("{sessionId}/submit-test")]
|
|
public async Task<ActionResult> SubmitTest(Guid sessionId, [FromBody] SubmitTestRequestDto request)
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
// 基本驗證
|
|
if (string.IsNullOrEmpty(request.TestType))
|
|
{
|
|
return BadRequest(new { Success = false, Error = "Test type is required" });
|
|
}
|
|
|
|
if (request.ConfidenceLevel.HasValue && (request.ConfidenceLevel < 1 || request.ConfidenceLevel > 5))
|
|
{
|
|
return BadRequest(new { Success = false, Error = "Confidence level must be between 1 and 5" });
|
|
}
|
|
|
|
var response = await _studySessionService.SubmitTestAsync(sessionId, request);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = response.Success,
|
|
Data = new
|
|
{
|
|
IsCardCompleted = response.IsCardCompleted,
|
|
Progress = response.Progress
|
|
},
|
|
Message = response.IsCardCompleted ? "Card completed!" : "Test recorded successfully"
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error submitting test for session {SessionId}", sessionId);
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to submit test result",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 獲取下一個測驗
|
|
/// </summary>
|
|
[HttpGet("{sessionId}/next-test")]
|
|
public async Task<ActionResult> GetNextTest(Guid sessionId)
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
var nextTest = await _studySessionService.GetNextTestAsync(sessionId);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = nextTest
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting next test for session {SessionId}", sessionId);
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to get next test",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 獲取詳細進度
|
|
/// </summary>
|
|
[HttpGet("{sessionId}/progress")]
|
|
public async Task<ActionResult> GetProgress(Guid sessionId)
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
var progress = await _studySessionService.GetProgressAsync(sessionId);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = progress
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting progress for session {SessionId}", sessionId);
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to get progress",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 完成學習會話
|
|
/// </summary>
|
|
[HttpPut("{sessionId}/complete")]
|
|
public async Task<ActionResult> CompleteSession(Guid sessionId)
|
|
{
|
|
try
|
|
{
|
|
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
|
|
if (userId == null)
|
|
return Unauthorized(new { Success = false, Error = "Invalid token" });
|
|
|
|
var session = await _studySessionService.CompleteSessionAsync(sessionId);
|
|
|
|
return Ok(new
|
|
{
|
|
Success = true,
|
|
Data = new
|
|
{
|
|
SessionId = session.Id,
|
|
CompletedAt = session.EndedAt,
|
|
TotalCards = session.TotalCards,
|
|
CompletedCards = session.CompletedCards,
|
|
TotalTests = session.TotalTests,
|
|
CompletedTests = session.CompletedTests,
|
|
DurationSeconds = session.DurationSeconds
|
|
},
|
|
Message = "Study session completed successfully"
|
|
});
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new { Success = false, Error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error completing session {SessionId}", sessionId);
|
|
return StatusCode(500, new
|
|
{
|
|
Success = false,
|
|
Error = "Failed to complete session",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
} |