ron codec
This commit is contained in:
@@ -1,32 +1,149 @@
|
||||
use camino::Utf8PathBuf;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod mini_moonboard {
|
||||
use crate::Error;
|
||||
use camino::Utf8PathBuf;
|
||||
use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
|
||||
pub const MINI_MOONBOARD_PROBLEMS: &str = "moonboard-problems/problems Mini MoonBoard 2020 40.json";
|
||||
pub const MINI_MOONBOARD_PROBLEMS: &str = "../../moonboard-problems/problems Mini MoonBoard 2020 40.json";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MiniMoonboardProblems {
|
||||
total: u64,
|
||||
data: Vec<Data>,
|
||||
pub struct MiniMoonboard {
|
||||
pub total: u64,
|
||||
|
||||
#[serde(rename = "data")]
|
||||
pub problems: Vec<Problem>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Problem {
|
||||
/// Name of the problem
|
||||
pub name: String,
|
||||
|
||||
pub grade: String,
|
||||
pub user_grade: Option<String>,
|
||||
pub setby_id: String,
|
||||
|
||||
/// Name of the route setter
|
||||
pub setby: String,
|
||||
|
||||
pub method: Method,
|
||||
|
||||
pub user_rating: u64,
|
||||
pub repeats: u64,
|
||||
|
||||
pub is_benchmark: bool,
|
||||
pub is_master: bool,
|
||||
pub upgraded: bool,
|
||||
pub downgraded: bool,
|
||||
pub moves: Vec<Move>,
|
||||
pub holdsets: Vec<HoldSet>,
|
||||
|
||||
pub has_beta_video: bool,
|
||||
pub moon_board_configuration_id: u64,
|
||||
pub api_id: u64,
|
||||
pub date_inserted: String,
|
||||
pub date_updated: Option<String>,
|
||||
pub date_deleted: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Data {}
|
||||
pub enum Method {
|
||||
#[serde(rename = "Feet follow hands")]
|
||||
FeetFollowHands,
|
||||
|
||||
pub async fn parse() -> Result<MiniMoonboardProblems, Error> {
|
||||
let file_path = Utf8PathBuf::from(MINI_MOONBOARD_PROBLEMS);
|
||||
#[serde(rename = "Footless")]
|
||||
Footless,
|
||||
|
||||
let content = tokio::fs::read_to_string(&file_path).await.map_err(|source| Error::Read {
|
||||
#[serde(rename = "Footless + kickboard")]
|
||||
FootlessPlusKickboard,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Move {
|
||||
pub problem_id: u64,
|
||||
pub description: MoveDescription,
|
||||
pub is_start: bool,
|
||||
pub is_end: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HoldSet {
|
||||
pub description: String,
|
||||
pub locations: Option<()>,
|
||||
pub api_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
pub enum MoveDescription {
|
||||
A12, B12, C12, D12, E12, F12, G12, H12, I12, J12, K12,
|
||||
A11, B11, C11, D11, E11, F11, G11, H11, I11, J11, K11,
|
||||
A10, B10, C10, D10, E10, F10, G10, H10, I10, J10, K10,
|
||||
A9, B9, C9, D9, E9, F9, G9, H9, I9, J9, K9,
|
||||
A8, B8, C8, D8, E8, F8, G8, H8, I8, J8, K8,
|
||||
A7, B7, C7, D7, E7, F7, G7, H7, I7, J7, K7,
|
||||
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, K6,
|
||||
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, K5,
|
||||
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4,
|
||||
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, K3,
|
||||
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, K2,
|
||||
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1,
|
||||
}
|
||||
impl MoveDescription {
|
||||
/// Convert to 0-indexed row (starting from top to bottom)
|
||||
pub fn row(&self) -> u64 {
|
||||
use MoveDescription::*;
|
||||
match self {
|
||||
A12 | B12 | C12 | D12 | E12 | F12 | G12 | H12 | I12 | J12 | K12 => 0,
|
||||
A11 | B11 | C11 | D11 | E11 | F11 | G11 | H11 | I11 | J11 | K11 => 1,
|
||||
A10 | B10 | C10 | D10 | E10 | F10 | G10 | H10 | I10 | J10 | K10 => 2,
|
||||
A9 | B9 | C9 | D9 | E9 | F9 | G9 | H9 | I9 | J9 | K9 => 3,
|
||||
A8 | B8 | C8 | D8 | E8 | F8 | G8 | H8 | I8 | J8 | K8 => 4,
|
||||
A7 | B7 | C7 | D7 | E7 | F7 | G7 | H7 | I7 | J7 | K7 => 5,
|
||||
A6 | B6 | C6 | D6 | E6 | F6 | G6 | H6 | I6 | J6 | K6 => 6,
|
||||
A5 | B5 | C5 | D5 | E5 | F5 | G5 | H5 | I5 | J5 | K5 => 7,
|
||||
A4 | B4 | C4 | D4 | E4 | F4 | G4 | H4 | I4 | J4 | K4 => 8,
|
||||
A3 | B3 | C3 | D3 | E3 | F3 | G3 | H3 | I3 | J3 | K3 => 9,
|
||||
A2 | B2 | C2 | D2 | E2 | F2 | G2 | H2 | I2 | J2 | K2 => 10,
|
||||
A1 | B1 | C1 | D1 | E1 | F1 | G1 | H1 | I1 | J1 | K1 => 11,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to 0-indexed column (starting from left to right)
|
||||
pub fn column(&self) -> u64 {
|
||||
use MoveDescription::*;
|
||||
match self {
|
||||
A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 => 0,
|
||||
B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B10 | B11 | B12 => 1,
|
||||
C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | C10 | C11 | C12 => 2,
|
||||
D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 | D11 | D12 => 3,
|
||||
E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9 | E10 | E11 | E12 => 4,
|
||||
F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 => 5,
|
||||
G1 | G2 | G3 | G4 | G5 | G6 | G7 | G8 | G9 | G10 | G11 | G12 => 6,
|
||||
H1 | H2 | H3 | H4 | H5 | H6 | H7 | H8 | H9 | H10 | H11 | H12 => 7,
|
||||
I1 | I2 | I3 | I4 | I5 | I6 | I7 | I8 | I9 | I10 | I11 | I12 => 8,
|
||||
J1 | J2 | J3 | J4 | J5 | J6 | J7 | J8 | J9 | J10 | J11 | J12 => 9,
|
||||
K1 | K2 | K3 | K4 | K5 | K6 | K7 | K8 | K9 | K10 | K11 | K12 => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn parse(file_path: &Path) -> Result<MiniMoonboard, Error> {
|
||||
let content = tokio::fs::read_to_string(file_path).await.map_err(|source| Error::Read {
|
||||
file_path: file_path.to_owned(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
let t: MiniMoonboardProblems = serde_json::from_str(&content).map_err(|source| Error::Deserialize {
|
||||
let t: MiniMoonboard = serde_json::from_str(&content).map_err(|source| Error::Deserialize {
|
||||
file_path: file_path.to_owned(),
|
||||
source,
|
||||
})?;
|
||||
@@ -36,22 +153,25 @@ pub mod mini_moonboard {
|
||||
#[cfg(test)]
|
||||
#[tokio::test]
|
||||
async fn test_parse() {
|
||||
parse().await.unwrap();
|
||||
use std::path::PathBuf;
|
||||
use type_toppings::ResultExt as _;
|
||||
let file_path = PathBuf::from(MINI_MOONBOARD_PROBLEMS);
|
||||
let mini_moonboard = parse(&file_path).await.unwrap_or_report();
|
||||
assert_eq!(mini_moonboard.total, mini_moonboard.problems.len() as u64);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, derive_more::Error, derive_more::Display)]
|
||||
#[display("Persistent state error: {_variant}")]
|
||||
pub enum Error {
|
||||
#[display("Failed to read file: {file_path}")]
|
||||
Read { file_path: Utf8PathBuf, source: std::io::Error },
|
||||
#[display("Failed to read file: {}", file_path.display())]
|
||||
Read { file_path: PathBuf, source: std::io::Error },
|
||||
|
||||
#[display("Failed to deserialize state from file: {file_path}")]
|
||||
Deserialize { file_path: Utf8PathBuf, source: serde_json::Error },
|
||||
#[display("Failed to deserialize file: {}", file_path.display())]
|
||||
Deserialize { file_path: PathBuf, source: serde_json::Error },
|
||||
|
||||
#[display("Failed to serialize state")]
|
||||
#[display("Failed to serialize")]
|
||||
Serialize { source: serde_json::Error },
|
||||
|
||||
#[display("Failed to write file: {file_path}")]
|
||||
Write { file_path: Utf8PathBuf, source: std::io::Error },
|
||||
#[display("Failed to write file: {}", file_path.display())]
|
||||
Write { file_path: PathBuf, source: std::io::Error },
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user