1use std::collections::BTreeSet;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 render::markdown::{MarkdownRenderable, RenderError},
7 roi, RawOrImport,
8};
9
10#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default, Hash)]
12#[serde(deny_unknown_fields)]
13pub struct Problem {
14 pub languages: Option<BTreeSet<String>>,
18 pub title: String,
20 pub description: Option<RawOrImport<MarkdownRenderable, roi::Raw>>,
22 pub tests: Vec<Test>,
24 pub points: Option<i32>,
25}
26
27impl Problem {
28 pub(crate) fn as_value(
29 &self,
30 world: &impl typst::World,
31 ) -> Result<typst::foundations::Value, RenderError> {
32 use crate::util;
33 use typst::foundations::Value;
34
35 let mut dict = typst::foundations::Dict::new();
36
37 if let Some(langs) = &self.languages {
38 dict.insert("languages".into(), util::convert(&langs));
39 }
40
41 dict.insert("title".into(), util::convert(&self.title));
42
43 if let Some(desc) = &self.description {
44 dict.insert("description".into(), Value::Content(desc.content(world)?));
45 }
46
47 dict.insert("tests".into(), util::convert(&self.tests));
48
49 Ok(Value::Dict(dict))
50 }
51}
52
53#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
57#[serde(deny_unknown_fields)]
58pub struct Test {
59 pub input: String,
61 pub output: String,
63 #[serde(default = "crate::default_false")]
67 pub visible: bool,
68}
69
70#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default, Hash)]
72#[serde(deny_unknown_fields)]
73pub struct Packet {
74 pub title: String,
76 pub preamble: Option<RawOrImport<MarkdownRenderable, roi::Raw>>,
78 pub problems: Vec<RawOrImport<Problem>>,
80}