api/routes/modules/assignments/mark_allocator/get.rs
1use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json};
2use serde_json::json;
3use util::mark_allocator::mark_allocator::{load_allocator, SaveError};
4use crate::response::ApiResponse;
5
6/// GET /api/modules/{module_id}/assignments/{assignment_id}/mark_allocator
7///
8/// Load the mark allocator JSON configuration for a specific assignment. Accessible to users with
9/// appropriate permissions assigned to the module.
10///
11/// The mark allocator configuration defines how marks are distributed across different tasks and
12/// criteria within an assignment. This configuration is used by the grading system to determine
13/// the weight and allocation of marks for various assessment components.
14///
15/// ### Path Parameters
16/// - `module_id` (i64): The ID of the module containing the assignment
17/// - `assignment_id` (i64): The ID of the assignment to load mark allocator for
18///
19/// ### Example Request
20/// ```bash
21/// curl -X GET http://localhost:3000/api/modules/1/assignments/2/mark_allocator \
22/// -H "Authorization: Bearer <token>"
23/// ```
24///
25/// ### Success Response (200 OK)
26/// ```json
27/// {
28/// "success": true,
29/// "message": "Mark allocator successfully loaded.",
30/// "data": {
31/// "tasks": [
32/// {
33/// "task_number": 1,
34/// "weight": 0.4,
35/// "criteria": [
36/// {
37/// "name": "Correctness",
38/// "weight": 0.7
39/// },
40/// {
41/// "name": "Code Quality",
42/// "weight": 0.3
43/// }
44/// ]
45/// },
46/// {
47/// "task_number": 2,
48/// "weight": 0.6,
49/// "criteria": [
50/// {
51/// "name": "Functionality",
52/// "weight": 0.8
53/// },
54/// {
55/// "name": "Documentation",
56/// "weight": 0.2
57/// }
58/// ]
59/// }
60/// ],
61/// "total_weight": 1.0
62/// }
63/// }
64/// ```
65///
66/// ### Error Responses
67///
68/// **404 Not Found** - Module or assignment folder does not exist
69/// ```json
70/// {
71/// "error": "Module or assignment folder does not exist"
72/// }
73/// ```
74///
75/// **500 Internal Server Error** - Failed to load allocator
76/// ```json
77/// {
78/// "error": "Failed to load allocator"
79/// }
80/// ```
81///
82/// ### Mark Allocator Structure
83/// The mark allocator configuration typically contains:
84/// - `tasks`: Array of task configurations with mark allocations
85/// - `task_number`: Sequential number of the task
86/// - `weight`: Relative weight of this task in the overall assignment (0.0 to 1.0)
87/// - `criteria`: Array of grading criteria for this task
88/// - `name`: Name of the grading criterion
89/// - `weight`: Weight of this criterion within the task (0.0 to 1.0)
90/// - `total_weight`: Sum of all task weights (should equal 1.0)
91///
92/// ### Notes
93/// - The mark allocator configuration is stored as a JSON file in the module/assignment directory
94/// - This configuration is used by the grading system to calculate final marks
95/// - Task weights should sum to 1.0 across all tasks in the assignment
96/// - Criteria weights within each task should also sum to 1.0
97/// - Mark allocator loading is restricted to users with appropriate module permissions
98pub async fn load(
99 Path((module_id, assignment_id)): Path<(i64, i64)>
100) -> impl IntoResponse {
101 match load_allocator(module_id, assignment_id).await {
102 Ok(json) => (
103 StatusCode::OK,
104 Json(ApiResponse::success(
105 json,
106 "Mark allocator successfully loaded.",
107 )),
108 )
109 .into_response(),
110
111 Err(SaveError::DirectoryNotFound) => (
112 StatusCode::NOT_FOUND,
113 Json(json!({ "error": "Module or assignment folder does not exist" })),
114 )
115 .into_response(),
116
117 Err(_) => (
118 StatusCode::INTERNAL_SERVER_ERROR,
119 Json(json!({ "error": "Failed to load allocator" })),
120 )
121 .into_response(),
122 }
123}