letslogic 0.1.1

A library providing interaction with the Let's Logic API
Documentation
use serde::{Deserialize, Serialize};

use crate::{submit_solution, SubmitSolutionError, SubmitSolutionResult};

#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
pub struct Level {
    id: i32,
    height: i32,
    width: i32,
    title: String,
    author: Option<String>,
    map: String,
    #[serde(rename = "blue_moves")]
    best_move_moves: Option<i32>,
    #[serde(rename = "blue_pushes")]
    best_move_pushes: Option<i32>,
    #[serde(rename = "green_moves")]
    best_push_moves: Option<i32>,
    #[serde(rename = "green_pushes")]
    best_push_pushes: Option<i32>,
}

impl Level {
    pub async fn submit_solution(
        &self,
        api_key: &str,
        solution: &str,
    ) -> Result<SubmitSolutionResult, SubmitSolutionError> {
        submit_solution(api_key, self.id, solution).await
    }

    pub fn xsb(&self) -> String {
        assert!(self.map.is_ascii());

        let mut result = String::new();
        for line in self.map.as_bytes().chunks(self.width as usize) {
            result.extend(line.iter().map(|c| match c {
                b'0' => ' ',
                b'1' => '#',
                b'2' => '@',
                b'3' => '$',
                b'4' => '.',
                b'5' => '*',
                b'6' => '+',
                b'7' => '_',
                _ => panic!("invalid character '{}'", *c as char),
            }));
            result.push('\n');
        }
        result
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use indoc::indoc;

    #[test]
    fn xsb() {
        let level = Level {
            id: 100089,
            height: 13,
            width: 13,
            title: "简单休闲系列".to_string(),
            author: Some(
                "闲(XIAN)".to_string(),
            ),
            map: "7111111111111710400304032171314134043317105043510401710530503014111001034311011044143041031133040430400114530504334011001304143341104053040030110000501111111111111177777".to_string(),
            best_move_moves: Some(
                265,
            ),
            best_move_pushes: Some(
                101,
            ),
            best_push_moves: Some(
                395,
            ),
            best_push_pushes: Some(
                73,
            ),
        };
        assert_eq!(
            level.xsb(),
            indoc! {"
                _############
                _# .  $ . $@#
                _#$#.#$. .$$#
                _# * .$*# . #
                _# *$ * $ #.#
                ##  # $.$## #
                # ..#.$ .# $#
                #$$ . .$ .  #
                #.*$ * .$$. #
                #  #$ .#.$$.#
                # . *$ .  $ #
                #    * ######
                ########_____
            "}
        );
    }
}