Skip to main content

mindus/
team.rs

1use std::fmt;
2
3use atools::Chunked;
4
5use crate::content::{Content, Type};
6
7#[derive(Clone, Copy, Debug, Eq, Ord, PartialOrd, Default, PartialEq)]
8pub struct Team(u8);
9
10impl Team {
11    #[must_use]
12    pub const fn of(id: u8) -> Self {
13        Self(id)
14    }
15
16    #[must_use]
17    pub const fn is_base(self) -> bool {
18        self.0 < 7
19    }
20}
21
22impl From<u8> for Team {
23    fn from(value: u8) -> Self {
24        Team::of(value)
25    }
26}
27
28impl TryFrom<u16> for Team {
29    type Error = TryFromU16Error;
30
31    fn try_from(value: u16) -> Result<Self, Self::Error> {
32        if u8::try_from(value).is_ok() {
33            Ok(Team(value as u8))
34        } else {
35            Err(TryFromU16Error(value))
36        }
37    }
38}
39
40#[derive(Copy, Clone, Debug, Eq, PartialEq, thiserror::Error)]
41#[error("no content of type Team for value {0}")]
42pub struct TryFromU16Error(pub u16);
43
44impl From<Team> for u8 {
45    fn from(value: Team) -> Self {
46        value.0
47    }
48}
49
50impl From<Team> for u16 {
51    fn from(value: Team) -> Self {
52        u16::from(value.0)
53    }
54}
55
56impl fmt::Display for Team {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self.0 {
59            0 => f.write_str("Derelict"),
60            1 => f.write_str("Sharded"),
61            2 => f.write_str("Crux"),
62            3 => f.write_str("Malis"),
63            4 => f.write_str("Green"),
64            5 => f.write_str("Blue"),
65            6 => f.write_str("Neoplastic"),
66            id => write!(f, "Team #{id}"),
67        }
68    }
69}
70
71const TEAM_NAMES: &str = include_str!("../res/team_names.txt");
72
73impl Content for Team {
74    fn get_type(&self) -> Type {
75        Type::Team
76    }
77
78    fn get_id(&self) -> u16 {
79        u16::from(self.0)
80    }
81
82    fn get_name(&self) -> &'static str {
83        match self.0 {
84            0 => "derelict",
85            1 => "sharded",
86            2 => "crux",
87            3 => "malis",
88            4 => "green",
89            5 => "blue",
90            6 => "neoplastic",
91            // dark magic: offsets manually computed, then rely on the format "...|team#{i}|..."
92            i @ 7..=9 => {
93                // length: 7 ("team#" (5) + 1 digit + "|" (1))
94                let s = ((i - 6) as usize) * 7;
95                &TEAM_NAMES[s..s + 6] // exclude the trailing "|"
96            }
97            i @ 10..=99 => {
98                // length: 8 ("team#" (5) + 2 digits + "|" (1))
99                let s = 28 + ((i - 10) as usize) * 8;
100                &TEAM_NAMES[s..s + 7] // exclude the trailing "|"
101            }
102            i @ 100..=255 => {
103                // length: 9 ("team#" (5) + 3 digits + "|" (1))
104                let s = 748 + ((i - 100) as usize) * 9;
105                &TEAM_NAMES[s..s + 8] // exclude the trailing "|"
106            }
107        }
108    }
109}
110
111impl Team {
112    pub const fn color(self) -> [u8; 3] {
113        static COLORS: [[u8; 3]; 256] = include_bytes!("colors").chunked::<3>();
114        COLORS[self.0 as usize]
115    }
116
117    pub const DERELICT: Team = Team(0);
118    pub const SHARDED: Team = Team(1);
119    pub const CRUX: Team = Team(2);
120    pub const MALIS: Team = Team(3);
121    pub const GREEN: Team = Team(4);
122    pub const BLUE: Team = Team(5);
123    pub const NEOPLASTIC: Team = Team(6);
124}