1
1
use serde:: { Deserialize , Serialize } ;
2
2
use std:: fs:: { self , File } ;
3
3
use std:: path:: { Path , PathBuf } ;
4
- use std:: io:: { self , Write } ;
5
4
use std:: process:: { Command , exit} ;
6
5
use std:: time:: Instant ;
6
+ use std:: io:: { self , Write } ;
7
7
8
8
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
9
9
struct Exercise {
10
10
name : String ,
11
11
path : String ,
12
12
#[ serde( rename = "type" ) ]
13
13
exercise_type : String ,
14
- score : i32 ,
14
+ score : i32 , // Added: Each exercise score
15
15
}
16
16
17
17
#[ derive( Serialize , Deserialize , Debug ) ]
@@ -25,15 +25,15 @@ struct ExerciseConfig {
25
25
struct ExerciseResult {
26
26
name : String ,
27
27
result : bool ,
28
- score : i32 ,
28
+ score : i32 , // Store score for each exercise
29
29
}
30
30
31
31
#[ derive( Serialize , Deserialize , Debug ) ]
32
32
struct Statistics {
33
33
total_exercises : usize ,
34
34
total_successes : usize ,
35
35
total_failures : usize ,
36
- total_score : i32 ,
36
+ total_score : i32 , // Total score for the assessment
37
37
total_time : u64 ,
38
38
}
39
39
@@ -43,7 +43,6 @@ struct Report {
43
43
statistics : Statistics ,
44
44
}
45
45
46
-
47
46
fn main ( ) {
48
47
let args: Vec < String > = std:: env:: args ( ) . collect ( ) ;
49
48
if args. len ( ) < 2 {
@@ -54,7 +53,7 @@ fn main() {
54
53
let mode = & args[ 1 ] ;
55
54
let start_time = Instant :: now ( ) ;
56
55
57
- // 加载 JSON 配置
56
+ // Load the exercise config
58
57
let config = match load_exercise_config ( "exercise_config.json" ) {
59
58
Ok ( cfg) => cfg,
60
59
Err ( e) => {
@@ -69,49 +68,50 @@ fn main() {
69
68
total_exercises : 0 ,
70
69
total_successes : 0 ,
71
70
total_failures : 0 ,
72
- total_score : 0 ,
71
+ total_score : 0 , // Initialize total score to 0
73
72
total_time : 0 ,
74
73
} ,
75
74
} ;
76
75
77
-
76
+ // Evaluate exercises from config
78
77
evaluate_exercises_from_config ( mode, config, & mut report) ;
79
78
80
-
79
+ // Calculate total time
81
80
report. statistics . total_time = start_time. elapsed ( ) . as_secs ( ) ;
82
81
report. statistics . total_exercises = report. statistics . total_successes + report. statistics . total_failures ;
83
82
84
-
83
+ // Output summary
85
84
println ! ( "\n Summary:" ) ;
86
85
println ! ( "Total exercises: {}" , report. statistics. total_exercises) ;
87
86
println ! ( "Total successes: {}" , report. statistics. total_successes) ;
88
87
println ! ( "Total failures: {}" , report. statistics. total_failures) ;
89
- println ! ( "Total score: {}" , report. statistics. total_score) ;
88
+ println ! ( "Total score: {}" , report. statistics. total_score) ; // Output the total score
90
89
91
-
90
+ // Save the report to a JSON file
92
91
if let Err ( e) = save_report_to_json ( "report.json" , & report) {
93
92
eprintln ! ( "Error saving report: {}" , e) ;
94
93
}
95
94
}
96
95
97
-
96
+ // Load exercise configuration from JSON
98
97
fn load_exercise_config ( file_path : & str ) -> Result < ExerciseConfig , io:: Error > {
99
98
let file = File :: open ( file_path) ?;
100
99
let config: ExerciseConfig = serde_json:: from_reader ( file) ?;
101
100
Ok ( config)
102
101
}
103
102
104
-
103
+ // Evaluate all exercises from the configuration
105
104
fn evaluate_exercises_from_config ( mode : & str , config : ExerciseConfig , report : & mut Report ) {
106
105
let all_exercises = [ config. easy , config. normal , config. hard ] . concat ( ) ;
107
106
108
107
for exercise in all_exercises {
109
108
println ! ( "\n Evaluating {}: {}" , exercise. exercise_type, exercise. name) ;
110
109
let result = evaluate_exercise ( & exercise) ;
111
110
112
-
111
+ // Calculate score based on result
113
112
let score = if result { exercise. score } else { 0 } ;
114
113
114
+ // Add result to the report
115
115
report. exercises . push ( ExerciseResult {
116
116
name : exercise. name . clone ( ) ,
117
117
result,
@@ -124,7 +124,7 @@ fn evaluate_exercises_from_config(mode: &str, config: ExerciseConfig, report: &m
124
124
report. statistics . total_failures += 1 ;
125
125
}
126
126
127
-
127
+ // Add score to total score
128
128
report. statistics . total_score += score;
129
129
130
130
if mode == "watch" && !ask_to_continue ( ) {
@@ -133,7 +133,7 @@ fn evaluate_exercises_from_config(mode: &str, config: ExerciseConfig, report: &m
133
133
}
134
134
}
135
135
136
-
136
+ // Evaluate a single exercise
137
137
fn evaluate_exercise ( exercise : & Exercise ) -> bool {
138
138
let exercise_path = PathBuf :: from ( & format ! ( "./exercises/{}" , exercise. path) ) ;
139
139
match exercise. exercise_type . as_str ( ) {
@@ -146,7 +146,7 @@ fn evaluate_exercise(exercise: &Exercise) -> bool {
146
146
}
147
147
}
148
148
149
-
149
+ // Evaluate a single file Rust exercise
150
150
fn evaluate_single_file ( file_path : & PathBuf ) -> bool {
151
151
let output = Command :: new ( "rustc" )
152
152
. arg ( file_path)
@@ -169,7 +169,7 @@ fn evaluate_single_file(file_path: &PathBuf) -> bool {
169
169
}
170
170
}
171
171
172
-
172
+ // Evaluate a cargo project
173
173
fn evaluate_cargo_project ( proj_path : & PathBuf ) -> bool {
174
174
let build_success = run_cargo_command ( proj_path, "build" ) ;
175
175
let test_success = run_cargo_command ( proj_path, "test" ) ;
@@ -183,10 +183,13 @@ fn evaluate_cargo_project(proj_path: &PathBuf) -> bool {
183
183
println ! ( "\x1b [31m{}: FAILED\x1b [0m" , proj_path. display( ) ) ;
184
184
}
185
185
186
+ // Clean up the target directory after evaluation
187
+ clean_target_directory ( proj_path) ;
188
+
186
189
passed
187
190
}
188
191
189
-
192
+ // Run a cargo command (build, test, clippy)
190
193
fn run_cargo_command ( proj_path : & PathBuf , command : & str ) -> bool {
191
194
let output = Command :: new ( "cargo" )
192
195
. arg ( command)
@@ -199,15 +202,28 @@ fn run_cargo_command(proj_path: &PathBuf, command: &str) -> bool {
199
202
}
200
203
}
201
204
205
+ // Clean up the target directory after evaluating a cargo project
206
+ fn clean_target_directory ( proj_path : & PathBuf ) {
207
+ let target_dir = proj_path. join ( "target" ) ;
208
+
209
+ if target_dir. exists ( ) {
210
+ if let Err ( e) = fs:: remove_dir_all ( & target_dir) {
211
+ eprintln ! ( "Failed to clean up target directory: {}" , e) ;
212
+ } else {
213
+ println ! ( "Successfully cleaned up target directory in: {}" , proj_path. display( ) ) ;
214
+ }
215
+ }
216
+ }
202
217
218
+ // Ask the user whether to continue after each evaluation
203
219
fn ask_to_continue ( ) -> bool {
204
220
let mut input = String :: new ( ) ;
205
221
println ! ( "\n Press any key to continue, or 'q' to quit." ) ;
206
222
io:: stdin ( ) . read_line ( & mut input) . unwrap ( ) ;
207
223
input. trim ( ) . to_lowercase ( ) != "q"
208
224
}
209
225
210
-
226
+ // Save the report to a JSON file
211
227
fn save_report_to_json ( file_name : & str , report : & Report ) -> io:: Result < ( ) > {
212
228
let file = File :: create ( file_name) ?;
213
229
serde_json:: to_writer_pretty ( file, report) ?;
0 commit comments