livesplit_core/run/run_metadata.rs
1use crate::{
2 platform::prelude::*,
3 util::{
4 ordered_map::{Iter, Map},
5 PopulateString,
6 },
7};
8use serde::{Deserialize, Serialize};
9
10/// A custom variable is a key value pair storing additional information about a
11/// run. Unlike the speedrun.com variables, these can be fully custom and don't
12/// need to correspond to anything on speedrun.com. Permanent custom variables
13/// can be specified by the runner. Additionally auto splitters or other sources
14/// may provide temporary custom variables that are not stored in the splits
15/// files.
16#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
17pub struct CustomVariable {
18 /// The current value of the custom variable. This may be provided by the
19 /// runner in the run editor or it may be provided through other means such
20 /// as an auto splitter.
21 pub value: String,
22 /// States whether the variable is permanent. Temporary variables don't get
23 /// stored in splits files. They also don't get shown in the run editor.
24 pub is_permanent: bool,
25}
26
27impl CustomVariable {
28 /// Turns the custom variable into a permanent one. If it already is
29 /// permanent variable, nothing happens.
30 pub fn permanent(&mut self) -> &mut Self {
31 self.is_permanent = true;
32 self
33 }
34
35 /// Sets the value of the custom variable.
36 pub fn set_value<S>(&mut self, value: S)
37 where
38 S: PopulateString,
39 {
40 value.populate(&mut self.value);
41 }
42
43 /// Clears the value of the custom variable. This does not delete the custom
44 /// variable.
45 pub fn clear_value(&mut self) {
46 self.value.clear();
47 }
48}
49
50/// The `RunMetadata` struct stores optional information about a run, like the
51/// platform and region of the game.
52#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
53pub struct RunMetadata {
54 /// The speedrun.com Run ID of the run. You need to ensure that the record
55 /// on speedrun.com matches up with the Personal Best of this run. This may
56 /// be empty if there's no association.
57 pub run_id: String,
58 /// The name of the platform this game is run on. This may be empty if it's
59 /// not specified.
60 pub platform_name: String,
61 /// Specifies whether this speedrun is done on an emulator. Keep in mind
62 /// that `false` may also mean that this information is simply not known.
63 pub uses_emulator: bool,
64 /// The name of the region this game is from. This may be empty if it's not
65 /// specified.
66 pub region_name: String,
67 /// Stores all the speedrun.com variables. A speedrun.com variable is a key
68 /// value pair storing additional information about the category. An example
69 /// of this may be whether Amiibos are used in this category. Use a custom
70 /// variable for storing arbitrary key value pairs that are independent of
71 /// speedrun.com.
72 pub speedrun_com_variables: Map<String>,
73 /// Stores all the custom variables. A custom variable is a key value pair
74 /// storing additional information about a run. Unlike the speedrun.com
75 /// variables, these can be fully custom and don't need to correspond to
76 /// anything on speedrun.com. Permanent custom variables can be specified by
77 /// the runner. Additionally auto splitters or other sources may provide
78 /// temporary custom variables that are not stored in the splits files.
79 pub custom_variables: Map<CustomVariable>,
80}
81
82impl RunMetadata {
83 /// Creates a new empty Run Metadata.
84 #[inline]
85 pub fn new() -> Self {
86 Default::default()
87 }
88
89 /// Accesses the speedrun.com Run ID of the run. This Run ID specify which
90 /// Record on speedrun.com this run is associated with. This should be
91 /// changed once the Personal Best doesn't match up with that record
92 /// anymore. This may be empty if there's no association.
93 #[inline]
94 pub fn run_id(&self) -> &str {
95 &self.run_id
96 }
97
98 /// Sets the speedrun.com Run ID of the run. You need to ensure that the
99 /// record on speedrun.com matches up with the Personal Best of this run.
100 /// This may be empty if there's no association.
101 #[inline]
102 pub fn set_run_id<S>(&mut self, id: S)
103 where
104 S: PopulateString,
105 {
106 id.populate(&mut self.run_id);
107 }
108
109 /// Accesses the name of the platform this game is run on. This may be empty
110 /// if it's not specified.
111 #[inline]
112 pub fn platform_name(&self) -> &str {
113 &self.platform_name
114 }
115
116 /// Sets the name of the platform this game is run on. This may be empty if
117 /// it's not specified.
118 #[inline]
119 pub fn set_platform_name<S>(&mut self, name: S)
120 where
121 S: PopulateString,
122 {
123 name.populate(&mut self.platform_name);
124 }
125
126 /// Returns `true` if this speedrun is done on an emulator. However `false`
127 /// may also indicate that this information is simply not known.
128 #[inline]
129 pub const fn uses_emulator(&self) -> bool {
130 self.uses_emulator
131 }
132
133 /// Specifies whether this speedrun is done on an emulator. Keep in mind
134 /// that `false` may also mean that this information is simply not known.
135 #[inline]
136 pub fn set_emulator_usage(&mut self, uses_emulator: bool) {
137 self.uses_emulator = uses_emulator;
138 }
139
140 /// Accesses the name of the region this game is from. This may be empty if
141 /// it's not specified.
142 #[inline]
143 pub fn region_name(&self) -> &str {
144 &self.region_name
145 }
146
147 /// Sets the name of the region this game is from. This may be empty if it's
148 /// not specified.
149 #[inline]
150 pub fn set_region_name<S>(&mut self, region_name: S)
151 where
152 S: PopulateString,
153 {
154 region_name.populate(&mut self.region_name);
155 }
156
157 /// Sets the speedrun.com variable with the name specified to the value
158 /// specified. A speedrun.com variable is an arbitrary key value pair
159 /// storing additional information about the category. An example of this
160 /// may be whether Amiibos are used in this category. If the variable
161 /// doesn't exist yet, it is being inserted.
162 pub fn set_speedrun_com_variable<N, V>(&mut self, name: N, value: V)
163 where
164 N: PopulateString,
165 V: PopulateString,
166 {
167 let entry = self.speedrun_com_variables.entry(name).or_default();
168 value.populate(entry);
169 }
170
171 /// Removes the speedrun.com variable with the name specified.
172 pub fn remove_speedrun_com_variable(&mut self, name: &str) {
173 self.speedrun_com_variables.shift_remove(name);
174 }
175
176 /// Returns an iterator iterating over all the speedrun.com variables and
177 /// their values that have been specified.
178 pub fn speedrun_com_variables(&self) -> Iter<'_, String> {
179 self.speedrun_com_variables.iter()
180 }
181
182 /// Accesses the custom variable with the name specified if there is one.
183 pub fn custom_variable(&self, name: &str) -> Option<&CustomVariable> {
184 self.custom_variables.get(name)
185 }
186
187 /// Accesses the value of the custom variable with the name specified if
188 /// there is one.
189 pub fn custom_variable_value(&self, name: &str) -> Option<&str> {
190 Some(&self.custom_variable(name)?.value)
191 }
192
193 /// Mutably accesses the custom variable with the name specified. If the
194 /// variable does not exist, it gets created as a temporary variable.
195 pub fn custom_variable_mut<S>(&mut self, name: S) -> &mut CustomVariable
196 where
197 S: PopulateString,
198 {
199 self.custom_variables.entry(name).or_default()
200 }
201
202 /// Removes the custom variable with the name specified. Nothing happens if
203 /// the variable does not exist.
204 pub fn remove_custom_variable(&mut self, name: &str) {
205 self.custom_variables.shift_remove(name);
206 }
207
208 /// Returns an iterator iterating over all the custom variables and their
209 /// values. This includes both temporary and permanent variables.
210 pub fn custom_variables(&self) -> Iter<'_, CustomVariable> {
211 self.custom_variables.iter()
212 }
213
214 /// Resets all the Metadata Information.
215 pub fn clear(&mut self) {
216 self.run_id.clear();
217 self.platform_name.clear();
218 self.region_name.clear();
219 self.uses_emulator = false;
220 self.speedrun_com_variables.clear();
221 self.custom_variables.clear();
222 }
223}