diff --git a/README.md b/README.md index 0b16a09..03eca13 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ cargo xtask learn learning-lm-rs --submodule https://github.com/LearningInfiniTe # 配置 rustlings 课程 cargo xtask learn rustlings --submodule https://github.com/rust-lang/rustlings.git +# 配置 learning-cxx 课程 cargo xtask learn learning-cxx --submodule # 评测 learning-lm-rs 课程 diff --git a/eval_result.json b/eval_result.json index 38b827d..595b068 100644 --- a/eval_result.json +++ b/eval_result.json @@ -1,34 +1,178 @@ { "exercises": [ { - "name": "f16_overflow.rs", - "result": false + "name": "exercise00", + "result": true + }, + { + "name": "exercise01", + "result": true + }, + { + "name": "exercise02", + "result": true + }, + { + "name": "exercise03", + "result": true + }, + { + "name": "exercise04", + "result": true + }, + { + "name": "exercise05", + "result": true + }, + { + "name": "exercise06", + "result": true + }, + { + "name": "exercise07", + "result": true + }, + { + "name": "exercise08", + "result": true + }, + { + "name": "exercise09", + "result": true }, { - "name": "f16_basics.rs", - "result": false + "name": "exercise10", + "result": true + }, + { + "name": "exercise11", + "result": true + }, + { + "name": "exercise12", + "result": true + }, + { + "name": "exercise13", + "result": true + }, + { + "name": "exercise14", + "result": true + }, + { + "name": "exercise15", + "result": true + }, + { + "name": "exercise16", + "result": true + }, + { + "name": "exercise17", + "result": true + }, + { + "name": "exercise18", + "result": true + }, + { + "name": "exercise19", + "result": true }, { - "name": "attention_score.rs", + "name": "exercise20", "result": true }, { - "name": "gradient_compute.rs", + "name": "exercise21", "result": true }, { - "name": "layer_norm.rs", - "result": false + "name": "exercise22", + "result": true + }, + { + "name": "exercise23", + "result": true + }, + { + "name": "exercise24", + "result": true + }, + { + "name": "exercise25", + "result": true + }, + { + "name": "exercise26", + "result": true + }, + { + "name": "exercise27", + "result": true + }, + { + "name": "exercise28", + "result": true + }, + { + "name": "exercise29", + "result": true + }, + { + "name": "exercise30", + "result": true + }, + { + "name": "exercise31", + "result": true + }, + { + "name": "exercise32", + "result": true + }, + { + "name": "exercise33", + "result": true + }, + { + "name": "exercise34", + "result": true + }, + { + "name": "exercise35", + "result": true + }, + { + "name": "exercise36", + "result": true + }, + { + "name": "exercise37", + "result": true + }, + { + "name": "exercise38", + "result": true + }, + { + "name": "exercise39", + "result": true + }, + { + "name": "exercise40", + "result": true }, { - "name": "multi_head_attention.rs", + "name": "exercise41", "result": true } ], "statistics": { - "total_exercations": 6, - "total_succeeds": 3, - "total_failures": 3, - "total_time": 2 + "total_exercations": 42, + "total_succeeds": 42, + "total_failures": 0, + "total_time": 17 } } \ No newline at end of file diff --git a/exercises/learning-cxx b/exercises/learning-cxx index 919dfd0..94586a6 160000 --- a/exercises/learning-cxx +++ b/exercises/learning-cxx @@ -1 +1 @@ -Subproject commit 919dfd0f7bbb61121f345d1590f6783e5d203a28 +Subproject commit 94586a69d3e3bcc7cf70983398e4ae874902cb8c diff --git a/report/index.html b/report/index.html new file mode 100644 index 0000000..0f90116 --- /dev/null +++ b/report/index.html @@ -0,0 +1,76 @@ + + + + + + 训练营项目报告 + + + + +
+

训练营项目产品手册

+

一个用于管理和评测编程练习的基于Rust的工具

+
+
+
+

🚀 产品使用说明

+

本工具提供了一套命令行接口,用于管理和评测不同课程的练习。

+

配置新课程

+

使用 learn 命令来克隆和配置一个新的课程仓库作为 git submodule。

+
cargo xtask learn --course <课程名称> --submodule <课程仓库Git地址>
+

例如,要配置一个名为 `my-rust-course` 的课程,可以运行:

+
cargo xtask learn --course my-rust-course --submodule https://github.com/user/my-rust-course.git
+ +

评测练习

+

使用 eval 命令来评测练习。可以评测所有课程,也可以指定单个课程。

+

评测所有课程:

+
cargo xtask eval
+

评测指定课程:

+
cargo xtask eval --course <课程名称>
+

评测结果将显示在终端,并保存到项目根目录下的 eval_result.json 文件中。

+
+ +
+

🧩 如何拓展新课程评测

+

系统可以方便地扩展以支持新的课程类型。目前的实现支持 `learning-lm-rs`、`learning-cxx` 和其他基于 `rustlings` 的课程。

+

要添加对新课程类型的支持,需要修改 xtask/src/eval.rs 文件:

+
    +
  1. eval.rs 中为你的新课程类型添加一个新的评测函数,例如 eval_my_course(&self, course_path: &Path) -> Result<(...)>
  2. +
  3. + 在 run_eval 函数的 match 语句中,添加一个新的分支来调用你的评测函数。 +
    // in xtask/src/eval.rs, inside run_eval function
    +let (results, succeeds, failures, exercations) = match course_name {
    +    "learning-lm-rs" => self.eval_learning_lm(&path)?,
    +    "learning-cxx" => self.eval_learning_cxx(&path)?,
    +    "my-new-course" => self.eval_my_course(&path)?, // 添加新的分支
    +    _ => self.eval_rustlings(&path)?
    +};
    +
  4. +
