livesplit_core/component/segment_time/
mod.rs1use super::key_value;
7use crate::{
8 analysis::state_helper::comparison_single_segment_time,
9 comparison,
10 platform::prelude::*,
11 settings::{Color, Field, Gradient, SettingsDescription, Value},
12 timing::formatter::{Accuracy, SegmentTime, TimeFormatter},
13 Timer, TimerPhase,
14};
15use alloc::borrow::Cow;
16use core::fmt::Write;
17use serde::{Deserialize, Serialize};
18
19#[cfg(test)]
20mod tests;
21
22#[derive(Default, Clone)]
26pub struct Component {
27 settings: Settings,
28}
29
30#[derive(Clone, Serialize, Deserialize)]
32#[serde(default)]
33pub struct Settings {
34 pub background: Gradient,
36 pub comparison_override: Option<String>,
39 pub display_two_rows: bool,
42 pub label_color: Option<Color>,
45 pub value_color: Option<Color>,
48 pub accuracy: Accuracy,
50}
51
52impl Default for Settings {
53 fn default() -> Self {
54 Self {
55 background: key_value::DEFAULT_GRADIENT,
56 comparison_override: None,
57 display_two_rows: false,
58 label_color: None,
59 value_color: None,
60 accuracy: Accuracy::Hundredths,
61 }
62 }
63}
64
65impl Component {
66 pub fn new() -> Self {
68 Default::default()
69 }
70
71 pub const fn with_settings(settings: Settings) -> Self {
73 Self { settings }
74 }
75
76 pub const fn settings(&self) -> &Settings {
78 &self.settings
79 }
80
81 pub fn settings_mut(&mut self) -> &mut Settings {
83 &mut self.settings
84 }
85
86 pub fn name(&self) -> Cow<'static, str> {
88 self.text(self.settings.comparison_override.as_deref())
89 }
90
91 fn text(&self, comparison: Option<&str>) -> Cow<'static, str> {
92 if let Some(comparison) = comparison {
93 match comparison {
94 comparison::best_segments::NAME => "Best Segment Time".into(),
95 comparison::worst_segments::NAME => "Worst Segment Time".into(),
96 comparison::average_segments::NAME => "Average Segment Time".into(),
97 comparison::median_segments::NAME => "Median Segment Time".into(),
98 comparison::latest_run::NAME => "Latest Segment Time".into(),
99 comparison => format!("Segment Time ({})", comparison::shorten(comparison)).into(),
100 }
101 } else {
102 "Segment Time".into()
103 }
104 }
105
106 pub fn update_state(&self, state: &mut key_value::State, timer: &Timer) {
108 let resolved_comparison = comparison::resolve(&self.settings.comparison_override, timer);
109 let comparison = comparison::or_current(resolved_comparison, timer);
110 let key = self.text(resolved_comparison); let time = catch! {
113 if timer.current_phase() == TimerPhase::Ended {
115 return None;
116 }
117
118 comparison_single_segment_time(
119 timer.run(),
120 timer.current_split_index()?,
121 comparison,
122 timer.current_timing_method(),
123 )?
124 };
125
126 state.background = self.settings.background;
127 state.key_color = self.settings.label_color;
128 state.value_color = self.settings.value_color;
129 state.semantic_color = Default::default();
130
131 state.key.clear();
132 state.key.push_str(&key);
133
134 state.value.clear();
135 let _ = write!(
136 state.value,
137 "{}",
138 SegmentTime::with_accuracy(self.settings.accuracy).format(time),
139 );
140
141 state.key_abbreviations.clear();
142 match &*key {
143 "Best Segment Time" => {
144 state.key_abbreviations.push("Best Seg. Time".into());
145 state.key_abbreviations.push("Best Segment".into());
146 }
147 "Worst Segment Time" => {
148 state.key_abbreviations.push("Worst Seg. Time".into());
149 state.key_abbreviations.push("Worst Segment".into());
150 }
151 "Average Segment Time" => {
152 state.key_abbreviations.push("Average Seg. Time".into());
153 state.key_abbreviations.push("Average Segment".into());
154 }
155 "Median Segment Time" => {
156 state.key_abbreviations.push("Median Seg. Time".into());
157 state.key_abbreviations.push("Median Segment".into());
158 }
159 "Latest Segment Time" => {
160 state.key_abbreviations.push("Latest Seg. Time".into());
161 state.key_abbreviations.push("Latest Segment".into());
162 }
163 "Segment Time" => state.key_abbreviations.push("Seg. Time".into()),
164 _ => {
165 state.key_abbreviations.push("Segment Time".into());
166 state.key_abbreviations.push("Seg. Time".into());
167 }
168 };
169
170 state.display_two_rows = self.settings.display_two_rows;
171 state.updates_frequently = false;
172 }
173
174 pub fn state(&self, timer: &Timer) -> key_value::State {
176 let mut state = Default::default();
177 self.update_state(&mut state, timer);
178 state
179 }
180
181 pub fn settings_description(&self) -> SettingsDescription {
184 SettingsDescription::with_fields(vec![
185 Field::new("Background".into(), self.settings.background.into()),
186 Field::new(
187 "Comparison".into(),
188 self.settings.comparison_override.clone().into(),
189 ),
190 Field::new(
191 "Display 2 Rows".into(),
192 self.settings.display_two_rows.into(),
193 ),
194 Field::new("Label Color".into(), self.settings.label_color.into()),
195 Field::new("Value Color".into(), self.settings.value_color.into()),
196 Field::new("Accuracy".into(), self.settings.accuracy.into()),
197 ])
198 }
199
200 pub fn set_value(&mut self, index: usize, value: Value) {
208 match index {
209 0 => self.settings.background = value.into(),
210 1 => self.settings.comparison_override = value.into(),
211 2 => self.settings.display_two_rows = value.into(),
212 3 => self.settings.label_color = value.into(),
213 4 => self.settings.value_color = value.into(),
214 5 => self.settings.accuracy = value.into(),
215 _ => panic!("Unsupported Setting Index"),
216 }
217 }
218}