///|
/// kiln — well-posed problem generation with machine-checkable certificates.
///
/// The library is arranged as a pipeline, and each stage is usable on its own:
///
/// 1. `load_schema` text → `Schema` (parse + static validation)
/// 2. `generate` `Schema` → `Pool` of independently verified `Item`s
/// 3. `assemble` `Pool` + `Blueprint` → `Paper`
/// 4. `render_*` `Paper` → self-contained HTML / Markdown
///
/// The convenience entry point for embedders is `quick_paper`, which runs the
/// first three stages and reports every failure as a string instead of raising.
pub fn quick_paper(
schema_src : String,
count : Int32,
seed : Int32,
) -> Result[Paper, String] {
match load_schema(schema_src) {
Err(e) => Err(e)
Ok(schema) => {
let pool = generate(schema, 0)
if pool.size() == 0 {
return Err("schema '\{schema.name}' 没有产出任何题目")
}
assemble(pool, schema.name, Blueprint::new(count, seed))
}
}
}
///|
/// Same as `quick_paper`, but with an explicit difficulty shape.
pub fn quick_paper_with(
schema_src : String,
per_level : Array[(Int32, Int32)],
seed : Int32,
) -> Result[Paper, String] {
match load_schema(schema_src) {
Err(e) => Err(e)
Ok(schema) => {
let pool = generate(schema, 0)
if pool.size() == 0 {
return Err("schema '\{schema.name}' 没有产出任何题目")
}
assemble(pool, schema.name, Blueprint::with_levels(per_level, seed))
}
}
}
///|
test "quick_paper runs the whole pipeline" {
match quick_paper(SAMPLE_SCHEMA, 5, 3) {
Ok(paper) => {
inspect(paper.size(), content="5")
inspect(paper.schema_name, content="quadratic_int_roots")
}
Err(e) => abort("unexpected: \{e}")
}
}
///|
test "quick_paper surfaces schema errors instead of raising" {
match quick_paper("schema \"bad\"\nfamily quadratic\n", 3, 1) {
Ok(_) => abort("expected an error")
Err(e) => inspect(e.contains("answer"), content="true")
}
}