clashlib/
clash.rs

1mod public_handle;
2mod testcase;
3
4pub use public_handle::PublicHandle;
5use serde::{Deserialize, Serialize};
6use testcase::deserialize_testcases;
7pub use testcase::Testcase;
8
9/// `Clash` represents a deserialized Clash of Code or I/O puzzle.
10#[derive(Debug, Serialize, Deserialize)]
11pub struct Clash {
12    id: u32,
13    #[serde(rename = "publicHandle")]
14    public_handle: PublicHandle,
15    #[serde(rename = "lastVersion")]
16    last_version: ClashVersion,
17    #[serde(rename = "type")]
18    puzzle_type: PuzzleType,
19    #[serde(rename = "upVotes")]
20    upvotes: i32,
21    #[serde(rename = "downVotes")]
22    downvotes: i32,
23}
24
25#[derive(Debug, Serialize, Deserialize)]
26enum PuzzleType {
27    #[serde(rename = "CLASHOFCODE")]
28    Clash,
29    #[serde(rename = "PUZZLE_INOUT")]
30    ClassicInOut,
31}
32
33#[derive(Debug, Serialize, Deserialize)]
34struct ClashVersion {
35    version: u32,
36    data: ClashData,
37    #[serde(rename = "statementHTML")]
38    statement_html: Option<String>,
39}
40
41#[derive(Debug, Serialize, Deserialize)]
42struct ClashData {
43    title: String,
44
45    // apparently some of these fields are missing in very old clashes, default to false
46    #[serde(default)]
47    fastest: bool,
48    #[serde(default)]
49    reverse: bool,
50    #[serde(default)]
51    shortest: bool,
52
53    statement: String,
54
55    #[serde(rename = "testCases")]
56    #[serde(deserialize_with = "deserialize_testcases")]
57    testcases: Vec<Testcase>,
58
59    constraints: Option<String>,
60    #[serde(rename = "stubGenerator")]
61    stub_generator: Option<String>,
62    #[serde(rename = "inputDescription")]
63    input_description: String,
64    #[serde(rename = "outputDescription")]
65    output_description: String,
66}
67
68impl Clash {
69    pub fn testcases(&self) -> &Vec<Testcase> {
70        &self.last_version.data.testcases
71    }
72
73    pub fn codingame_link(&self) -> String {
74        format!("https://www.codingame.com/contribute/view/{}", self.public_handle)
75    }
76
77    pub fn title(&self) -> &str {
78        &self.last_version.data.title
79    }
80
81    pub fn statement(&self) -> &str {
82        &self.last_version.data.statement
83    }
84
85    pub fn constraints(&self) -> Option<&str> {
86        self.last_version.data.constraints.as_deref()
87    }
88
89    pub fn stub_generator(&self) -> Option<&str> {
90        self.last_version.data.stub_generator.as_deref()
91    }
92
93    pub fn input_description(&self) -> &str {
94        &self.last_version.data.input_description
95    }
96
97    pub fn output_description(&self) -> &str {
98        &self.last_version.data.output_description
99    }
100
101    pub fn is_reverse(&self) -> bool {
102        self.last_version.data.reverse
103    }
104
105    pub fn is_fastest(&self) -> bool {
106        self.last_version.data.fastest
107    }
108
109    pub fn is_shortest(&self) -> bool {
110        self.last_version.data.shortest
111    }
112
113    pub fn is_reverse_only(&self) -> bool {
114        self.is_reverse() && !self.is_fastest() && !self.is_shortest()
115    }
116}