1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use fehler::throws;
use serde_derive::Deserialize;
use std::path::Path;
#[derive(Debug, Deserialize)]
pub struct SkillTree {
pub group: Vec<Group>,
pub goal: Option<Vec<Goal>>,
}
#[derive(Debug, Deserialize)]
pub struct Goal {
pub name: String,
pub label: Option<String>,
pub requires: Option<Vec<String>>,
pub href: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct Group {
pub name: String,
pub label: Option<String>,
pub requires: Option<Vec<String>>,
pub items: Vec<Item>,
pub width: Option<f64>,
pub status: Option<Status>,
pub href: Option<String>,
pub header_color: Option<String>,
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct GroupIndex(pub usize);
#[derive(Debug, Deserialize)]
pub struct Item {
pub label: String,
pub href: Option<String>,
pub port: Option<String>,
pub requires: Option<Vec<String>>,
pub status: Option<Status>,
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct ItemIndex(pub usize);
#[derive(Copy, Clone, Debug, Deserialize)]
pub enum Status {
Blocked,
Unassigned,
Assigned,
Complete,
}
impl SkillTree {
#[throws(anyhow::Error)]
pub fn load(path: &Path) -> SkillTree {
let skill_tree_text = std::fs::read_to_string(path)?;
Self::parse(&skill_tree_text)?
}
#[throws(anyhow::Error)]
pub fn parse(text: &str) -> SkillTree {
toml::from_str(text)?
}
#[throws(anyhow::Error)]
pub fn validate(&self) {
for group in &self.group {
group.validate()?;
}
}
pub fn is_goal(&self, name: &str) -> bool {
self.goals().any(|goal| goal.name == name)
}
pub fn goals(&self) -> impl Iterator<Item = &Goal> {
self.goal.iter().flat_map(|v| v.iter())
}
pub fn groups(&self) -> impl Iterator<Item = &Group> {
self.group.iter()
}
}
impl Group {
#[throws(anyhow::Error)]
pub fn validate(&self) {
for item in &self.items {
item.validate()?;
}
}
pub fn items(&self) -> impl Iterator<Item = &Item> {
self.items.iter()
}
}
impl Item {
#[throws(anyhow::Error)]
pub fn validate(&self) {
}
}