livesplit_core/component/
possible_time_save.rs1use super::key_value;
8use crate::{
9 analysis::possible_time_save,
10 comparison,
11 platform::prelude::*,
12 settings::{Color, Field, Gradient, SettingsDescription, Value},
13 timing::{
14 formatter::{Accuracy, SegmentTime, TimeFormatter},
15 Snapshot,
16 },
17 TimerPhase,
18};
19use alloc::borrow::Cow;
20use core::fmt::Write as FmtWrite;
21use serde::{Deserialize, Serialize};
22
23#[derive(Default, Clone)]
28pub struct Component {
29 settings: Settings,
30}
31
32#[derive(Clone, Serialize, Deserialize)]
34#[serde(default)]
35pub struct Settings {
36 pub background: Gradient,
38 pub comparison_override: Option<String>,
41 pub display_two_rows: bool,
44 pub total_possible_time_save: bool,
48 pub label_color: Option<Color>,
51 pub value_color: Option<Color>,
54 pub accuracy: Accuracy,
56}
57
58impl Default for Settings {
59 fn default() -> Self {
60 Self {
61 background: key_value::DEFAULT_GRADIENT,
62 comparison_override: None,
63 display_two_rows: false,
64 total_possible_time_save: false,
65 label_color: None,
66 value_color: None,
67 accuracy: Accuracy::Hundredths,
68 }
69 }
70}
71
72impl Component {
73 pub fn new() -> Self {
75 Default::default()
76 }
77
78 pub const fn with_settings(settings: Settings) -> Self {
80 Self { settings }
81 }
82
83 pub const fn settings(&self) -> &Settings {
85 &self.settings
86 }
87
88 pub fn settings_mut(&mut self) -> &mut Settings {
90 &mut self.settings
91 }
92
93 pub fn name(&self) -> Cow<'static, str> {
95 self.text(
96 self.settings
97 .comparison_override
98 .as_ref()
99 .map(String::as_ref),
100 )
101 }
102
103 fn text(&self, comparison: Option<&str>) -> Cow<'static, str> {
104 let text = if self.settings.total_possible_time_save {
105 "Total Possible Time Save"
106 } else {
107 "Possible Time Save"
108 };
109 let mut text = Cow::from(text);
110 if let Some(comparison) = comparison {
111 write!(text.to_mut(), " ({})", comparison::shorten(comparison)).unwrap();
112 }
113 text
114 }
115
116 pub fn update_state(&self, state: &mut key_value::State, timer: &Snapshot<'_>) {
118 let segment_index = timer.current_split_index();
119 let current_phase = timer.current_phase();
120 let comparison = comparison::resolve(&self.settings.comparison_override, timer);
121 let text = self.text(comparison);
122 let comparison = comparison::or_current(comparison, timer);
123
124 let (time, updates_frequently) = if self.settings.total_possible_time_save {
125 let (time, updates_frequently) =
126 possible_time_save::calculate_total(timer, segment_index.unwrap_or(0), comparison);
127 (Some(time), updates_frequently)
128 } else if current_phase == TimerPhase::Running || current_phase == TimerPhase::Paused {
129 possible_time_save::calculate(timer, segment_index.unwrap(), comparison, false)
130 } else {
131 (None, false)
132 };
133
134 state.background = self.settings.background;
135 state.key_color = self.settings.label_color;
136 state.value_color = self.settings.value_color;
137 state.semantic_color = Default::default();
138
139 state.key.clear();
140 state.key.push_str(&text); state.value.clear();
143 let _ = write!(
144 state.value,
145 "{}",
146 SegmentTime::with_accuracy(self.settings.accuracy).format(time)
147 );
148
149 state.key_abbreviations.clear();
150 if self.settings.total_possible_time_save {
151 state
152 .key_abbreviations
153 .push("Total Possible Time Save".into());
154 }
155 state.key_abbreviations.push("Possible Time Save".into());
156 state.key_abbreviations.push("Poss. Time Save".into());
157 state.key_abbreviations.push("Time Save".into());
158
159 state.display_two_rows = self.settings.display_two_rows;
160 state.updates_frequently = updates_frequently;
161 }
162
163 pub fn state(&self, timer: &Snapshot<'_>) -> key_value::State {
165 let mut state = Default::default();
166 self.update_state(&mut state, timer);
167 state
168 }
169
170 pub fn settings_description(&self) -> SettingsDescription {
173 SettingsDescription::with_fields(vec![
174 Field::new("Background".into(), self.settings.background.into()),
175 Field::new(
176 "Comparison".into(),
177 self.settings.comparison_override.clone().into(),
178 ),
179 Field::new(
180 "Display 2 Rows".into(),
181 self.settings.display_two_rows.into(),
182 ),
183 Field::new(
184 "Show Total Possible Time Save".into(),
185 self.settings.total_possible_time_save.into(),
186 ),
187 Field::new("Label Color".into(), self.settings.label_color.into()),
188 Field::new("Value Color".into(), self.settings.value_color.into()),
189 Field::new("Accuracy".into(), self.settings.accuracy.into()),
190 ])
191 }
192
193 pub fn set_value(&mut self, index: usize, value: Value) {
201 match index {
202 0 => self.settings.background = value.into(),
203 1 => self.settings.comparison_override = value.into(),
204 2 => self.settings.display_two_rows = value.into(),
205 3 => self.settings.total_possible_time_save = value.into(),
206 4 => self.settings.label_color = value.into(),
207 5 => self.settings.value_color = value.into(),
208 6 => self.settings.accuracy = value.into(),
209 _ => panic!("Unsupported Setting Index"),
210 }
211 }
212}