zeeper/
playlist.rs

1use std::str::FromStr;
2
3use anyhow::bail;
4use clap::ValueEnum;
5use serde::{Deserialize, Serialize};
6
7use crate::Level;
8
9#[derive(Serialize, Deserialize, Debug, Clone)]
10pub struct PlaylistMeta {
11    pub name: String,
12    #[serde(rename = "roundLength")]
13    pub round_length: f32,
14    #[serde(rename = "shufflePlaylist")]
15    pub shuffle: bool,
16}
17
18impl FromStr for PlaylistMeta {
19    type Err = anyhow::Error;
20
21    fn from_str(s: &str) -> Result<Self, Self::Err> {
22        let Some((name, rest)) = s.split_once(',') else {
23            bail!("MetaData needs 'name' 'round' 'shuffle' separated by ','");
24        };
25        let Some((round_length, shuffle)) = rest.split_once(',') else {
26            bail!("MetaData needs 'name' 'round' 'shuffle' separated by ','");
27        };
28        let name = name.to_string();
29        let round_length = round_length.parse()?;
30        let shuffle = shuffle.to_lowercase() == "y";
31        Ok(Self {
32            name,
33            round_length,
34            shuffle,
35        })
36    }
37}
38
39#[derive(Serialize, Deserialize, Debug)]
40pub struct Playlist {
41    #[serde(flatten)]
42    pub meta: PlaylistMeta,
43    #[serde(rename = "amountOfLevels")]
44    level_count: usize,
45    levels: Vec<Level>,
46}
47
48// TODO: remove this, only one varient used
49#[derive(ValueEnum, Clone, Copy, Debug)]
50pub enum PurgeStrata {
51    Uid,
52    // Hash,
53}
54
55impl PurgeStrata {
56    fn purge(&mut self, level: &Level, list: &[String]) -> bool {
57        let mut i = list.iter();
58        match self {
59            PurgeStrata::Uid => i.any(|i| level.uid == *i),
60            // PurgeStrata::Hash => i.any(|(_, h)| level.hash == *h),
61        }
62    }
63}
64
65impl Playlist {
66    pub fn new(meta: PlaylistMeta, levels: Vec<Level>) -> Playlist {
67        Self {
68            meta,
69            level_count: levels.len(),
70            levels,
71        }
72    }
73
74    pub fn purge_duplicate(&mut self, mut strategy: PurgeStrata) -> usize {
75        let mut l = vec![];
76        let mut i = 0;
77        self.levels.retain(|p| {
78            let s = strategy.purge(p, &l);
79            if s {
80                i += 1;
81            } else {
82                // l.push((p.uid.clone(), p.hash.clone()));
83                l.push(p.uid.clone())
84            }
85            !s
86        });
87        self.level_count = self.levels.len();
88        i
89    }
90
91    pub fn get_name(&self) -> &str {
92        &self.meta.name
93    }
94
95    pub fn merge(&mut self, mut two: Playlist) {
96        self.levels.append(&mut two.levels);
97        self.level_count = self.levels.len();
98    }
99}