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
文件:
+
+ - 在
eval.rs
中为你的新课程类型添加一个新的评测函数,例如 eval_my_course(&self, course_path: &Path) -> Result<(...)>
。
+ -
+ 在
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)?
+};
+
+
+ 新的评测函数需要实现具体的评测逻辑,例如运行测试、检查输出来确定练习的通过状态,并返回一个包含练习结果、成功数、失败数和总数的元组。
+
+
+
+ 💡 技术特点
+
+ - 基于 Rust 构建: 核心工具链使用 Rust 编写,确保了高性能和内存安全。
+ - 可扩展的评测引擎: 通过模块化的设计,可以轻松地为不同语言或框架的课程添加新的评测逻辑。
+ - 命令行接口: 使用
clap
库提供清晰、易用的命令行接口。
+ - Git Submodule 集成: 课程作为 Git 子模块进行管理,方便版本控制和分发。
+ - 结构化输出: 评测结果以 JSON 格式输出,方便与其他工具或系统集成。
+
+
+
+
+
+
\ 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() {