+

新的评测函数需要实现具体的评测逻辑,例如运行测试、检查输出来确定练习的通过状态,并返回一个包含练习结果、成功数、失败数和总数的元组。

+
+ +
+

💡 技术特点

+ +
+
+ + + \ No newline at end of file diff --git a/report/style.css b/report/style.css new file mode 100644 index 0000000..6d8e247 --- /dev/null +++ b/report/style.css @@ -0,0 +1,117 @@ +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + line-height: 1.8; + margin: 0; + padding: 0; + background-color: #f8f9fa; + color: #343a40; +} + +nav { + background: #ffffff; + color: #333; + padding: 0 2rem; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #e9ecef; + position: sticky; + top: 0; + z-index: 1000; +} + +nav .logo { + font-size: 1.5rem; + font-weight: bold; +} + +nav ul { + list-style: none; + margin: 0; + padding: 0; + display: flex; +} + +nav ul li a { + display: block; + padding: 1.5rem 1rem; + text-decoration: none; + color: #555; + transition: background-color 0.3s, color 0.3s; +} + +nav ul li a:hover { + background-color: #f1f1f1; + color: #000; +} + +header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: #fff; + padding: 4rem 2rem; + text-align: center; +} + +header h1 { + font-size: 3rem; + margin: 0; +} + +header p { + font-size: 1.2rem; + opacity: 0.9; +} + +main { + padding: 2rem; + margin: 2rem auto; + max-width: 900px; + background: #ffffff; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0,0,0,0.05); +} + +section { + margin-bottom: 3rem; + padding: 2rem; + border-bottom: 1px solid #eee; +} + +section:last-child { + border-bottom: none; +} + +h2 { + font-size: 2rem; + color: #333; + display: flex; + align-items: center; +} + +h2 .icon { + margin-right: 1rem; + font-size: 2.5rem; +} + +pre { + background: #2d2d2d; + color: #f8f8f2; + padding: 1.5rem; + border-radius: 8px; + white-space: pre-wrap; + word-wrap: break-word; + font-size: 0.95rem; + position: relative; +} + +code { + font-family: 'Fira Code', 'Courier New', Courier, monospace; +} + +footer { + text-align: center; + padding: 1rem 0; + margin-top: 2rem; + font-size: 0.9rem; + color: #666; +} \ No newline at end of file diff --git a/xtask/src/eval.rs b/xtask/src/eval.rs index 79a4263..7bb1c74 100644 --- a/xtask/src/eval.rs +++ b/xtask/src/eval.rs @@ -198,14 +198,7 @@ impl EvalArgs { fn eval_rustlings(&self, course_path: &Path) -> Result<(Vec, usize, usize, usize)> { println!("{}", "评测 rustlings 项目...".blue().bold()); - // 检查是否存在 rustlings 命令 - let rustlings_check = Command::new("rustlings") - .arg("--help") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .output(); - - // 无论 rustlings 命令是否存在,都使用 rustc 编译和运行测试来评测 + // 使用 rustc 编译和运行测试来评测 println!("{}", "使用 rustc 编译和运行测试来评测...".blue().bold()); // 处理 Rustlings 或其他非 learning-lm-rs 项目 @@ -241,41 +234,6 @@ impl EvalArgs { } bar.finish_with_message("评测完成!"); - return Ok((exercise_results, total_succeeds, total_failures, total_exercations)); - - // 处理 Rustlings 或其他非 learning-lm-rs 项目 - let exercise_files = find_exercise_files(&course_path, &None)?; - let total_exercations = exercise_files.len(); - println!("{} {} {}", "找到".blue().bold(), total_exercations, "个练习文件".blue().bold()); - - if total_exercations == 0 { - println!("{}", "未找到练习文件,评测结束。".yellow()); - return Ok((Vec::new(), 0, 0, 0)); - } - - let bar = ProgressBar::new(total_exercations as u64); - bar.set_style( - ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})") - .unwrap() - .progress_chars("##-"), - ); - - let mut exercise_results = Vec::new(); - let mut total_succeeds = 0; - let mut total_failures = 0; - - for exercise_path in exercise_files.iter() { - bar.inc(1); - let (name, result, _time) = grade_exercise(exercise_path, self.verbose)?; - if result { - total_succeeds += 1; - } else { - total_failures += 1; - } - exercise_results.push(ExerciseResult { name, result }); - } - bar.finish_with_message("评测完成!"); - Ok((exercise_results, total_succeeds, total_failures, total_exercations)) } @@ -403,31 +361,10 @@ impl EvalArgs { } } -/// 查找 learning-lm-rs 项目的根目录 -fn find_learning_lm_root(start_path: &Path) -> Result { - // First, check if the provided path exists - if !start_path.exists() { - return Err(anyhow::anyhow!("提供的路径不存在: {}", start_path.display())); - } - // Canonicalize the starting path to resolve any relative components - let mut current_path = start_path - .canonicalize() - .with_context(|| format!("无法规范化路径: {}", start_path.display()))?; - loop { - if current_path.join("Cargo.toml").exists() && current_path.file_name().map_or(false, |name| name == "learning-lm-rs") { - return Ok(current_path); - } - if let Some(parent) = current_path.parent() { - current_path = parent.to_path_buf(); - } else { - break; - } - } - Err(anyhow::anyhow!("找不到 learning-lm-rs 项目根目录")) -} + /// 查找指定目录下的所有练习文件 -fn find_exercise_files(course_path: &Path, course: &Option) -> Result> { +fn find_exercise_files(course_path: &Path, _course: &Option) -> Result> { let mut exercise_files = Vec::new(); if !course_path.exists() {