From 1610f1827890f8d064ae9c00f15da4b9387b49f1 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Wed, 9 Nov 2022 22:09:05 -0500 Subject: [PATCH 01/44] Refactor API processing to apply settings from single thread and queue API calls instead of locking --- backend/Cargo.lock | 33 +++- backend/Cargo.toml | 8 +- backend/src/api/async_utils.rs | 65 ++++++++ backend/src/api/battery.rs | 62 ++++---- backend/src/api/cpu.rs | 271 ++++++++++++++++++-------------- backend/src/api/general.rs | 153 ++++++++++++------ backend/src/api/gpu.rs | 208 ++++++++++++------------ backend/src/api/handler.rs | 199 +++++++++++++++++++++++ backend/src/api/mod.rs | 2 + backend/src/api/utility.rs | 4 +- backend/src/api_worker.rs | 13 ++ backend/src/consts.rs | 2 +- backend/src/main.rs | 85 +++++----- backend/src/resume_worker.rs | 9 +- backend/src/settings/general.rs | 150 +++++++----------- backend/src/utility.rs | 6 +- package.json | 2 +- 17 files changed, 821 insertions(+), 451 deletions(-) create mode 100644 backend/src/api/async_utils.rs create mode 100644 backend/src/api/handler.rs create mode 100644 backend/src/api_worker.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index d6a68ab..0dfa192 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -38,6 +38,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "async-recursion" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -567,12 +589,14 @@ dependencies = [ [[package]] name = "powertools-rs" -version = "1.0.5" +version = "1.1.0" dependencies = [ + "async-trait", "log", "serde", "serde_json", "simplelog", + "tokio", "usdpl-back", ] @@ -1053,12 +1077,15 @@ dependencies = [ [[package]] name = "usdpl-back" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbbc0781e83ba990f8239142e33173a2d2548701775f3db66702d1af4fd0319a" +checksum = "4ca96dac4ee471e9534940f99cb36f5212cbfaf4e7779eb3ba970d3c511d9583" dependencies = [ + "async-recursion", + "async-trait", "bytes", "hex", + "log", "obfstr", "tokio", "usdpl-core", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 9178f52..9fbf9bd 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,15 +1,19 @@ [package] name = "powertools-rs" -version = "1.0.5" +version = "1.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -usdpl-back = { version = "0.6.0", features = ["blocking"]} +usdpl-back = { version = "0.7.0", features = ["blocking"]} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +# async +tokio = { version = "*", features = ["time"] } +async-trait = { version = "0.1" } + # logging log = "0.4" simplelog = "0.12" diff --git a/backend/src/api/async_utils.rs b/backend/src/api/async_utils.rs new file mode 100644 index 0000000..689ac9b --- /dev/null +++ b/backend/src/api/async_utils.rs @@ -0,0 +1,65 @@ +//use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; + +/*pub struct AsyncIsh Result) + Send + Sync, + SG: (Fn(T) -> T) + Send + Sync + 'static, + TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> { + pub trans_setter: TS, // assumed to be pretty fast + pub set_get: SG, // probably has locks (i.e. slow) + pub trans_getter: TG, // assumed to be pretty fast +} + +#[async_trait::async_trait] +impl Result) + Send + Sync, + SG: (Fn(T) -> T) + Send + Sync + 'static, + TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> + AsyncCallable for AsyncIsh { + async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { + let t_to_set = match (self.trans_setter)(params) { + Ok(t) => t, + Err(e) => return vec![e.into()] + }; + let t_got = match tokio::task::spawn_blocking(|| (self.set_get)(t_to_set)).await { + Ok(t) => t, + Err(e) => return vec![e.to_string().into()], + }; + (self.trans_getter)(t_got) + } +}*/ + +pub struct AsyncIshGetter G) + Send + Sync, + G: (Fn() -> T) + Send + Sync + 'static, + TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> { + pub set_get: Gen, // probably has locks (i.e. slow) + pub trans_getter: TG, // assumed to be pretty fast +} + +#[async_trait::async_trait] +impl G) + Send + Sync, + G: (Fn() -> T) + Send + Sync + 'static, + TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> + AsyncCallable for AsyncIshGetter { + async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType { + let getter = (self.set_get)(); + let t_got = match tokio::task::spawn_blocking(move || getter()).await { + Ok(t) => t, + Err(e) => return vec![e.to_string().into()], + }; + (self.trans_getter)(t_got) + } +} + +pub struct Blocking super::ApiParameterType) + Send + Sync> { + pub func: F, +} + +#[async_trait::async_trait] +impl super::ApiParameterType) + Send + Sync> AsyncCallable for Blocking { + async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { + (self.func)(params) + } +} diff --git a/backend/src/api/battery.rs b/backend/src/api/battery.rs index 6140902..83af197 100644 --- a/backend/src/api/battery.rs +++ b/backend/src/api/battery.rs @@ -1,8 +1,8 @@ -use std::sync::{mpsc::Sender, Arc, Mutex}; +use std::sync::mpsc::{Sender, self}; +use std::sync::Mutex; use usdpl_back::core::serdes::Primitive; -use crate::settings::{Battery, OnSet}; -use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use super::handler::{ApiMessage, BatteryMessage}; /// Current current (ha!) web method pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { @@ -26,22 +26,18 @@ pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType { /// Generate set battery charge rate web method pub fn set_charge_rate( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |rate: f64| + sender.lock() + .unwrap() + .send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(rate as u64)))) + .expect("set_charge_rate send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(new_val)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "battery"); - settings_lock.charge_rate = Some(*new_val as _); - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result( - settings_lock.on_set(), - settings_lock.charge_rate.unwrap(), - ) + if let Some(&Primitive::F64(new_val)) = params_in.get(0) { + setter(new_val); + vec![(new_val).into()] } else { vec!["set_charge_rate missing parameter".into()] } @@ -50,30 +46,28 @@ pub fn set_charge_rate( /// Generate get battery charge rate web method pub fn get_charge_rate( - settings: Arc>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |rate: Option| tx.send(rate).expect("get_charge_rate callback send failed"); + sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeRate(Box::new(callback)))).expect("get_charge_rate send failed"); + rx.recv().expect("get_charge_rate callback recv failed") + }; move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "battery"); - vec![settings_lock - .charge_rate - .map(|x| x.into()) - .unwrap_or(Primitive::Empty)] + vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)] } } /// Generate unset battery charge rate web method pub fn unset_charge_rate( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety - move |_: super::ApiParameterType| { - let mut settings_lock = unwrap_lock(settings.lock(), "battery"); - settings_lock.charge_rate = None; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result(settings_lock.on_set(), true) + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeRate(None))).expect("unset_charge_rate send failed"); + move |_params_in: super::ApiParameterType| { + setter(); + vec![true.into()] } } diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index 47a9243..0e55c4c 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -1,8 +1,11 @@ -use std::sync::{mpsc::Sender, Arc, Mutex}; +use std::sync::mpsc::{Sender, self}; +use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; -use crate::settings::{Cpu, OnSet, SettingError, SettingVariant, MinMax}; -use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use crate::settings::{Cpu, SettingError, SettingVariant, MinMax}; +//use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use super::handler::{ApiMessage, CpuMessage}; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { @@ -20,29 +23,21 @@ pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { /// Generate set CPU online web method pub fn set_cpu_online( - settings: Arc>>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |index: usize, value: bool| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value))).expect("set_cpu_online send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(index)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); - if let Some(cpu) = settings_lock.get_mut(*index as usize) { - if let Some(Primitive::Bool(online)) = params_in.get(1) { - cpu.online = *online; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result( - cpu.on_set(), - cpu.online, - ) - } else { - vec!["set_cpu_online missing parameter 1".into()] - } + if let Some(&Primitive::F64(index)) = params_in.get(0) { + //let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); + if let Some(&Primitive::Bool(online)) = params_in.get(1) { + setter(index as usize, online); + vec![online.into()] } else { - vec!["set_cpu_online cpu index out of bounds".into()] + vec!["set_cpu_online missing parameter 1".into()] } } else { vec!["set_cpu_online missing parameter 0".into()] @@ -51,81 +46,94 @@ pub fn set_cpu_online( } pub fn set_cpus_online( - settings: Arc>>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |values: Vec| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values))).expect("set_cpus_online send failed"); move |params_in: super::ApiParameterType| { let mut result = Vec::with_capacity(params_in.len()); - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); + let mut values = Vec::with_capacity(params_in.len()); for i in 0..params_in.len() { if let Primitive::Bool(online) = params_in[i] { - if let Some(cpu) = settings_lock.get_mut(i) { - cpu.online = online; - match cpu.on_set() { - Ok(_) => result.push(cpu.online.into()), - Err(e) => result.push(e.msg.into()) - } - } + values.push(online); + result.push(online.into()); } else { + values.push(true); result.push(format!("Invalid parameter {}", i).into()) } } - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); + setter(values); result } } -pub fn get_cpus_online( - settings: Arc>>, +/*pub fn get_cpus_online( + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |values: Vec| tx.send(values).expect("get_cpus_online callback send failed"); + sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed"); + rx.recv().expect("get_cpus_online callback recv failed") + }; move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "cpu"); - let mut output = Vec::with_capacity(settings_lock.len()); - for cpu in settings_lock.as_slice() { - output.push(cpu.online.into()); + let result = getter(); + let mut output = Vec::with_capacity(result.len()); + for &status in result.as_slice() { + output.push(status.into()); } output } +}*/ + +pub fn get_cpus_online( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |values: Vec| tx.send(values).expect("get_cpus_online callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed"); + rx.recv().expect("get_cpus_online callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + let mut output = Vec::with_capacity(result.len()); + for &status in result.as_slice() { + output.push(status.into()); + } + output + } + } } pub fn set_clock_limits( - settings: Arc>>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |index: usize, value: MinMax| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, Some(value)))).expect("set_clock_limits send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(index)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); - if let Some(cpu) = settings_lock.get_mut(*index as usize) { - if let Some(Primitive::F64(min)) = params_in.get(1) { - if let Some(Primitive::F64(max)) = params_in.get(2) { - cpu.clock_limits = Some(MinMax { - min: *min as _, - max: *max as _, - }); - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - match cpu.on_set() { - Ok(_) => vec![ - cpu.clock_limits.as_ref().unwrap().min.into(), - cpu.clock_limits.as_ref().unwrap().max.into(), - ], - Err(e) => vec![e.msg.into()] - } - } else { - vec!["set_clock_limits missing parameter 2".into()] - } + if let Some(&Primitive::F64(index)) = params_in.get(0) { + if let Some(&Primitive::F64(min)) = params_in.get(1) { + if let Some(&Primitive::F64(max)) = params_in.get(2) { + setter(index as usize, MinMax {min: min as u64, max: max as u64}); + vec![min.into(), max.into()] } else { - vec!["set_clock_limits missing parameter 1".into()] + vec!["set_clock_limits missing parameter 2".into()] } } else { - vec!["set_clock_limits cpu index out of bounds".into()] + vec!["set_clock_limits missing parameter 1".into()] } } else { vec!["set_clock_limits missing parameter 0".into()] @@ -134,19 +142,21 @@ pub fn set_clock_limits( } pub fn get_clock_limits( - settings: Arc>>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move |index: usize| { + let (tx, rx) = mpsc::channel(); + let callback = move |values: Option>| tx.send(values).expect("get_clock_limits callback send failed"); + sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetClockLimits(index, Box::new(callback)))).expect("get_clock_limits send failed"); + rx.recv().expect("get_clock_limits callback recv failed") + }; move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(index)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); - if let Some(cpu) = settings_lock.get_mut(*index as usize) { - if let Some(min_max) = &cpu.clock_limits { - vec![min_max.min.into(), min_max.max.into()] - } else { - vec![Primitive::Empty, Primitive::Empty] - } + if let Some(&Primitive::F64(index)) = params_in.get(0) { + if let Some(min_max) = getter(index as usize) { + vec![min_max.min.into(), min_max.max.into()] } else { - vec!["get_clock_limits cpu index out of bounds".into()] + vec![Primitive::Empty, Primitive::Empty] } } else { vec!["get_clock_limits missing parameter 0".into()] @@ -155,23 +165,17 @@ pub fn get_clock_limits( } pub fn unset_clock_limits( - settings: Arc>>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |index: usize| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None))).expect("unset_clock_limits send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(index)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); - if let Some(cpu) = settings_lock.get_mut(*index as usize) { - cpu.clock_limits = None; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result(cpu.on_set(), true) - } else { - vec!["get_clock_limits cpu index out of bounds".into()] - } + if let Some(&Primitive::F64(index)) = params_in.get(0) { + setter(index as usize); + vec![true.into()] } else { vec!["get_clock_limits missing parameter 0".into()] } @@ -179,29 +183,20 @@ pub fn unset_clock_limits( } pub fn set_cpu_governor( - settings: Arc>>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |index: usize, governor: String| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor))).expect("set_cpu_governor send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(index)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); - if let Some(cpu) = settings_lock.get_mut(*index as usize) { - if let Some(Primitive::String(governor)) = params_in.get(1) { - cpu.governor = governor.to_owned(); - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result( - cpu.on_set(), - &cpu.governor as &str, - ) - } else { - vec!["set_cpu_governor missing parameter 1".into()] - } + if let Some(&Primitive::F64(index)) = params_in.get(0) { + if let Some(Primitive::String(governor)) = params_in.get(1) { + setter(index as usize, governor.to_owned()); + vec![(governor as &str).into()] } else { - vec!["set_cpu_governor cpu index out of bounds".into()] + vec!["set_cpu_governor missing parameter 1".into()] } } else { vec!["set_cpu_governor missing parameter 0".into()] @@ -209,14 +204,46 @@ pub fn set_cpu_governor( } } +pub fn set_cpus_governors( + sender: Sender, +) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |governors: Vec| + sender.lock() + .unwrap() + .send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors))).expect("set_cpus_governor send failed"); + move |params_in: super::ApiParameterType| { + let mut result = Vec::with_capacity(params_in.len()); + let mut values = Vec::with_capacity(params_in.len()); + for i in 0..params_in.len() { + if let Primitive::String(gov) = ¶ms_in[i] { + values.push(gov.to_owned()); + result.push((gov as &str).into()); + } else { + //values.push(true); + result.push(format!("Invalid parameter {}", i).into()) + } + } + setter(values); + result + } +} + pub fn get_cpu_governors( - settings: Arc>>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |values: Vec| tx.send(values).expect("get_cpu_governors callback send failed"); + sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(callback)))).expect("get_cpu_governors send failed"); + rx.recv().expect("get_cpu_governors callback recv failed") + }; move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "cpu"); - let mut output = Vec::with_capacity(settings_lock.len()); - for cpu in settings_lock.as_slice() { - output.push(cpu.governor.clone().into()); + let result = getter(); + let mut output = Vec::with_capacity(result.len()); + for cpu in result.as_slice() { + output.push(cpu.clone().into()); } output } diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index 4da5021..a0216eb 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -1,29 +1,25 @@ -use std::sync::{mpsc::Sender, Arc, Mutex}; +use std::sync::mpsc::{Sender, self}; +use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; -use crate::settings::{General, Settings, OnSet}; -use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +//use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use super::handler::{ApiMessage, GeneralMessage}; /// Generate set persistent web method pub fn set_persistent( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |pers: bool| + sender.lock() + .unwrap() + .send(ApiMessage::General(GeneralMessage::SetPersistent(pers))).expect("set_persistent send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::Bool(new_val)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "general"); - settings_lock.persistent = *new_val; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - let result = super::utility::map_empty_result( - settings_lock.on_set(), - settings_lock.persistent, - ); - log::debug!("Persistent is now {}", settings_lock.persistent); - result + if let Some(&Primitive::Bool(new_val)) = params_in.get(0) { + setter(new_val); + //log::debug!("Persistent is now {}", settings_lock.persistent); + vec![new_val.into()] } else { vec!["set_persistent missing parameter".into()] } @@ -32,30 +28,34 @@ pub fn set_persistent( /// Generate get persistent save mode web method pub fn get_persistent( - settings: Arc>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |value: bool| tx.send(value).expect("get_persistent callback send failed"); + sender.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetPersistent(Box::new(callback)))).expect("get_persistent send failed"); + rx.recv().expect("get_persistent callback recv failed") + }; move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "general"); - vec![settings_lock - .persistent.into()] + vec![getter().into()] } } /// Generate load app settings from file web method pub fn load_settings( - settings: Settings, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |path: String, name: String| + sender.lock() + .unwrap() + .send(ApiMessage::LoadSettings(path, name)).expect("load_settings send failed"); move |params_in: super::ApiParameterType| { if let Some(Primitive::String(path)) = params_in.get(0) { if let Some(Primitive::String(name)) = params_in.get(1) { - match settings.load_file(path.into(), name.to_owned(), false) { - Err(e) => vec![e.msg.into()], - Ok(success) => - super::utility::map_empty_result( - settings.clone().on_set(), - success - ) - } + setter(path.to_owned(), name.to_owned()); + vec![true.into()] } else { vec!["load_settings missing name parameter".into()] } @@ -68,10 +68,17 @@ pub fn load_settings( /// Generate load default settings from file web method pub fn load_default_settings( - settings: Settings, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || + sender.lock() + .unwrap() + .send(ApiMessage::LoadMainSettings).expect("load_default_settings send failed"); move |_: super::ApiParameterType| { - match settings.load_file( + setter(); + vec![true.into()] + /*match settings.load_file( crate::consts::DEFAULT_SETTINGS_FILE.into(), crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), true @@ -81,32 +88,76 @@ pub fn load_default_settings( settings.clone().on_set(), success ) - } + }*/ } } -/// Generate get current settings name -pub fn get_name( - settings: Arc>, +/// Generate load system default settings from file web method +pub fn load_system_settings( + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || + sender.lock() + .unwrap() + .send(ApiMessage::LoadSystemSettings).expect("load_default_settings send failed"); move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "general"); - vec![settings_lock - .name - .clone() - .into()] + setter(); + vec![true.into()] + /*match settings.load_file( + crate::consts::DEFAULT_SETTINGS_FILE.into(), + crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + true + ) { + Err(e) => vec![e.msg.into()], + Ok(success) => super::utility::map_empty_result( + settings.clone().on_set(), + success + ) + }*/ + } +} + +/// Generate get current settings name +pub fn get_name( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |name: String| tx.send(name).expect("get_name callback send failed"); + sender2.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetCurrentProfileName(Box::new(callback)))).expect("get_name send failed"); + rx.recv().expect("get_name callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + vec![result.into()] + } } } /// Generate wait for all locks to be available web method pub fn lock_unlock_all( - settings: Settings, -) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - move |_: super::ApiParameterType| { - let _lock = unwrap_lock(settings.general.lock(), "general"); - let _lock = unwrap_lock(settings.cpus.lock(), "cpus"); - let _lock = unwrap_lock(settings.gpu.lock(), "gpu"); - let _lock = unwrap_lock(settings.battery.lock(), "battery"); - vec![true.into()] + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |x| tx.send(x).expect("lock_unlock_all callback send failed"); + sender2.lock().unwrap().send(ApiMessage::WaitForEmptyQueue(Box::new(callback))).expect("lock_unlock_all send failed"); + rx.recv().expect("lock_unlock_all callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |_| { + vec![true.into()] + } } } diff --git a/backend/src/api/gpu.rs b/backend/src/api/gpu.rs index 5ff5fd3..e23ba85 100644 --- a/backend/src/api/gpu.rs +++ b/backend/src/api/gpu.rs @@ -1,31 +1,25 @@ -use std::sync::{mpsc::Sender, Arc, Mutex}; +use std::sync::mpsc::{Sender, self}; +use std::sync::{Mutex, Arc}; use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; -use crate::settings::{Gpu, OnSet, MinMax}; -use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use crate::settings::MinMax; +//use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use super::handler::{ApiMessage, GpuMessage}; pub fn set_ppt( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |fast: u64, slow: u64| + sender.lock() + .unwrap() + .send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow)))).expect("set_ppt send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(fast_ppt)) = params_in.get(0) { - if let Some(Primitive::F64(slow_ppt)) = params_in.get(1) { - let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); - settings_lock.fast_ppt = Some(*fast_ppt as u64); - settings_lock.slow_ppt = Some(*slow_ppt as u64); - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - match settings_lock.on_set() { - Ok(_) => vec![ - settings_lock.fast_ppt.unwrap().into(), - settings_lock.slow_ppt.unwrap().into() - ], - Err(e) => vec![e.msg.into()], - } + if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) { + if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) { + setter(fast_ppt as u64, slow_ppt as u64); + vec![(fast_ppt as u64).into(), (slow_ppt as u64).into()] } else { vec!["set_ppt missing parameter 1".into()] } @@ -36,60 +30,59 @@ pub fn set_ppt( } pub fn get_ppt( - settings: Arc>, -) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "gpu"); - let fast_ppt = settings_lock.fast_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty); - let slow_ppt = settings_lock.slow_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty); - vec![fast_ppt, slow_ppt] + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |ppt: (Option, Option)| tx.send(ppt).expect("get_ppt callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback)))).expect("get_ppt send failed"); + rx.recv().expect("get_ppt callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |(fast, slow): (Option, Option)| { + vec![ + fast.map(|x| x.into()).unwrap_or(Primitive::Empty), + slow.map(|x| x.into()).unwrap_or(Primitive::Empty), + ] + } } } pub fn unset_ppt( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || + sender.lock() + .unwrap() + .send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None))).expect("set_ppt send failed"); move |_: super::ApiParameterType| { - let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); - settings_lock.fast_ppt = None; - settings_lock.slow_ppt = None; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result( - settings_lock.on_set(), - Primitive::Empty, - ) + setter(); + vec![true.into()] } } pub fn set_clock_limits( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |value: MinMax| + sender.lock() + .unwrap() + .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value)))).expect("set_clock_limits send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::F64(min)) = params_in.get(0) { - if let Some(Primitive::F64(max)) = params_in.get(1) { - let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); - settings_lock.clock_limits = Some(MinMax { - min: *min as _, - max: *max as _, + if let Some(&Primitive::F64(min)) = params_in.get(0) { + if let Some(&Primitive::F64(max)) = params_in.get(1) { + setter(MinMax { + min: min as _, + max: max as _, }); - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - match settings_lock.on_set() { - Ok(_) => vec![ - settings_lock.clock_limits.as_ref().unwrap().min.into(), - settings_lock.clock_limits.as_ref().unwrap().max.into(), - ], - Err(e) => vec![e.msg.into()] - } + vec![(min as u64).into(), (max as u64).into()] } else { vec!["set_clock_limits missing parameter 1".into()] } @@ -100,51 +93,54 @@ pub fn set_clock_limits( } pub fn get_clock_limits( - settings: Arc>, -) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "gpu"); - if let Some(min_max) = &settings_lock.clock_limits { - vec![min_max.min.into(), min_max.max.into()] - } else { - vec![Primitive::Empty, Primitive::Empty] + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move|| { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |clocks: Option>| tx.send(clocks).expect("get_clock_limits callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new(callback)))).expect("get_clock_limits send failed"); + rx.recv().expect("get_clock_limits callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |clocks: Option>| { + clocks.map(|x| vec![ + x.min.into(), x.max.into() + ]).unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty]) } } } pub fn unset_clock_limits( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || + sender.lock() + .unwrap() + .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None))).expect("unset_clock_limits send failed"); move |_: super::ApiParameterType| { - let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); - settings_lock.clock_limits = None; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result(settings_lock.on_set(), true) + setter(); + vec![true.into()] } } pub fn set_slow_memory( - settings: Arc>, - saver: Sender<()>, + sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |value: bool| + sender.lock() + .unwrap() + .send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value))).expect("unset_clock_limits send failed"); move |params_in: super::ApiParameterType| { - if let Some(Primitive::Bool(memory_is_slow)) = params_in.get(0) { - let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); - settings_lock.slow_memory = *memory_is_slow; - unwrap_maybe_fatal( - unwrap_lock(saver.lock(), "save channel").send(()), - "Failed to send on save channel", - ); - super::utility::map_empty_result( - settings_lock.on_set(), - settings_lock.slow_memory, - ) + if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) { + setter(memory_is_slow); + vec![memory_is_slow.into()] } else { vec!["set_slow_memory missing parameter 0".into()] } @@ -152,10 +148,22 @@ pub fn set_slow_memory( } pub fn get_slow_memory( - settings: Arc>, -) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { - move |_: super::ApiParameterType| { - let settings_lock = unwrap_lock(settings.lock(), "cpu"); - vec![settings_lock.slow_memory.into()] + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |value: bool| tx.send(value).expect("get_slow_memory callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(callback)))).expect("get_slow_memory send failed"); + rx.recv().expect("get_slow_memory callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |value: bool| { + vec![value.into()] + } } } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs new file mode 100644 index 0000000..46d6bd2 --- /dev/null +++ b/backend/src/api/handler.rs @@ -0,0 +1,199 @@ +use std::sync::mpsc::{self, Receiver, Sender}; + +use crate::settings::{Settings, Cpu, Gpu, Battery, General, OnSet, OnResume, MinMax}; +use crate::persist::SettingsJson; +use crate::utility::unwrap_maybe_fatal; + +type Callback = Box; + +pub enum ApiMessage { + Battery(BatteryMessage), + Cpu(CpuMessage), + Gpu(GpuMessage), + General(GeneralMessage), + OnResume, + WaitForEmptyQueue(Callback<()>), + LoadSettings(String, String), // (path, name) + LoadMainSettings, + LoadSystemSettings, +} + +pub enum BatteryMessage { + SetChargeRate(Option), + GetChargeRate(Callback>), +} + +impl BatteryMessage { + fn process(self, settings: &mut Battery) { + match self { + Self::SetChargeRate(rate) => settings.charge_rate = rate, + Self::GetChargeRate(cb) => cb(settings.charge_rate), + } + } +} + +pub enum CpuMessage { + SetCpuOnline(usize, bool), + SetCpusOnline(Vec), + GetCpusOnline(Callback>), + SetClockLimits(usize, Option>), + GetClockLimits(usize, Callback>>), + SetCpuGovernor(usize, String), + SetCpusGovernor(Vec), + GetCpusGovernor(Callback>), +} + +impl CpuMessage { + fn process(self, settings: &mut Vec) { + match self { + Self::SetCpuOnline(index, status) => {settings.get_mut(index).map(|c| c.online = status);}, + Self::SetCpusOnline(cpus) => { + for i in 0..cpus.len() { + settings.get_mut(i).map(|c| c.online = cpus[i]); + } + }, + Self::GetCpusOnline(cb) => { + let mut result = Vec::with_capacity(settings.len()); + for cpu in settings { + result.push(cpu.online); + } + cb(result); + }, + Self::SetClockLimits(index, clocks) => {settings.get_mut(index).map(|c| c.clock_limits = clocks);}, + Self::GetClockLimits(index, cb) => {settings.get(index).map(|c| cb(c.clock_limits.clone()));}, + Self::SetCpuGovernor(index, gov) => {settings.get_mut(index).map(|c| c.governor = gov);}, + Self::SetCpusGovernor(govs) => { + for i in 0..govs.len() { + settings.get_mut(i).map(|c| c.governor = govs[i].clone()); + } + }, + Self::GetCpusGovernor(cb) => { + let mut result = Vec::with_capacity(settings.len()); + for cpu in settings { + result.push(cpu.governor.clone()); + } + cb(result); + } + } + } +} + +pub enum GpuMessage { + SetPpt(Option, Option), // (fast, slow) + GetPpt(Callback<(Option, Option)>), + SetClockLimits(Option>), + GetClockLimits(Callback>>), + SetSlowMemory(bool), + GetSlowMemory(Callback), +} + +impl GpuMessage { + fn process(self, settings: &mut Gpu) { + match self { + Self::SetPpt(fast, slow) => { + settings.fast_ppt = fast; + settings.slow_ppt = slow; + }, + Self::GetPpt(cb) => cb((settings.fast_ppt, settings.slow_ppt)), + Self::SetClockLimits(clocks) => settings.clock_limits = clocks, + Self::GetClockLimits(cb) => cb(settings.clock_limits.clone()), + Self::SetSlowMemory(val) => settings.slow_memory = val, + Self::GetSlowMemory(cb) => cb(settings.slow_memory), + } + } +} + +pub enum GeneralMessage { + SetPersistent(bool), + GetPersistent(Callback), + GetCurrentProfileName(Callback), +} + +impl GeneralMessage { + fn process(self, settings: &mut General) { + match self { + Self::SetPersistent(val) => settings.persistent = val, + Self::GetPersistent(cb) => cb(settings.persistent), + Self::GetCurrentProfileName(cb) => cb(settings.name.clone()), + } + } +} + +pub struct ApiMessageHandler { + intake: Receiver, + on_empty: Vec>, +} + +impl ApiMessageHandler { + pub fn process_forever(&mut self, settings: &mut Settings) { + while let Ok(msg) = self.intake.recv() { + self.process(settings, msg); + while let Ok(msg) = self.intake.try_recv() { + self.process(settings, msg); + } + // run on_set + if let Err(e) = settings.on_set() { + log::error!("Settings on_set() err: {}", e); + } + // do callbacks + for func in self.on_empty.drain(..) { + func(()); + } + // save + log::debug!("api_worker is saving..."); + let is_persistent = settings.general.persistent; + if is_persistent { + let save_path = crate::utility::settings_dir() + .join(settings.general.path.clone()); + let settings_clone = settings.clone(); + let save_json: SettingsJson = settings_clone.into(); + unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); + log::debug!("Saved settings to {}", save_path.display()); + } else { + log::debug!("Ignored save request for non-persistent settings"); + } + } + } + + pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) { + match message { + ApiMessage::Battery(x) => x.process(&mut settings.battery), + ApiMessage::Cpu(x) => x.process(&mut settings.cpus), + ApiMessage::Gpu(x) => x.process(&mut settings.gpu), + ApiMessage::General(x) => x.process(&mut settings.general), + ApiMessage::OnResume => { + if let Err(e) = settings.on_resume() { + log::error!("Settings on_resume() err: {}", e); + } + } + ApiMessage::WaitForEmptyQueue(callback) => self.on_empty.push(callback), + ApiMessage::LoadSettings(path, name) => { + match settings.load_file(path.into(), name, false) { + Ok(success) => log::info!("Loaded settings file? {}", success), + Err(e) => log::warn!("Load file err: {}", e), + } + } + ApiMessage::LoadMainSettings => { + match settings.load_file( + crate::consts::DEFAULT_SETTINGS_FILE.into(), + crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + true + ) { + Ok(success) => log::info!("Loaded main settings file? {}", success), + Err(e) => log::warn!("Load file err: {}", e), + } + } + ApiMessage::LoadSystemSettings => { + settings.load_system_default(); + } + } + } + + pub fn new() -> (Self, Sender) { + let (tx, rx) = mpsc::channel(); + (Self { + intake: rx, + on_empty: Vec::with_capacity(4), + }, tx) + } +} diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs index 75e2a6d..03412a8 100644 --- a/backend/src/api/mod.rs +++ b/backend/src/api/mod.rs @@ -2,6 +2,8 @@ pub mod battery; pub mod cpu; pub mod general; pub mod gpu; +pub mod handler; +mod async_utils; mod utility; pub(super) type ApiParameterType = Vec; diff --git a/backend/src/api/utility.rs b/backend/src/api/utility.rs index c5b4bc0..c797f60 100644 --- a/backend/src/api/utility.rs +++ b/backend/src/api/utility.rs @@ -14,7 +14,7 @@ pub fn map_result>(result: Result) -> super: } } -#[inline] +/*#[inline] pub fn map_empty_result>( result: Result<(), SettingError>, success: T, @@ -26,4 +26,4 @@ pub fn map_empty_result>( vec![e.msg.into()] }, } -} +}*/ diff --git a/backend/src/api_worker.rs b/backend/src/api_worker.rs new file mode 100644 index 0000000..2ddff02 --- /dev/null +++ b/backend/src/api_worker.rs @@ -0,0 +1,13 @@ +use std::thread::{self, JoinHandle}; + +use crate::settings::Settings; +//use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; +use crate::api::handler::ApiMessageHandler; + +pub fn spawn(mut settings: Settings, mut handler: ApiMessageHandler) -> JoinHandle<()> { + thread::spawn(move || { + log::info!("api_worker starting..."); + handler.process_forever(&mut settings); + log::warn!("api_worker completed!"); + }) +} diff --git a/backend/src/consts.rs b/backend/src/consts.rs index 43e23b7..055d0ff 100644 --- a/backend/src/consts.rs +++ b/backend/src/consts.rs @@ -4,4 +4,4 @@ pub const PACKAGE_NAME: &'static str = env!("CARGO_PKG_NAME"); pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION"); pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json"; -pub const DEFAULT_SETTINGS_NAME: &str = "Default"; +pub const DEFAULT_SETTINGS_NAME: &str = "Main"; diff --git a/backend/src/main.rs b/backend/src/main.rs index 66ef8e2..ed9586f 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -6,7 +6,8 @@ mod state; mod consts; use consts::*; mod resume_worker; -mod save_worker; +//mod save_worker; +mod api_worker; mod utility; use settings::OnSet; @@ -49,14 +50,16 @@ fn main() -> Result<(), ()> { log::debug!("Settings: {:?}", loaded_settings); - let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone()); - let _resume_handle = resume_worker::spawn(loaded_settings.clone()); + let (api_handler, api_sender) = crate::api::handler::ApiMessageHandler::new(); + + //let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone()); + let _resume_handle = resume_worker::spawn(api_sender.clone()); if let Err(e) = loaded_settings.on_set() { log::error!("Startup Settings.on_set() error: {}", e); } - Instance::new(PORT) + let instance = Instance::new(PORT) .register("V_INFO", |_: Vec| { vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()] }) @@ -67,107 +70,119 @@ fn main() -> Result<(), ()> { .register("BATTERY_charge_design", api::battery::charge_design) .register( "BATTERY_set_charge_rate", - api::battery::set_charge_rate(loaded_settings.battery.clone(), save_sender.clone()), + api::battery::set_charge_rate(api_sender.clone()), ) .register( "BATTERY_get_charge_rate", - api::battery::get_charge_rate(loaded_settings.battery.clone()), + api::battery::get_charge_rate(api_sender.clone()), ) .register( "BATTERY_unset_charge_rate", - api::battery::unset_charge_rate(loaded_settings.battery.clone(), save_sender.clone()), + api::battery::unset_charge_rate(api_sender.clone()), ) // cpu API functions .register("CPU_count", api::cpu::max_cpus) .register( "CPU_set_online", - api::cpu::set_cpu_online(loaded_settings.cpus.clone(), save_sender.clone()) + api::cpu::set_cpu_online(api_sender.clone()) ) .register( "CPU_set_onlines", - api::cpu::set_cpus_online(loaded_settings.cpus.clone(), save_sender.clone()) + api::cpu::set_cpus_online(api_sender.clone()) ) - .register( + .register_async( "CPU_get_onlines", - api::cpu::get_cpus_online(loaded_settings.cpus.clone()) + api::cpu::get_cpus_online(api_sender.clone()) ) .register( "CPU_set_clock_limits", - api::cpu::set_clock_limits(loaded_settings.cpus.clone(), save_sender.clone()) + api::cpu::set_clock_limits(api_sender.clone()) ) .register( "CPU_get_clock_limits", - api::cpu::get_clock_limits(loaded_settings.cpus.clone()) + api::cpu::get_clock_limits(api_sender.clone()) ) .register( "CPU_unset_clock_limits", - api::cpu::unset_clock_limits(loaded_settings.cpus.clone(), save_sender.clone()) + api::cpu::unset_clock_limits(api_sender.clone()) ) .register( "CPU_set_governor", - api::cpu::set_cpu_governor(loaded_settings.cpus.clone(), save_sender.clone()) + api::cpu::set_cpu_governor(api_sender.clone()) + ) + .register( + "CPU_set_governors", + api::cpu::set_cpus_governors(api_sender.clone()) ) .register( "CPU_get_governors", - api::cpu::get_cpu_governors(loaded_settings.cpus.clone()) + api::cpu::get_cpu_governors(api_sender.clone()) ) // gpu API functions .register( "GPU_set_ppt", - api::gpu::set_ppt(loaded_settings.gpu.clone(), save_sender.clone()) + api::gpu::set_ppt(api_sender.clone()) ) - .register( + .register_async( "GPU_get_ppt", - api::gpu::get_ppt(loaded_settings.gpu.clone()) + api::gpu::get_ppt(api_sender.clone()) ) .register( "GPU_unset_ppt", - api::gpu::unset_ppt(loaded_settings.gpu.clone(), save_sender.clone()) + api::gpu::unset_ppt(api_sender.clone()) ) .register( "GPU_set_clock_limits", - api::gpu::set_clock_limits(loaded_settings.gpu.clone(), save_sender.clone()) + api::gpu::set_clock_limits(api_sender.clone()) ) - .register( + .register_async( "GPU_get_clock_limits", - api::gpu::get_clock_limits(loaded_settings.gpu.clone()) + api::gpu::get_clock_limits(api_sender.clone()) ) .register( "GPU_unset_clock_limits", - api::gpu::unset_clock_limits(loaded_settings.gpu.clone(), save_sender.clone()) + api::gpu::unset_clock_limits(api_sender.clone()) ) .register( "GPU_set_slow_memory", - api::gpu::set_slow_memory(loaded_settings.gpu.clone(), save_sender.clone()) + api::gpu::set_slow_memory(api_sender.clone()) ) - .register( + .register_async( "GPU_get_slow_memory", - api::gpu::get_slow_memory(loaded_settings.gpu.clone()) + api::gpu::get_slow_memory(api_sender.clone()) ) // general API functions .register( "GENERAL_set_persistent", - api::general::set_persistent(loaded_settings.general.clone(), save_sender.clone()) + api::general::set_persistent(api_sender.clone()) ) .register( "GENERAL_get_persistent", - api::general::get_persistent(loaded_settings.general.clone()) + api::general::get_persistent(api_sender.clone()) ) .register( "GENERAL_load_settings", - api::general::load_settings(loaded_settings.clone()) + api::general::load_settings(api_sender.clone()) ) .register( "GENERAL_load_default_settings", - api::general::load_default_settings(loaded_settings.clone()) + api::general::load_default_settings(api_sender.clone()) ) .register( + "GENERAL_load_system_settings", + api::general::load_system_settings(api_sender.clone()) + ) + .register_async( "GENERAL_get_name", - api::general::get_name(loaded_settings.general.clone()) + api::general::get_name(api_sender.clone()) ) - .register( + .register_async( "GENERAL_wait_for_unlocks", - api::general::lock_unlock_all(loaded_settings.clone()) - ) + api::general::lock_unlock_all(api_sender.clone()) + ); + + api_worker::spawn(loaded_settings, api_handler); + + instance .run_blocking() } diff --git a/backend/src/resume_worker.rs b/backend/src/resume_worker.rs index 9560d84..2c9279d 100644 --- a/backend/src/resume_worker.rs +++ b/backend/src/resume_worker.rs @@ -1,12 +1,13 @@ use std::thread::{self, JoinHandle}; use std::time::{Duration, Instant}; +use std::sync::mpsc::Sender; -use crate::settings::{OnResume, Settings}; -use crate::utility::unwrap_maybe_fatal; +use crate::api::handler::ApiMessage; +//use crate::utility::unwrap_maybe_fatal; const ALLOWED_ERROR: f64 = 100.0; // period of 10ms with 100x means sleep has to be >= 1s to be detected -pub fn spawn(settings: Settings) -> JoinHandle<()> { +pub fn spawn(sender: Sender) -> JoinHandle<()> { thread::spawn(move || { log::info!("resume_worker starting..."); let duration = Duration::from_millis(10); // very low so it detects before Steam client does @@ -18,7 +19,7 @@ pub fn spawn(settings: Settings) -> JoinHandle<()> { if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) { // has just resumed from sleep log::info!("Resume detected"); - unwrap_maybe_fatal(settings.on_resume(), "On resume failure"); + sender.send(ApiMessage::OnResume).expect("resume_worker send failed"); log::debug!( "OnResume completed after sleeping for {}s", old_start.as_secs_f32() diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index 5c40ea4..bb3ff17 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -1,11 +1,11 @@ use std::convert::Into; use std::path::PathBuf; -use std::sync::{Arc, Mutex}; +//use std::sync::{Arc, Mutex}; use super::{Battery, Cpu, Gpu}; use super::{OnResume, OnSet, SettingError}; use crate::persist::{CpuJson, SettingsJson}; -use crate::utility::unwrap_lock; +//use crate::utility::unwrap_lock; const LATEST_VERSION: u64 = 0; @@ -43,24 +43,20 @@ impl OnSet for General { #[derive(Debug, Clone)] pub struct Settings { - pub general: Arc>, - pub cpus: Arc>>, - pub gpu: Arc>, - pub battery: Arc>, + pub general: General, + pub cpus: Vec, + pub gpu: Gpu, + pub battery: Battery, } impl OnSet for Settings { fn on_set(&mut self) -> Result<(), SettingError> { - unwrap_lock(self.battery.lock(), "battery").on_set()?; - { - // cpu lock scope - let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); - for cpu in cpu_lock.iter_mut() { - cpu.on_set()?; - } + self.battery.on_set()?; + for cpu in self.cpus.iter_mut() { + cpu.on_set()?; } - unwrap_lock(self.gpu.lock(), "gpu").on_set()?; - unwrap_lock(self.general.lock(), "general").on_set()?; + self.gpu.on_set()?; + self.general.on_set()?; Ok(()) } } @@ -70,24 +66,24 @@ impl Settings { pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self { match other.version { 0 => Self { - general: Arc::new(Mutex::new(General { + general: General { persistent: other.persistent, path: json_path, name: other.name, - })), - cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))), - gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))), - battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))), + }, + cpus: Self::convert_cpus(other.cpus, other.version), + gpu: Gpu::from_json(other.gpu, other.version), + battery: Battery::from_json(other.battery, other.version), }, _ => Self { - general: Arc::new(Mutex::new(General { + general: General { persistent: other.persistent, path: json_path, name: other.name, - })), - cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))), - gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))), - battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))), + }, + cpus: Self::convert_cpus(other.cpus, other.version), + gpu: Gpu::from_json(other.gpu, other.version), + battery: Battery::from_json(other.battery, other.version), }, } } @@ -117,35 +113,26 @@ impl Settings { pub fn system_default(json_path: PathBuf) -> Self { Self { - general: Arc::new(Mutex::new(General { + general: General { persistent: false, path: json_path, name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - })), - cpus: Arc::new(Mutex::new(Cpu::system_default())), - gpu: Arc::new(Mutex::new(Gpu::system_default())), - battery: Arc::new(Mutex::new(Battery::system_default())), + }, + cpus: Cpu::system_default(), + gpu: Gpu::system_default(), + battery: Battery::system_default(), } } - fn load_system_default(&self) { - { - let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); - *cpu_lock = Cpu::system_default(); - } - { - let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu"); - *gpu_lock = Gpu::system_default(); - } - { - let mut battery_lock = unwrap_lock(self.battery.lock(), "battery"); - *battery_lock = Battery::system_default(); - } + pub fn load_system_default(&mut self) { + self.cpus = Cpu::system_default(); + self.gpu = Gpu::system_default(); + self.battery = Battery::system_default(); } - pub fn load_file(&self, filename: PathBuf, name: String, system_defaults: bool) -> Result { + pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result { let json_path = crate::utility::settings_dir().join(filename); - let mut general_lock = unwrap_lock(self.general.lock(), "general"); + //let mut general_lock = unwrap_lock(self.general.lock(), "general"); if json_path.exists() { let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError { msg: e.to_string(), @@ -153,53 +140,38 @@ impl Settings { })?; if !settings_json.persistent { log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display()); - general_lock.persistent = false; - general_lock.name = name; + self.general.persistent = false; + self.general.name = name; } else { - let new_cpus = Self::convert_cpus(settings_json.cpus, settings_json.version); - let new_gpu = Gpu::from_json(settings_json.gpu, settings_json.version); - let new_battery = Battery::from_json(settings_json.battery, settings_json.version); - { - let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); - *cpu_lock = new_cpus; - } - { - let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu"); - *gpu_lock = new_gpu; - } - { - let mut battery_lock = unwrap_lock(self.battery.lock(), "battery"); - *battery_lock = new_battery; - } - general_lock.persistent = true; - general_lock.name = settings_json.name; + self.cpus = Self::convert_cpus(settings_json.cpus, settings_json.version); + self.gpu = Gpu::from_json(settings_json.gpu, settings_json.version); + self.battery = Battery::from_json(settings_json.battery, settings_json.version); + self.general.persistent = true; + self.general.name = settings_json.name; } } else { if system_defaults { self.load_system_default(); } - general_lock.persistent = false; - general_lock.name = name; + self.general.persistent = false; + self.general.name = name; } - general_lock.path = json_path; - Ok(general_lock.persistent) + self.general.path = json_path; + Ok(self.general.persistent) } } impl OnResume for Settings { fn on_resume(&self) -> Result<(), SettingError> { - log::debug!("Locking settings for on_resume"); - unwrap_lock(self.battery.lock(), "battery").on_resume()?; - log::debug!("Got battery lock"); - { - let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); - log::debug!("Got cpus lock"); - for cpu in cpu_lock.iter() { - cpu.on_resume()?; - } + log::debug!("Applying settings for on_resume"); + self.battery.on_resume()?; + log::debug!("Resumed battery"); + for cpu in self.cpus.iter() { + cpu.on_resume()?; } - unwrap_lock(self.gpu.lock(), "gpu").on_resume()?; - log::debug!("Got gpu lock"); + log::debug!("Resumed CPUs"); + self.gpu.on_resume()?; + log::debug!("Resumed GPU"); Ok(()) } } @@ -207,26 +179,18 @@ impl OnResume for Settings { impl Into for Settings { #[inline] fn into(self) -> SettingsJson { - log::debug!("Locking settings to convert into json"); - let gen_lock = unwrap_lock(self.general.lock(), "general"); - log::debug!("Got general lock"); - let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); - log::debug!("Got cpus lock"); - let gpu_lock = unwrap_lock(self.gpu.lock(), "gpu"); - log::debug!("Got gpu lock"); - let batt_lock = unwrap_lock(self.battery.lock(), "battery"); - log::debug!("Got battery lock"); + log::debug!("Converting into json"); SettingsJson { version: LATEST_VERSION, - name: gen_lock.name.clone(), - persistent: gen_lock.persistent, - cpus: cpu_lock + name: self.general.name.clone(), + persistent: self.general.persistent, + cpus: self.cpus .clone() .drain(..) .map(|cpu| cpu.into()) .collect(), - gpu: gpu_lock.clone().into(), - battery: batt_lock.clone().into(), + gpu: self.gpu.clone().into(), + battery: self.battery.clone().into(), } } } diff --git a/backend/src/utility.rs b/backend/src/utility.rs index 1369816..1c1f90c 100644 --- a/backend/src/utility.rs +++ b/backend/src/utility.rs @@ -1,5 +1,5 @@ use std::fmt::Display; -use std::sync::{LockResult, MutexGuard}; +//use std::sync::{LockResult, MutexGuard}; pub fn unwrap_maybe_fatal(result: Result, message: &str) -> T { match result { @@ -11,7 +11,7 @@ pub fn unwrap_maybe_fatal(result: Result, message: & } } -pub fn unwrap_lock<'a, T: Sized>( +/*pub fn unwrap_lock<'a, T: Sized>( result: LockResult>, lock_name: &str, ) -> MutexGuard<'a, T> { @@ -22,7 +22,7 @@ pub fn unwrap_lock<'a, T: Sized>( panic!("Failed to acquire {} lock: {}", lock_name, e); } } -} +}*/ pub fn settings_dir() -> std::path::PathBuf { usdpl_back::api::dirs::home() diff --git a/package.json b/package.json index c35eabe..e811299 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.0.5", + "version": "1.1.0", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", From 01c86eeafef7e6fc4462a82692c80dc679dcf2bb Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 12 Nov 2022 23:17:13 -0500 Subject: [PATCH 02/44] Add some additional APIs endpoints for #48 and more --- backend/src/api/async_utils.rs | 29 +++--- backend/src/api/cpu.rs | 36 +++++++- backend/src/api/handler.rs | 33 ++++--- backend/src/main.rs | 4 + backend/src/settings/cpu.rs | 154 ++++++++++++++++++++++++++------ backend/src/settings/general.rs | 49 +++------- backend/src/settings/mod.rs | 2 +- backend/src/state/cpu.rs | 2 + src/backend.ts | 8 ++ 9 files changed, 224 insertions(+), 93 deletions(-) diff --git a/backend/src/api/async_utils.rs b/backend/src/api/async_utils.rs index 689ac9b..7afdaa6 100644 --- a/backend/src/api/async_utils.rs +++ b/backend/src/api/async_utils.rs @@ -1,33 +1,38 @@ //use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; -/*pub struct AsyncIsh Result) + Send + Sync, - SG: (Fn(T) -> T) + Send + Sync + 'static, - TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> { +pub struct AsyncIsh Result) + Send + Sync, + Gen: (Fn() -> SG) + Send + Sync, + SG: (Fn(In) -> Out) + Send + Sync + 'static, + TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync> { pub trans_setter: TS, // assumed to be pretty fast - pub set_get: SG, // probably has locks (i.e. slow) + pub set_get: Gen, // probably has locks (i.e. slow) pub trans_getter: TG, // assumed to be pretty fast } #[async_trait::async_trait] -impl Result) + Send + Sync, - SG: (Fn(T) -> T) + Send + Sync + 'static, - TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> - AsyncCallable for AsyncIsh { +impl Result) + Send + Sync, + Gen: (Fn() -> SG) + Send + Sync, + SG: (Fn(In) -> Out) + Send + Sync + 'static, + TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync> + AsyncCallable for AsyncIsh { async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { let t_to_set = match (self.trans_setter)(params) { Ok(t) => t, Err(e) => return vec![e.into()] }; - let t_got = match tokio::task::spawn_blocking(|| (self.set_get)(t_to_set)).await { + let setter = (self.set_get)(); + let t_got = match tokio::task::spawn_blocking(move || setter(t_to_set)).await { Ok(t) => t, Err(e) => return vec![e.to_string().into()], }; (self.trans_getter)(t_got) } -}*/ +} pub struct AsyncIshGetter G) + Send + Sync, diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index 0e55c4c..c4c1922 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -3,14 +3,14 @@ use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; -use crate::settings::{Cpu, SettingError, SettingVariant, MinMax}; +use crate::settings::{Cpus, SettingError, SettingVariant, MinMax}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, CpuMessage}; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { super::utility::map_result( - Cpu::cpu_count() + Cpus::cpu_count() .map(|x| x as u64) .ok_or_else( || SettingError { @@ -90,6 +90,38 @@ pub fn set_cpus_online( } }*/ +pub fn set_smt( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move |smt: bool| { + let (tx, rx) = mpsc::channel(); + let callback = move |values: Vec| tx.send(values).expect("set_smt callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::SetSmt(smt, Box::new(callback)))).expect("set_smt send failed"); + rx.recv().expect("set_smt callback recv failed") + } + }; + super::async_utils::AsyncIsh { + trans_setter: |params| { + if let Some(&Primitive::Bool(smt_value)) = params.get(0) { + Ok(smt_value) + } else { + Err("set_smt missing/invalid parameter 0".to_owned()) + } + }, + set_get: getter, + trans_getter: |result| { + let mut output = Vec::with_capacity(result.len()); + for &status in result.as_slice() { + output.push(status.into()); + } + output + } + } +} + pub fn get_cpus_online( sender: Sender, ) -> impl AsyncCallable { diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 46d6bd2..3ceef2e 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -1,6 +1,6 @@ use std::sync::mpsc::{self, Receiver, Sender}; -use crate::settings::{Settings, Cpu, Gpu, Battery, General, OnSet, OnResume, MinMax}; +use crate::settings::{Settings, Cpus, Gpu, Battery, General, OnSet, OnResume, MinMax}; use crate::persist::SettingsJson; use crate::utility::unwrap_maybe_fatal; @@ -35,6 +35,7 @@ impl BatteryMessage { pub enum CpuMessage { SetCpuOnline(usize, bool), SetCpusOnline(Vec), + SetSmt(bool, Callback>), GetCpusOnline(Callback>), SetClockLimits(usize, Option>), GetClockLimits(usize, Callback>>), @@ -44,32 +45,40 @@ pub enum CpuMessage { } impl CpuMessage { - fn process(self, settings: &mut Vec) { + fn process(self, settings: &mut Cpus) { match self { - Self::SetCpuOnline(index, status) => {settings.get_mut(index).map(|c| c.online = status);}, + Self::SetCpuOnline(index, status) => {settings.cpus.get_mut(index).map(|c| c.online = status);}, Self::SetCpusOnline(cpus) => { for i in 0..cpus.len() { - settings.get_mut(i).map(|c| c.online = cpus[i]); + settings.cpus.get_mut(i).map(|c| c.online = cpus[i]); } }, + Self::SetSmt(status, cb) => { + let mut result = Vec::with_capacity(settings.cpus.len()); + for i in 0..settings.cpus.len() { + settings.cpus[i].online = settings.cpus[i].online && (status || i % 2 == 0); + result.push(settings.cpus[i].online); + } + cb(result); + } Self::GetCpusOnline(cb) => { - let mut result = Vec::with_capacity(settings.len()); - for cpu in settings { + let mut result = Vec::with_capacity(settings.cpus.len()); + for cpu in &settings.cpus { result.push(cpu.online); } cb(result); }, - Self::SetClockLimits(index, clocks) => {settings.get_mut(index).map(|c| c.clock_limits = clocks);}, - Self::GetClockLimits(index, cb) => {settings.get(index).map(|c| cb(c.clock_limits.clone()));}, - Self::SetCpuGovernor(index, gov) => {settings.get_mut(index).map(|c| c.governor = gov);}, + Self::SetClockLimits(index, clocks) => {settings.cpus.get_mut(index).map(|c| c.clock_limits = clocks);}, + Self::GetClockLimits(index, cb) => {settings.cpus.get(index).map(|c| cb(c.clock_limits.clone()));}, + Self::SetCpuGovernor(index, gov) => {settings.cpus.get_mut(index).map(|c| c.governor = gov);}, Self::SetCpusGovernor(govs) => { for i in 0..govs.len() { - settings.get_mut(i).map(|c| c.governor = govs[i].clone()); + settings.cpus.get_mut(i).map(|c| c.governor = govs[i].clone()); } }, Self::GetCpusGovernor(cb) => { - let mut result = Vec::with_capacity(settings.len()); - for cpu in settings { + let mut result = Vec::with_capacity(settings.cpus.len()); + for cpu in &settings.cpus { result.push(cpu.governor.clone()); } cb(result); diff --git a/backend/src/main.rs b/backend/src/main.rs index ed9586f..aa53e00 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -94,6 +94,10 @@ fn main() -> Result<(), ()> { "CPU_get_onlines", api::cpu::get_cpus_online(api_sender.clone()) ) + .register_async( + "CPU_set_smt", + api::cpu::set_smt(api_sender.clone()) + ) .register( "CPU_set_clock_limits", api::cpu::set_clock_limits(api_sender.clone()) diff --git a/backend/src/settings/cpu.rs b/backend/src/settings/cpu.rs index dd27ab7..b2d1efe 100644 --- a/backend/src/settings/cpu.rs +++ b/backend/src/settings/cpu.rs @@ -4,6 +4,131 @@ use super::MinMax; use super::{OnResume, OnSet, SettingError, SettingsRange}; use crate::persist::CpuJson; +const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; +const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; + +#[derive(Debug, Clone)] +pub struct Cpus { + pub cpus: Vec, + pub smt: bool, + pub smt_capable: bool, +} + +impl OnSet for Cpus { + fn on_set(&mut self) -> Result<(), SettingError> { + if self.smt_capable { + // toggle SMT + if self.smt { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `on` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: super::SettingVariant::Cpu, + } + })?; + } else { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `off` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: super::SettingVariant::Cpu, + } + })?; + } + } + for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { + cpu.state.do_set_online = self.smt || i % 2 == 0; + cpu.on_set()?; + } + Ok(()) + } +} + +impl OnResume for Cpus { + fn on_resume(&self) -> Result<(), SettingError> { + for cpu in &self.cpus { + cpu.on_resume()?; + } + Ok(()) + } +} + +impl Cpus { + pub fn cpu_count() -> Option { + let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) + .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); + if let Some(dash_index) = data.find('-') { + let data = data.split_off(dash_index + 1); + if let Ok(max_cpu) = data.parse::() { + return Some(max_cpu + 1); + } + } + log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); + None + } + + fn system_smt_capabilities() -> (bool, bool) { + match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { + Ok(val) => (val.trim().to_lowercase() == "on", true), + Err(_) => (false, false) + } + } + + pub fn system_default() -> Self { + if let Some(max_cpu) = Self::cpu_count() { + let mut sys_cpus = Vec::with_capacity(max_cpu); + for i in 0..max_cpu { + sys_cpus.push(Cpu::from_sys(i)); + } + let (smt_status, can_smt) = Self::system_smt_capabilities(); + Self { + cpus: sys_cpus, + smt: smt_status, + smt_capable: can_smt, + } + } else { + Self { + cpus: vec![], + smt: false, + smt_capable: false, + } + } + } + + #[inline] + pub fn from_json(mut other: Vec, version: u64) -> Self { + let (_, can_smt) = Self::system_smt_capabilities(); + let mut result = Vec::with_capacity(other.len()); + let max_cpus = Self::cpu_count(); + for (i, cpu) in other.drain(..).enumerate() { + // prevent having more CPUs than available + if let Some(max_cpus) = max_cpus { + if i == max_cpus { + break; + } + } + result.push(Cpu::from_json(cpu, version, i)); + } + if let Some(max_cpus) = max_cpus { + if result.len() != max_cpus { + let mut sys_cpus = Cpus::system_default(); + for i in result.len()..sys_cpus.cpus.len() { + result.push(sys_cpus.cpus.remove(i)); + } + } + } + Self { + cpus: result, + smt: true, + smt_capable: can_smt, + } + } +} + #[derive(Debug, Clone)] pub struct Cpu { pub online: bool, @@ -16,8 +141,6 @@ pub struct Cpu { const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; const CPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; -const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; - impl Cpu { #[inline] pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { @@ -41,7 +164,7 @@ impl Cpu { fn set_all(&mut self) -> Result<(), SettingError> { // set cpu online/offline - if self.index != 0 { // cpu0 cannot be disabled + if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled let online_path = cpu_online_path(self.index); usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { SettingError { @@ -162,31 +285,6 @@ impl Cpu { state: crate::state::Cpu::default(), } } - - pub fn cpu_count() -> Option { - let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) - .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); - if let Some(dash_index) = data.find('-') { - let data = data.split_off(dash_index + 1); - if let Ok(max_cpu) = data.parse::() { - return Some(max_cpu + 1); - } - } - log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); - None - } - - pub fn system_default() -> Vec { - if let Some(max_cpu) = Self::cpu_count() { - let mut cpus = Vec::with_capacity(max_cpu); - for i in 0..max_cpu { - cpus.push(Self::from_sys(i)); - } - cpus - } else { - Vec::with_capacity(0) - } - } } impl Into for Cpu { diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index bb3ff17..fb95f52 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -2,9 +2,9 @@ use std::convert::Into; use std::path::PathBuf; //use std::sync::{Arc, Mutex}; -use super::{Battery, Cpu, Gpu}; +use super::{Battery, Cpus, Gpu}; use super::{OnResume, OnSet, SettingError}; -use crate::persist::{CpuJson, SettingsJson}; +use crate::persist::SettingsJson; //use crate::utility::unwrap_lock; const LATEST_VERSION: u64 = 0; @@ -44,7 +44,7 @@ impl OnSet for General { #[derive(Debug, Clone)] pub struct Settings { pub general: General, - pub cpus: Vec, + pub cpus: Cpus, pub gpu: Gpu, pub battery: Battery, } @@ -52,9 +52,7 @@ pub struct Settings { impl OnSet for Settings { fn on_set(&mut self) -> Result<(), SettingError> { self.battery.on_set()?; - for cpu in self.cpus.iter_mut() { - cpu.on_set()?; - } + self.cpus.on_set()?; self.gpu.on_set()?; self.general.on_set()?; Ok(()) @@ -71,7 +69,7 @@ impl Settings { path: json_path, name: other.name, }, - cpus: Self::convert_cpus(other.cpus, other.version), + cpus: Cpus::from_json(other.cpus, other.version), gpu: Gpu::from_json(other.gpu, other.version), battery: Battery::from_json(other.battery, other.version), }, @@ -81,36 +79,13 @@ impl Settings { path: json_path, name: other.name, }, - cpus: Self::convert_cpus(other.cpus, other.version), + cpus: Cpus::from_json(other.cpus, other.version), gpu: Gpu::from_json(other.gpu, other.version), battery: Battery::from_json(other.battery, other.version), }, } } - fn convert_cpus(mut cpus: Vec, version: u64) -> Vec { - let mut result = Vec::with_capacity(cpus.len()); - let max_cpus = Cpu::cpu_count(); - for (i, cpu) in cpus.drain(..).enumerate() { - // prevent having more CPUs than available - if let Some(max_cpus) = max_cpus { - if i == max_cpus { - break; - } - } - result.push(Cpu::from_json(cpu, version, i)); - } - if let Some(max_cpus) = max_cpus { - if result.len() != max_cpus { - let mut sys_cpus = Cpu::system_default(); - for i in result.len()..sys_cpus.len() { - result.push(sys_cpus.remove(i)); - } - } - } - result - } - pub fn system_default(json_path: PathBuf) -> Self { Self { general: General { @@ -118,14 +93,14 @@ impl Settings { path: json_path, name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), }, - cpus: Cpu::system_default(), + cpus: Cpus::system_default(), gpu: Gpu::system_default(), battery: Battery::system_default(), } } pub fn load_system_default(&mut self) { - self.cpus = Cpu::system_default(); + self.cpus = Cpus::system_default(); self.gpu = Gpu::system_default(); self.battery = Battery::system_default(); } @@ -143,7 +118,7 @@ impl Settings { self.general.persistent = false; self.general.name = name; } else { - self.cpus = Self::convert_cpus(settings_json.cpus, settings_json.version); + self.cpus = Cpus::from_json(settings_json.cpus, settings_json.version); self.gpu = Gpu::from_json(settings_json.gpu, settings_json.version); self.battery = Battery::from_json(settings_json.battery, settings_json.version); self.general.persistent = true; @@ -166,9 +141,7 @@ impl OnResume for Settings { log::debug!("Applying settings for on_resume"); self.battery.on_resume()?; log::debug!("Resumed battery"); - for cpu in self.cpus.iter() { - cpu.on_resume()?; - } + self.cpus.on_resume()?; log::debug!("Resumed CPUs"); self.gpu.on_resume()?; log::debug!("Resumed GPU"); @@ -184,7 +157,7 @@ impl Into for Settings { version: LATEST_VERSION, name: self.general.name.clone(), persistent: self.general.persistent, - cpus: self.cpus + cpus: self.cpus.cpus .clone() .drain(..) .map(|cpu| cpu.into()) diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 9f327af..2cef68c 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -7,7 +7,7 @@ mod min_max; mod traits; pub use battery::Battery; -pub use cpu::Cpu; +pub use cpu::{Cpu, Cpus}; pub use general::{SettingVariant, Settings, General}; pub use gpu::Gpu; pub use min_max::MinMax; diff --git a/backend/src/state/cpu.rs b/backend/src/state/cpu.rs index e122115..54b423f 100644 --- a/backend/src/state/cpu.rs +++ b/backend/src/state/cpu.rs @@ -2,6 +2,7 @@ pub struct Cpu { pub clock_limits_set: bool, pub is_resuming: bool, + pub do_set_online: bool, } impl std::default::Default for Cpu { @@ -9,6 +10,7 @@ impl std::default::Default for Cpu { Self { clock_limits_set: false, is_resuming: false, + do_set_online: true, } } } diff --git a/src/backend.ts b/src/backend.ts index 29d53b8..e2c5746 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -62,6 +62,10 @@ export async function unsetBatteryChargeRate(): Promise { // CPU +export async function setCpuSmt(status: boolean): Promise { + return (await call_backend("CPU_set_smt", [status]))[0]; +} + export async function getCpuCount(): Promise { return (await call_backend("CPU_count", []))[0]; } @@ -150,6 +154,10 @@ export async function loadGeneralDefaultSettings(): Promise { return (await call_backend("GENERAL_load_default_settings", []))[0]; } +export async function loadGeneralSystemSettings(): Promise { + return (await call_backend("GENERAL_load_system_settings", []))[0]; +} + export async function getGeneralSettingsName(): Promise { return (await call_backend("GENERAL_get_name", []))[0]; } From 1a49516d5130cd06502e281eb8b9a967c68e56e4 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 12 Nov 2022 23:37:54 -0500 Subject: [PATCH 03/44] Make Persistent description a bit more self-evident, as requested by sentient burger conglomerate --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 91f9547..16b39f9 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -550,7 +550,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { { console.debug("Persist is now " + persist.toString()); backend.resolve( From d6196c6dad480ff3b68ac61a93407073c8335fdd Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 13 Nov 2022 12:41:45 -0500 Subject: [PATCH 04/44] Add new API calls to front-end for #44 and #48 and improve resolve's type '''safety''' --- src/backend.ts | 6 +++--- src/index.tsx | 30 +++++++++++++++++------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/backend.ts b/src/backend.ts index e2c5746..2e50f60 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -4,7 +4,7 @@ const USDPL_PORT: number = 44443; // Utility -export function resolve(promise: Promise, setter: any) { +export function resolve(promise: Promise, setter: (t: T) => void) { (async function () { let data = await promise; if (data != null) { @@ -62,7 +62,7 @@ export async function unsetBatteryChargeRate(): Promise { // CPU -export async function setCpuSmt(status: boolean): Promise { +export async function setCpuSmt(status: boolean): Promise { return (await call_backend("CPU_set_smt", [status]))[0]; } @@ -158,7 +158,7 @@ export async function loadGeneralSystemSettings(): Promise { return (await call_backend("GENERAL_load_system_settings", []))[0]; } -export async function getGeneralSettingsName(): Promise { +export async function getGeneralSettingsName(): Promise { return (await call_backend("GENERAL_get_name", []))[0]; } diff --git a/src/index.tsx b/src/index.tsx index 16b39f9..9b0d68f 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -29,7 +29,6 @@ var startHook: any = null; var usdplReady = false; var smtAllowed = true; -var smtGlobal = smtAllowed; // usdpl persistent store keys @@ -43,6 +42,7 @@ const CHARGE_DESIGN_BATT = "BATTERY_charge_design" const TOTAL_CPUS = "CPUs_total"; const ONLINE_CPUS = "CPUs_online"; +const SMT_CPU = "CPUs_SMT"; const CLOCK_MIN_CPU = "CPUs_min_clock"; const CLOCK_MAX_CPU = "CPUs_max_clock"; const GOVERNOR_CPU = "CPUs_governor"; @@ -80,7 +80,7 @@ const reload = function() { // TODO: allow for per-core control of online status const count = countCpus(statii); set_value(ONLINE_CPUS, count); - smtGlobal = statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3] && smtAllowed; + set_value(SMT_CPU, statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3] && smtAllowed); }); // TODO: allow for per-core control of clock limits backend.resolve(backend.getCpuClockLimits(0), (limits: number[]) => { @@ -181,18 +181,21 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {smtAllowed && { console.debug("SMT is now " + smt.toString()); const cpus = get_value(ONLINE_CPUS); - smtGlobal = smt && smtAllowed; + const smtNow = smt && smtAllowed // TODO: move SMT setting logic back to back-end + backend.resolve(backend.setCpuSmt(smtNow), (newVal: boolean) => { + set_value(SMT_CPU, newVal); + }); let onlines: boolean[] = []; for (let i = 0; i < total_cpus; i++) { - const online = (smtGlobal? i < cpus : (i % 2 == 0) && (i < cpus * 2)) - || (!smtGlobal && cpus == 4); + const online = (smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2)) + || (!smtNow && cpus == 4); onlines.push(online); } backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { @@ -209,7 +212,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Threads" value={get_value(ONLINE_CPUS)} step={1} - max={smtGlobal? total_cpus : total_cpus/2} + max={get_value(SMT_CPU)? total_cpus : total_cpus/2} min={1} showValue={true} onChange={(cpus: number) => { @@ -217,9 +220,10 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { const onlines = get_value(ONLINE_CPUS); if (cpus != onlines) { set_value(ONLINE_CPUS, cpus); + const smtNow = get_value(SMT_CPU); let onlines: boolean[] = []; for (let i = 0; i < total_cpus; i++) { - const online = smtGlobal? i < cpus : (i % 2 == 0) && (i < cpus * 2); + const online = smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2); onlines.push(online); } backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { @@ -249,7 +253,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { for (let i = 0; i < total_cpus; i++) { backend.resolve(backend.unsetCpuClockLimits(i), (_idc: any[]) => {}); } - backend.resolve(backend.waitForComplete(), (_: boolean[]) => { + backend.resolve(backend.waitForComplete(), (_: boolean) => { reloadGUI("CPUUnsetFreq"); }); } @@ -277,7 +281,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { set_value(CLOCK_MAX_CPU, limits[1]); }); } - backend.resolve(backend.waitForComplete(), (_: boolean[]) => { + backend.resolve(backend.waitForComplete(), (_: boolean) => { reloadGUI("CPUMinFreq"); }); reloadGUI("CPUMinFreqImmediate"); @@ -306,7 +310,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { set_value(CLOCK_MAX_CPU, limits[1]); }); } - backend.resolve(backend.waitForComplete(), (_: boolean[]) => { + backend.resolve(backend.waitForComplete(), (_: boolean) => { reloadGUI("CPUMaxFreq"); }); reloadGUI("CPUMaxFreqImmediate"); @@ -621,9 +625,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { backend.setGeneralPersistent(false), (val: boolean) => { set_value(PERSISTENT_GEN, val); - backend.resolve(backend.loadGeneralDefaultSettings(), (_: any[]) => { + backend.resolve(backend.loadGeneralSystemSettings(), (_) => { reload(); - backend.resolve(backend.waitForComplete(), (_: any[]) => {reloadGUI("LoadDefaults")}); + backend.resolve(backend.waitForComplete(), (_) => {reloadGUI("LoadSystemDefaults")}); }); } ); From 165a78e23133f01a2741315a84e08ef104c9311c Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 13 Nov 2022 21:18:48 -0500 Subject: [PATCH 05/44] Add advanced CPU config UI (untested) --- src/index.tsx | 242 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 223 insertions(+), 19 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 9b0d68f..8a33f52 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -12,6 +12,10 @@ import { staticClasses, SliderField, ToggleField, + Dropdown, + Field, + //DropdownOption, + SingleDropdownOption, //NotchLabel gamepadDialogClasses, joinClassNames, @@ -29,6 +33,40 @@ var startHook: any = null; var usdplReady = false; var smtAllowed = true; +var advancedMode = false; +var advancedCpu = 1; + +type MinMax = { + min: number | null; + max: number | null; +} + +const governorOptions: SingleDropdownOption[] = [ + { + data: "conservative", + label: conservative, + }, + { + data: "ondemand", + label: ondemand, + }, + { + data: "userspace", + label: userspace, + }, + { + data: "powersave", + label: powersave, + }, + { + data: "performance", + label: performance, + }, + { + data: "schedutil", + label: schedutil, + }, +]; // usdpl persistent store keys @@ -42,9 +80,11 @@ const CHARGE_DESIGN_BATT = "BATTERY_charge_design" const TOTAL_CPUS = "CPUs_total"; const ONLINE_CPUS = "CPUs_online"; +const ONLINE_STATUS_CPUS = "CPUs_status_online"; const SMT_CPU = "CPUs_SMT"; const CLOCK_MIN_CPU = "CPUs_min_clock"; const CLOCK_MAX_CPU = "CPUs_max_clock"; +const CLOCK_MIN_MAX_CPU = "CPUs_minmax_clocks"; const GOVERNOR_CPU = "CPUs_governor"; const FAST_PPT_GPU = "GPU_fastPPT"; @@ -66,6 +106,20 @@ function countCpus(statii: boolean[]): number { return count; } +function syncPlebClockToAdvanced() { + const cpuCount = get_value(TOTAL_CPUS); + const minClock = get_value(CLOCK_MIN_CPU); + const maxClock = get_value(CLOCK_MAX_CPU); + let clockArr = []; + for (let i = 0; i < cpuCount; i++) { + clockArr.push({ + min: minClock, + max: maxClock, + } as MinMax); + } + set_value(CLOCK_MIN_MAX_CPU, clockArr); +} + const reload = function() { if (!usdplReady) {return;} @@ -77,18 +131,21 @@ const reload = function() { backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)}); backend.resolve(backend.getCpusOnline(), (statii: boolean[]) => { - // TODO: allow for per-core control of online status + set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); set_value(SMT_CPU, statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3] && smtAllowed); }); - // TODO: allow for per-core control of clock limits backend.resolve(backend.getCpuClockLimits(0), (limits: number[]) => { set_value(CLOCK_MIN_CPU, limits[0]); set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); + }); + backend.resolve(backend.getCpusGovernor(), (governors: string[]) => { + set_value(GOVERNOR_CPU, governors); + console.log("POWERTOOLS: Governors from backend", governors); + console.log("POWERTOOLS: Governors in dropdown", governorOptions); }); - // TODO: allow for control of governor - backend.resolve(backend.getCpusGovernor(), (governors: string[]) => { set_value(GOVERNOR_CPU, governors[0]) }); backend.resolve(backend.getGpuPpt(), (ppts: number[]) => { set_value(FAST_PPT_GPU, ppts[0]); @@ -172,14 +229,26 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard); const total_cpus = get_value(TOTAL_CPUS); + const advancedCpuIndex = advancedCpu - 1; return ( - {/* CPU */ /* TODO: set per-core stuff*/} + {/* CPU */}
CPU
- {smtAllowed && + + { + advancedMode = advanced; + }} + /> + + {/* CPU plebeian mode */} + {!advancedMode && smtAllowed && = ({}) => { onChange={(smt: boolean) => { console.debug("SMT is now " + smt.toString()); const cpus = get_value(ONLINE_CPUS); - const smtNow = smt && smtAllowed - // TODO: move SMT setting logic back to back-end + const smtNow = smt && smtAllowed; backend.resolve(backend.setCpuSmt(smtNow), (newVal: boolean) => { set_value(SMT_CPU, newVal); }); @@ -199,7 +267,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { onlines.push(online); } backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { - // TODO: allow for per-core control of online status + set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); reloadGUI("SMT"); @@ -207,7 +275,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} /> } - + {!advancedMode && = ({}) => { onlines.push(online); } backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { - // TODO: allow for per-core control of online status + set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); reloadGUI("CPUs"); @@ -236,8 +304,8 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} /> - - + } + {!advancedMode && = ({}) => { if (value) { set_value(CLOCK_MIN_CPU, 1400); set_value(CLOCK_MAX_CPU, 3500); + syncPlebClockToAdvanced(); reloadGUI("CPUFreqToggle"); } else { set_value(CLOCK_MIN_CPU, null); @@ -256,11 +325,12 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { backend.resolve(backend.waitForComplete(), (_: boolean) => { reloadGUI("CPUUnsetFreq"); }); + syncPlebClockToAdvanced(); } }} /> - - + } + {!advancedMode && {get_value(CLOCK_MIN_CPU) != null && = ({}) => { (limits: number[]) => { set_value(CLOCK_MIN_CPU, limits[0]); set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); }); } backend.resolve(backend.waitForComplete(), (_: boolean) => { @@ -288,8 +359,8 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} />} - - + } + {!advancedMode && {get_value(CLOCK_MAX_CPU) != null && = ({}) => { (limits: number[]) => { set_value(CLOCK_MIN_CPU, limits[0]); set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); }); } backend.resolve(backend.waitForComplete(), (_: boolean) => { @@ -317,8 +389,140 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} />} - - {/* TODO: CPU governor */} + } + {/* CPU advanced mode */} + {advancedMode && + { + advancedCpu = cpuNum; + }} + /> + } + {advancedMode && + { + console.debug("CPU " + advancedCpu.toString() + " is now " + status.toString()); + if (get_value(SMT_CPU)) { + backend.resolve(backend.setCpuSmt(false), (newVal: boolean) => { + set_value(SMT_CPU, newVal); + }); + } + backend.resolve(backend.setCpuOnline(advancedCpuIndex, status), (newVal: boolean) => { + const onlines = get_value(ONLINE_STATUS_CPUS); + onlines[advancedCpuIndex] = newVal; + set_value(ONLINE_STATUS_CPUS, onlines); + }); + }} + /> + } + {advancedMode && + { + if (value) { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = 1400; + clocks[advancedCpuIndex].max = 3500; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUFreqToggle"); + } else { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = null; + clocks[advancedCpuIndex].max = null; + set_value(CLOCK_MIN_MAX_CPU, clocks); + backend.resolve(backend.unsetCpuClockLimits(advancedCpuIndex), (_idc: any[]) => { + reloadGUI("CPUUnsetFreq"); + }); + } + }} + /> + } + {advancedMode && + {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min != null && { + console.debug("Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; + if (freq != freqNow.min) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMinFreq"); + }); + } + }} + />} + } + {advancedMode && + {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max != null && { + console.debug("Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; + if (freq != freqNow.max) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMaxFreq"); + }); + } + }} + />} + } + {advancedMode && + + { + console.debug("POWERTOOLS: array item", val); + console.debug("POWERTOOLS: looking for data", get_value(GOVERNOR_CPU)[advancedCpuIndex]); + return val.data == get_value(GOVERNOR_CPU)[advancedCpuIndex]; + })} + strDefaultLabel={get_value(GOVERNOR_CPU)[advancedCpuIndex]} + onChange={(elem: SingleDropdownOption) => { + console.debug("Governor dropdown selected", elem); + backend.resolve(backend.setCpuGovernor(advancedCpuIndex, elem.data as string), (gov: string) => { + const governors = get_value(GOVERNOR_CPU); + governors[advancedCpuIndex] = gov; + set_value(GOVERNOR_CPU, governors); + reloadGUI("CPUGovernor"); + }); + }} + /> + + } {/* GPU */}
GPU From 31c72de11e31970a960eaeec4a2e7b3d1c77c1b4 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 19 Nov 2022 15:21:09 -0500 Subject: [PATCH 06/44] Add and (mostly) test driver support --- backend/src/api/api_types.rs | 54 +++ backend/src/api/battery.rs | 8 +- backend/src/api/cpu.rs | 4 +- backend/src/api/general.rs | 16 + backend/src/api/handler.rs | 90 ++-- backend/src/api/mod.rs | 3 + backend/src/api/utility.rs | 14 + backend/src/main.rs | 6 + backend/src/persist/driver.rs | 14 + backend/src/persist/general.rs | 4 +- backend/src/persist/mod.rs | 2 + backend/src/settings/driver.rs | 179 +++++++ backend/src/settings/general.rs | 161 ++++--- backend/src/settings/mod.rs | 14 +- .../src/settings/{ => steam_deck}/battery.rs | 62 ++- backend/src/settings/steam_deck/cpu.rs | 446 ++++++++++++++++++ backend/src/settings/steam_deck/gpu.rs | 308 ++++++++++++ backend/src/settings/steam_deck/mod.rs | 7 + .../src/settings/steam_deck_adv/battery.rs | 216 +++++++++ .../src/settings/{ => steam_deck_adv}/cpu.rs | 110 ++++- .../src/settings/{ => steam_deck_adv}/gpu.rs | 99 +++- backend/src/settings/steam_deck_adv/mod.rs | 7 + backend/src/settings/traits.rs | 68 +++ backend/src/settings/unknown/battery.rs | 49 ++ backend/src/settings/unknown/cpu.rs | 289 ++++++++++++ backend/src/settings/unknown/gpu.rs | 89 ++++ backend/src/settings/unknown/mod.rs | 7 + backend/src/state/mod.rs | 8 +- backend/src/state/{ => steam_deck}/battery.rs | 0 backend/src/state/{ => steam_deck}/cpu.rs | 0 backend/src/state/{ => steam_deck}/gpu.rs | 0 backend/src/state/steam_deck/mod.rs | 7 + src/backend.ts | 52 +- src/index.tsx | 344 +++++++------- 34 files changed, 2379 insertions(+), 358 deletions(-) create mode 100644 backend/src/api/api_types.rs create mode 100644 backend/src/persist/driver.rs create mode 100644 backend/src/settings/driver.rs rename backend/src/settings/{ => steam_deck}/battery.rs (76%) create mode 100644 backend/src/settings/steam_deck/cpu.rs create mode 100644 backend/src/settings/steam_deck/gpu.rs create mode 100644 backend/src/settings/steam_deck/mod.rs create mode 100644 backend/src/settings/steam_deck_adv/battery.rs rename backend/src/settings/{ => steam_deck_adv}/cpu.rs (79%) rename backend/src/settings/{ => steam_deck_adv}/gpu.rs (72%) create mode 100644 backend/src/settings/steam_deck_adv/mod.rs create mode 100644 backend/src/settings/unknown/battery.rs create mode 100644 backend/src/settings/unknown/cpu.rs create mode 100644 backend/src/settings/unknown/gpu.rs create mode 100644 backend/src/settings/unknown/mod.rs rename backend/src/state/{ => steam_deck}/battery.rs (100%) rename backend/src/state/{ => steam_deck}/cpu.rs (100%) rename backend/src/state/{ => steam_deck}/gpu.rs (100%) create mode 100644 backend/src/state/steam_deck/mod.rs diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs new file mode 100644 index 0000000..1210ece --- /dev/null +++ b/backend/src/api/api_types.rs @@ -0,0 +1,54 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct RangeLimit { + pub min: T, + pub max: T, +} + +#[derive(Serialize, Deserialize)] +pub struct SettingsLimits { + pub battery: BatteryLimits, + pub cpu: CpusLimits, + pub gpu: GpuLimits, + pub general: GeneralLimits, +} + +#[derive(Serialize, Deserialize)] +pub struct BatteryLimits { + pub charge_rate: Option>, + pub charge_step: u64, +} + +#[derive(Serialize, Deserialize)] +pub struct CpusLimits { + pub cpus: Vec, + pub count: usize, + pub smt_capable: bool, +} + +#[derive(Serialize, Deserialize)] +pub struct CpuLimits { + pub clock_min_limits: Option>, + pub clock_max_limits: Option>, + pub clock_step: u64, + pub governors: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct GeneralLimits { +} + +#[derive(Serialize, Deserialize)] +pub struct GpuLimits { + pub fast_ppt_limits: Option>, + pub slow_ppt_limits: Option>, + pub ppt_step: u64, + pub tdp_limits: Option>, + pub tdp_boost_limits: Option>, + pub tdp_step: u64, + pub clock_min_limits: Option>, + pub clock_max_limits: Option>, + pub clock_step: u64, + pub memory_control_capable: bool, +} diff --git a/backend/src/api/battery.rs b/backend/src/api/battery.rs index 83af197..caa35d4 100644 --- a/backend/src/api/battery.rs +++ b/backend/src/api/battery.rs @@ -6,22 +6,22 @@ use super::handler::{ApiMessage, BatteryMessage}; /// Current current (ha!) web method pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_result(crate::settings::Battery::read_current_now()) + super::utility::map_optional_result(crate::settings::driver::read_current_now()) } /// Charge now web method pub fn charge_now(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_result(crate::settings::Battery::read_charge_now()) + super::utility::map_optional_result(crate::settings::driver::read_charge_now()) } /// Charge full web method pub fn charge_full(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_result(crate::settings::Battery::read_charge_full()) + super::utility::map_optional_result(crate::settings::driver::read_charge_full()) } /// Charge design web method pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_result(crate::settings::Battery::read_charge_design()) + super::utility::map_optional_result(crate::settings::driver::read_charge_design()) } /// Generate set battery charge rate web method diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index c4c1922..02e2f1e 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -3,14 +3,14 @@ use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; -use crate::settings::{Cpus, SettingError, SettingVariant, MinMax}; +use crate::settings::{SettingError, SettingVariant, MinMax}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, CpuMessage}; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { super::utility::map_result( - Cpus::cpu_count() + crate::settings::steam_deck::Cpus::cpu_count() .map(|x| x as u64) .ok_or_else( || SettingError { diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index a0216eb..9dc765f 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -161,3 +161,19 @@ pub fn lock_unlock_all( } } } + +/// Generate get limits web method +pub fn get_limits( + sender: Sender, +) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |value: super::SettingsLimits| tx.send(value).expect("get_limits callback send failed"); + sender.lock().unwrap().send(ApiMessage::GetLimits(Box::new(callback))).expect("get_limits send failed"); + rx.recv().expect("get_limits callback recv failed") + }; + move |_: super::ApiParameterType| { + vec![Primitive::Json(serde_json::to_string(&getter()).unwrap())] + } +} diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 3ceef2e..aa3e683 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -1,6 +1,6 @@ use std::sync::mpsc::{self, Receiver, Sender}; -use crate::settings::{Settings, Cpus, Gpu, Battery, General, OnSet, OnResume, MinMax}; +use crate::settings::{Settings, TCpus, TGpu, TBattery, TGeneral, OnSet, OnResume, MinMax}; use crate::persist::SettingsJson; use crate::utility::unwrap_maybe_fatal; @@ -16,6 +16,7 @@ pub enum ApiMessage { LoadSettings(String, String), // (path, name) LoadMainSettings, LoadSystemSettings, + GetLimits(Callback), } pub enum BatteryMessage { @@ -24,10 +25,10 @@ pub enum BatteryMessage { } impl BatteryMessage { - fn process(self, settings: &mut Battery) { + fn process(self, settings: &mut dyn TBattery) { match self { - Self::SetChargeRate(rate) => settings.charge_rate = rate, - Self::GetChargeRate(cb) => cb(settings.charge_rate), + Self::SetChargeRate(rate) => settings.charge_rate(rate), + Self::GetChargeRate(cb) => cb(settings.get_charge_rate()), } } } @@ -45,41 +46,41 @@ pub enum CpuMessage { } impl CpuMessage { - fn process(self, settings: &mut Cpus) { + fn process(self, settings: &mut dyn TCpus) { match self { - Self::SetCpuOnline(index, status) => {settings.cpus.get_mut(index).map(|c| c.online = status);}, + Self::SetCpuOnline(index, status) => {settings.cpus().get_mut(index).map(|c| *c.online() = status);}, Self::SetCpusOnline(cpus) => { for i in 0..cpus.len() { - settings.cpus.get_mut(i).map(|c| c.online = cpus[i]); + settings.cpus().get_mut(i).map(|c| *c.online() = cpus[i]); } }, Self::SetSmt(status, cb) => { - let mut result = Vec::with_capacity(settings.cpus.len()); - for i in 0..settings.cpus.len() { - settings.cpus[i].online = settings.cpus[i].online && (status || i % 2 == 0); - result.push(settings.cpus[i].online); + let mut result = Vec::with_capacity(settings.len()); + for i in 0..settings.len() { + *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); + result.push(*settings.cpus()[i].online()); } cb(result); } Self::GetCpusOnline(cb) => { - let mut result = Vec::with_capacity(settings.cpus.len()); - for cpu in &settings.cpus { - result.push(cpu.online); + let mut result = Vec::with_capacity(settings.len()); + for cpu in settings.cpus() { + result.push(*cpu.online()); } cb(result); }, - Self::SetClockLimits(index, clocks) => {settings.cpus.get_mut(index).map(|c| c.clock_limits = clocks);}, - Self::GetClockLimits(index, cb) => {settings.cpus.get(index).map(|c| cb(c.clock_limits.clone()));}, - Self::SetCpuGovernor(index, gov) => {settings.cpus.get_mut(index).map(|c| c.governor = gov);}, + Self::SetClockLimits(index, clocks) => {settings.cpus().get_mut(index).map(|c| c.clock_limits(clocks));}, + Self::GetClockLimits(index, cb) => {settings.cpus().get(index).map(|c| cb(c.get_clock_limits().map(|x| x.to_owned())));}, + Self::SetCpuGovernor(index, gov) => {settings.cpus().get_mut(index).map(|c| c.governor(gov));}, Self::SetCpusGovernor(govs) => { for i in 0..govs.len() { - settings.cpus.get_mut(i).map(|c| c.governor = govs[i].clone()); + settings.cpus().get_mut(i).map(|c| c.governor(govs[i].clone())); } }, Self::GetCpusGovernor(cb) => { - let mut result = Vec::with_capacity(settings.cpus.len()); - for cpu in &settings.cpus { - result.push(cpu.governor.clone()); + let mut result = Vec::with_capacity(settings.len()); + for cpu in settings.cpus() { + result.push(cpu.get_governor().to_owned()); } cb(result); } @@ -97,17 +98,14 @@ pub enum GpuMessage { } impl GpuMessage { - fn process(self, settings: &mut Gpu) { + fn process(self, settings: &mut dyn TGpu) { match self { - Self::SetPpt(fast, slow) => { - settings.fast_ppt = fast; - settings.slow_ppt = slow; - }, - Self::GetPpt(cb) => cb((settings.fast_ppt, settings.slow_ppt)), - Self::SetClockLimits(clocks) => settings.clock_limits = clocks, - Self::GetClockLimits(cb) => cb(settings.clock_limits.clone()), - Self::SetSlowMemory(val) => settings.slow_memory = val, - Self::GetSlowMemory(cb) => cb(settings.slow_memory), + Self::SetPpt(fast, slow) => settings.ppt(fast, slow), + Self::GetPpt(cb) => cb(settings.get_ppt()), + Self::SetClockLimits(clocks) => settings.clock_limits(clocks), + Self::GetClockLimits(cb) => cb(settings.get_clock_limits().map(|x| x.to_owned())), + Self::SetSlowMemory(val) => *settings.slow_memory() = val, + Self::GetSlowMemory(cb) => cb(*settings.slow_memory()), } } } @@ -119,11 +117,11 @@ pub enum GeneralMessage { } impl GeneralMessage { - fn process(self, settings: &mut General) { + fn process(self, settings: &mut dyn TGeneral) { match self { - Self::SetPersistent(val) => settings.persistent = val, - Self::GetPersistent(cb) => cb(settings.persistent), - Self::GetCurrentProfileName(cb) => cb(settings.name.clone()), + Self::SetPersistent(val) => *settings.persistent() = val, + Self::GetPersistent(cb) => cb(*settings.persistent()), + Self::GetCurrentProfileName(cb) => cb(settings.get_name().to_owned()), } } } @@ -150,11 +148,11 @@ impl ApiMessageHandler { } // save log::debug!("api_worker is saving..."); - let is_persistent = settings.general.persistent; + let is_persistent = *settings.general.persistent(); if is_persistent { let save_path = crate::utility::settings_dir() - .join(settings.general.path.clone()); - let settings_clone = settings.clone(); + .join(settings.general.get_path().clone()); + let settings_clone = settings.json(); let save_json: SettingsJson = settings_clone.into(); unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); log::debug!("Saved settings to {}", save_path.display()); @@ -166,10 +164,10 @@ impl ApiMessageHandler { pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) { match message { - ApiMessage::Battery(x) => x.process(&mut settings.battery), - ApiMessage::Cpu(x) => x.process(&mut settings.cpus), - ApiMessage::Gpu(x) => x.process(&mut settings.gpu), - ApiMessage::General(x) => x.process(&mut settings.general), + ApiMessage::Battery(x) => x.process(settings.battery.as_mut()), + ApiMessage::Cpu(x) => x.process(settings.cpus.as_mut()), + ApiMessage::Gpu(x) => x.process(settings.gpu.as_mut()), + ApiMessage::General(x) => x.process(settings.general.as_mut()), ApiMessage::OnResume => { if let Err(e) = settings.on_resume() { log::error!("Settings on_resume() err: {}", e); @@ -194,6 +192,14 @@ impl ApiMessageHandler { } ApiMessage::LoadSystemSettings => { settings.load_system_default(); + }, + ApiMessage::GetLimits(cb) => { + cb(super::SettingsLimits { + battery: settings.battery.limits(), + cpu: settings.cpus.limits(), + gpu: settings.gpu.limits(), + general: settings.general.limits(), + }); } } } diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs index 03412a8..174d1bb 100644 --- a/backend/src/api/mod.rs +++ b/backend/src/api/mod.rs @@ -1,3 +1,4 @@ +mod api_types; pub mod battery; pub mod cpu; pub mod general; @@ -7,3 +8,5 @@ mod async_utils; mod utility; pub(super) type ApiParameterType = Vec; + +pub use api_types::*; diff --git a/backend/src/api/utility.rs b/backend/src/api/utility.rs index c797f60..76957ca 100644 --- a/backend/src/api/utility.rs +++ b/backend/src/api/utility.rs @@ -14,6 +14,20 @@ pub fn map_result>(result: Result) -> super: } } +#[inline] +pub fn map_optional_result>(result: Result, SettingError>) -> super::ApiParameterType { + match result { + Ok(val) => match val { + Some(val) => vec![val.into()], + None => vec![Primitive::Empty], + }, + Err(e) => { + log::debug!("Mapping error to primitive: {}", e); + vec![e.msg.into()] + }, + } +} + /*#[inline] pub fn map_empty_result>( result: Result<(), SettingError>, diff --git a/backend/src/main.rs b/backend/src/main.rs index aa53e00..884d519 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -44,6 +44,8 @@ fn main() -> Result<(), ()> { log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); + crate::settings::driver::auto_detect_loud(); + let mut loaded_settings = persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE)) .map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into())) .unwrap_or_else(|_| settings::Settings::system_default(DEFAULT_SETTINGS_FILE.into())); @@ -183,6 +185,10 @@ fn main() -> Result<(), ()> { .register_async( "GENERAL_wait_for_unlocks", api::general::lock_unlock_all(api_sender.clone()) + ) + .register( + "GENERAL_get_limits", + api::general::get_limits(api_sender.clone()) ); api_worker::spawn(loaded_settings, api_handler); diff --git a/backend/src/persist/driver.rs b/backend/src/persist/driver.rs new file mode 100644 index 0000000..bf8b891 --- /dev/null +++ b/backend/src/persist/driver.rs @@ -0,0 +1,14 @@ +//use std::default::Default; + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Default, Debug, Clone)] +pub enum DriverJson { + #[default] + #[serde(rename = "steam-deck", alias = "gabe-boy")] + SteamDeck, + #[serde(rename = "steam-deck-oc", alias = "gabe-boy-advance")] + SteamDeckAdvance, + #[serde(rename = "unknown")] + Unknown, +} diff --git a/backend/src/persist/general.rs b/backend/src/persist/general.rs index 4ae3c89..b85df70 100644 --- a/backend/src/persist/general.rs +++ b/backend/src/persist/general.rs @@ -3,7 +3,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; use super::JsonError; -use super::{BatteryJson, CpuJson, GpuJson}; +use super::{BatteryJson, CpuJson, GpuJson, DriverJson}; #[derive(Serialize, Deserialize)] pub struct SettingsJson { @@ -13,6 +13,7 @@ pub struct SettingsJson { pub cpus: Vec, pub gpu: GpuJson, pub battery: BatteryJson, + pub provider: Option, } impl Default for SettingsJson { @@ -24,6 +25,7 @@ impl Default for SettingsJson { cpus: Vec::with_capacity(8), gpu: GpuJson::default(), battery: BatteryJson::default(), + provider: None, } } } diff --git a/backend/src/persist/mod.rs b/backend/src/persist/mod.rs index 5b70ff5..ef9a677 100644 --- a/backend/src/persist/mod.rs +++ b/backend/src/persist/mod.rs @@ -1,11 +1,13 @@ mod battery; mod cpu; +mod driver; mod error; mod general; mod gpu; pub use battery::BatteryJson; pub use cpu::CpuJson; +pub use driver::DriverJson; pub use general::{MinMaxJson, SettingsJson}; pub use gpu::GpuJson; diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs new file mode 100644 index 0000000..921c7a7 --- /dev/null +++ b/backend/src/settings/driver.rs @@ -0,0 +1,179 @@ +use crate::persist::{DriverJson, SettingsJson}; +use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General}; + +/// Device detection logic +fn auto_detect() -> DriverJson { + let lscpu: String = match usdpl_back::api::files::read_single("/proc/cpuinfo") { + Ok(s) => s, + Err(_) => return DriverJson::Unknown, + }; + log::debug!("Read from /proc/cpuinfo:\n{}", lscpu); + let os_info: String = match usdpl_back::api::files::read_single("/etc/os-release") { + Ok(s) => s, + Err(_) => return DriverJson::Unknown, + }; + log::debug!("Read from /etc/os-release:\n{}", os_info); + if let Some(_) = lscpu.find("model name\t: AMD Custom APU 0405\n") { + // definitely a Steam Deck, check if it's overclocked + let max_freq: u64 = match usdpl_back::api::files::read_single("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq") { + Ok(u) => u, + Err(_) => return DriverJson::SteamDeck, + }; + if max_freq == 2800000 { // default clock speed + DriverJson::SteamDeck + } else { + DriverJson::SteamDeckAdvance + } + } else { + DriverJson::Unknown + } +} + +#[inline] +pub fn auto_detect_loud() -> DriverJson { + let provider = auto_detect(); + log::info!("Detected device automatically, compatible driver: {:?}", provider); + provider +} + +pub struct Driver { + pub general: Box, + pub cpus: Box, + pub gpu: Box, + pub battery: Box, +} + +impl Driver { + pub fn init(settings: SettingsJson, json_path: std::path::PathBuf) -> Result { + Ok(match settings.version { + 0 => Self::version0(settings, json_path)?, + _ => Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::SteamDeck, + }), + cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), + }, + }) + } + + fn version0(settings: SettingsJson, json_path: std::path::PathBuf) -> Result { + let provider = settings.provider.unwrap_or_else(auto_detect); + match provider { + DriverJson::SteamDeck => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::SteamDeck, + }), + cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), + }), + DriverJson::SteamDeckAdvance => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::SteamDeckAdvance, + }), + cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::steam_deck_adv::Battery::from_json(settings.battery, settings.version)), + }), + DriverJson::Unknown => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::Unknown, + }), + cpus: Box::new(super::unknown::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::unknown::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::unknown::Battery), + }), + } + } + + pub fn system_default(json_path: std::path::PathBuf) -> Self { + let provider = auto_detect(); + match provider { + DriverJson::SteamDeck => Self { + general: Box::new(General { + persistent: false, + path: json_path, + name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + driver: DriverJson::SteamDeck, + }), + cpus: Box::new(super::steam_deck::Cpus::system_default()), + gpu: Box::new(super::steam_deck::Gpu::system_default()), + battery: Box::new(super::steam_deck::Battery::system_default()), + }, + DriverJson::SteamDeckAdvance => Self { + general: Box::new(General { + persistent: false, + path: json_path, + name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + driver: DriverJson::SteamDeck, + }), + cpus: Box::new(super::steam_deck_adv::Cpus::system_default()), + gpu: Box::new(super::steam_deck_adv::Gpu::system_default()), + battery: Box::new(super::steam_deck_adv::Battery::system_default()), + }, + DriverJson::Unknown => Self { + general: Box::new(General { + persistent: false, + path: json_path, + name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + driver: DriverJson::Unknown, + }), + cpus: Box::new(super::unknown::Cpus::system_default()), + gpu: Box::new(super::unknown::Gpu::system_default()), + battery: Box::new(super::unknown::Battery), + } + } + } +} + +// static battery calls + +#[inline] +pub fn read_current_now() -> Result, SettingError> { + match auto_detect() { + DriverJson::SteamDeck => super::steam_deck::Battery::read_current_now().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_current_now().map(|x| Some(x)), + DriverJson::Unknown => Ok(None), + } +} + +#[inline] +pub fn read_charge_now() -> Result, SettingError> { + match auto_detect() { + DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_now().map(|x| Some(x)), + DriverJson::Unknown => Ok(None), + } +} + +#[inline] +pub fn read_charge_full() -> Result, SettingError> { + match auto_detect() { + DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_full().map(|x| Some(x)), + DriverJson::Unknown => Ok(None), + } +} + +#[inline] +pub fn read_charge_design() -> Result, SettingError> { + match auto_detect() { + DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_design().map(|x| Some(x)), + DriverJson::Unknown => Ok(None), + } +} diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index fb95f52..9c6afd7 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -1,9 +1,9 @@ -use std::convert::Into; use std::path::PathBuf; //use std::sync::{Arc, Mutex}; -use super::{Battery, Cpus, Gpu}; +//use super::{Battery, Cpus, Gpu}; use super::{OnResume, OnSet, SettingError}; +use super::{TGeneral, TGpu, TCpus, TBattery}; use crate::persist::SettingsJson; //use crate::utility::unwrap_lock; @@ -33,6 +33,7 @@ pub struct General { pub persistent: bool, pub path: PathBuf, pub name: String, + pub driver: crate::persist::DriverJson, } impl OnSet for General { @@ -41,12 +42,52 @@ impl OnSet for General { } } -#[derive(Debug, Clone)] +impl OnResume for General { + fn on_resume(&self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl TGeneral for General { + fn limits(&self) -> crate::api::GeneralLimits { + crate::api::GeneralLimits { } + } + + fn get_persistent(&self) -> bool { + self.persistent + } + + fn persistent(&mut self) -> &'_ mut bool { + &mut self.persistent + } + + fn get_path(&self) -> &'_ std::path::Path { + &self.path + } + + fn path(&mut self, path: std::path::PathBuf) { + self.path = path; + } + + fn get_name(&self) -> &'_ str { + &self.name + } + + fn name(&mut self, name: String) { + self.name = name; + } + + fn provider(&self) -> crate::persist::DriverJson { + self.driver.clone() + } +} + +#[derive(Debug)] pub struct Settings { - pub general: General, - pub cpus: Cpus, - pub gpu: Gpu, - pub battery: Battery, + pub general: Box, + pub cpus: Box, + pub gpu: Box, + pub battery: Box, } impl OnSet for Settings { @@ -62,47 +103,38 @@ impl OnSet for Settings { impl Settings { #[inline] pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self { - match other.version { - 0 => Self { - general: General { - persistent: other.persistent, - path: json_path, - name: other.name, - }, - cpus: Cpus::from_json(other.cpus, other.version), - gpu: Gpu::from_json(other.gpu, other.version), - battery: Battery::from_json(other.battery, other.version), - }, - _ => Self { - general: General { - persistent: other.persistent, - path: json_path, - name: other.name, - }, - cpus: Cpus::from_json(other.cpus, other.version), - gpu: Gpu::from_json(other.gpu, other.version), - battery: Battery::from_json(other.battery, other.version), + match super::Driver::init(other, json_path.clone()) { + Ok(x) => { + log::info!("Loaded settings for driver {:?}", x.general.provider()); + Self { + general: x.general, + cpus: x.cpus, + gpu: x.gpu, + battery: x.battery, + } }, + Err(e) => { + log::error!("Driver init error: {}", e); + Self::system_default(json_path) + } } } pub fn system_default(json_path: PathBuf) -> Self { + let driver = super::Driver::system_default(json_path); Self { - general: General { - persistent: false, - path: json_path, - name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - }, - cpus: Cpus::system_default(), - gpu: Gpu::system_default(), - battery: Battery::system_default(), + general: driver.general, + cpus: driver.cpus, + gpu: driver.gpu, + battery: driver.battery, } } pub fn load_system_default(&mut self) { - self.cpus = Cpus::system_default(); - self.gpu = Gpu::system_default(); - self.battery = Battery::system_default(); + let driver = super::Driver::system_default(self.general.get_path().to_owned()); + self.cpus = driver.cpus; + self.gpu = driver.gpu; + self.battery = driver.battery; } pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result { @@ -115,24 +147,36 @@ impl Settings { })?; if !settings_json.persistent { log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display()); - self.general.persistent = false; - self.general.name = name; + *self.general.persistent() = false; + self.general.name(name); } else { - self.cpus = Cpus::from_json(settings_json.cpus, settings_json.version); - self.gpu = Gpu::from_json(settings_json.gpu, settings_json.version); - self.battery = Battery::from_json(settings_json.battery, settings_json.version); - self.general.persistent = true; - self.general.name = settings_json.name; + self.cpus = Box::new(super::steam_deck::Cpus::from_json(settings_json.cpus, settings_json.version)); + self.gpu = Box::new(super::steam_deck::Gpu::from_json(settings_json.gpu, settings_json.version)); + self.battery = Box::new(super::steam_deck::Battery::from_json(settings_json.battery, settings_json.version)); + *self.general.persistent() = true; + self.general.name(settings_json.name); } } else { if system_defaults { self.load_system_default(); } - self.general.persistent = false; - self.general.name = name; + *self.general.persistent() = false; + self.general.name(name); + } + self.general.path(json_path); + Ok(*self.general.persistent()) + } + + pub fn json(&self) -> SettingsJson { + SettingsJson { + version: LATEST_VERSION, + name: self.general.get_name().to_owned(), + persistent: self.general.get_persistent(), + cpus: self.cpus.json(), + gpu: self.gpu.json(), + battery: self.battery.json(), + provider: Some(self.general.provider()), } - self.general.path = json_path; - Ok(self.general.persistent) } } @@ -149,21 +193,18 @@ impl OnResume for Settings { } } -impl Into for Settings { +/*impl Into for Settings { #[inline] fn into(self) -> SettingsJson { log::debug!("Converting into json"); SettingsJson { version: LATEST_VERSION, - name: self.general.name.clone(), - persistent: self.general.persistent, - cpus: self.cpus.cpus - .clone() - .drain(..) - .map(|cpu| cpu.into()) - .collect(), - gpu: self.gpu.clone().into(), - battery: self.battery.clone().into(), + name: self.general.get_name().to_owned(), + persistent: self.general.get_persistent(), + cpus: self.cpus.json(), + gpu: self.gpu.json(), + battery: self.battery.json(), + provider: Some(self.general.provider()), } } -} +}*/ diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 2cef68c..5dd569c 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -1,19 +1,19 @@ -mod battery; -mod cpu; +pub mod driver; mod error; mod general; -mod gpu; mod min_max; mod traits; -pub use battery::Battery; -pub use cpu::{Cpu, Cpus}; +pub mod steam_deck; +pub mod steam_deck_adv; +pub mod unknown; + +pub use driver::Driver; pub use general::{SettingVariant, Settings, General}; -pub use gpu::Gpu; pub use min_max::MinMax; pub use error::SettingError; -pub use traits::{OnResume, OnSet, SettingsRange}; +pub use traits::{OnResume, OnSet, SettingsRange, TGeneral, TGpu, TCpus, TBattery, TCpu}; #[cfg(test)] mod tests { diff --git a/backend/src/settings/battery.rs b/backend/src/settings/steam_deck/battery.rs similarity index 76% rename from backend/src/settings/battery.rs rename to backend/src/settings/steam_deck/battery.rs index ae0dd63..a002bca 100644 --- a/backend/src/settings/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -1,12 +1,14 @@ use std::convert::Into; -use super::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::api::RangeLimit; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::TBattery; use crate::persist::BatteryJson; #[derive(Debug, Clone)] pub struct Battery { pub charge_rate: Option, - state: crate::state::Battery, + state: crate::state::steam_deck::Battery, } const BATTERY_VOLTAGE: f64 = 7.7; @@ -23,11 +25,11 @@ impl Battery { match version { 0 => Self { charge_rate: other.charge_rate, - state: crate::state::Battery::default(), + state: crate::state::steam_deck::Battery::default(), }, _ => Self { charge_rate: other.charge_rate, - state: crate::state::Battery::default(), + state: crate::state::steam_deck::Battery::default(), }, } } @@ -38,7 +40,7 @@ impl Battery { usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( |e| SettingError { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }, ) } else if self.state.charge_rate_set { @@ -46,7 +48,7 @@ impl Battery { usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, Self::max().charge_rate.unwrap()).map_err( |e| SettingError { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }, ) } else { @@ -66,11 +68,11 @@ impl Battery { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) { Err((Some(e), None)) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err((None, Some(e))) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err(_) => panic!( "Invalid error while reading from `{}`", @@ -86,11 +88,11 @@ impl Battery { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) { Err((Some(e), None)) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err((None, Some(e))) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err(_) => panic!( "Invalid error while reading from `{}`", @@ -105,11 +107,11 @@ impl Battery { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) { Err((Some(e), None)) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err((None, Some(e))) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err(_) => panic!( "Invalid error while reading from `{}`", @@ -124,11 +126,11 @@ impl Battery { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { Err((Some(e), None)) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err((None, Some(e))) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), - setting: super::SettingVariant::Battery, + setting: crate::settings::SettingVariant::Battery, }), Err(_) => panic!( "Invalid error while reading from `{}`", @@ -142,7 +144,7 @@ impl Battery { pub fn system_default() -> Self { Self { charge_rate: None, - state: crate::state::Battery::default(), + state: crate::state::steam_deck::Battery::default(), } } } @@ -174,7 +176,7 @@ impl SettingsRange for Battery { fn max() -> Self { Self { charge_rate: Some(2500), - state: crate::state::Battery::default(), + state: crate::state::steam_deck::Battery::default(), } } @@ -182,7 +184,33 @@ impl SettingsRange for Battery { fn min() -> Self { Self { charge_rate: Some(250), - state: crate::state::Battery::default(), + state: crate::state::steam_deck::Battery::default(), } } } + +impl TBattery for Battery { + fn limits(&self) -> crate::api::BatteryLimits { + let max = Self::max(); + let min = Self::min(); + crate::api::BatteryLimits { + charge_rate: Some(RangeLimit{ + min: min.charge_rate.unwrap(), + max: max.charge_rate.unwrap(), + }), + charge_step: 50, + } + } + + fn json(&self) -> crate::persist::BatteryJson { + self.clone().into() + } + + fn charge_rate(&mut self, rate: Option) { + self.charge_rate = rate; + } + + fn get_charge_rate(&self) -> Option { + self.charge_rate + } +} diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs new file mode 100644 index 0000000..845e3fe --- /dev/null +++ b/backend/src/settings/steam_deck/cpu.rs @@ -0,0 +1,446 @@ +use std::convert::Into; + +use crate::api::RangeLimit; +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::{TCpus, TCpu}; +use crate::persist::CpuJson; + +const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; +const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; + +#[derive(Debug, Clone)] +pub struct Cpus { + pub cpus: Vec, + pub smt: bool, + pub smt_capable: bool, +} + +impl OnSet for Cpus { + fn on_set(&mut self) -> Result<(), SettingError> { + if self.smt_capable { + // toggle SMT + if self.smt { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `on` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } else { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `off` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + } + for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { + cpu.state.do_set_online = self.smt || i % 2 == 0; + cpu.on_set()?; + } + Ok(()) + } +} + +impl OnResume for Cpus { + fn on_resume(&self) -> Result<(), SettingError> { + for cpu in &self.cpus { + cpu.on_resume()?; + } + Ok(()) + } +} + +impl Cpus { + pub fn cpu_count() -> Option { + let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) + .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); + if let Some(dash_index) = data.find('-') { + let data = data.split_off(dash_index + 1); + if let Ok(max_cpu) = data.parse::() { + return Some(max_cpu + 1); + } + } + log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); + None + } + + fn system_smt_capabilities() -> (bool, bool) { + match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { + Ok(val) => (val.trim().to_lowercase() == "on", true), + Err(_) => (false, false) + } + } + + pub fn system_default() -> Self { + if let Some(max_cpu) = Self::cpu_count() { + let mut sys_cpus = Vec::with_capacity(max_cpu); + for i in 0..max_cpu { + sys_cpus.push(Cpu::from_sys(i)); + } + let (smt_status, can_smt) = Self::system_smt_capabilities(); + Self { + cpus: sys_cpus, + smt: smt_status, + smt_capable: can_smt, + } + } else { + Self { + cpus: vec![], + smt: false, + smt_capable: false, + } + } + } + + #[inline] + pub fn from_json(mut other: Vec, version: u64) -> Self { + let (_, can_smt) = Self::system_smt_capabilities(); + let mut result = Vec::with_capacity(other.len()); + let max_cpus = Self::cpu_count(); + for (i, cpu) in other.drain(..).enumerate() { + // prevent having more CPUs than available + if let Some(max_cpus) = max_cpus { + if i == max_cpus { + break; + } + } + result.push(Cpu::from_json(cpu, version, i)); + } + if let Some(max_cpus) = max_cpus { + if result.len() != max_cpus { + let mut sys_cpus = Cpus::system_default(); + for i in result.len()..sys_cpus.cpus.len() { + result.push(sys_cpus.cpus.remove(i)); + } + } + } + Self { + cpus: result, + smt: true, + smt_capable: can_smt, + } + } +} + +impl TCpus for Cpus { + fn limits(&self) -> crate::api::CpusLimits { + crate::api::CpusLimits { + cpus: self.cpus.iter().map(|x| x.limits()).collect(), + count: self.cpus.len(), + smt_capable: self.smt_capable, + } + } + + fn json(&self) -> Vec { + self.cpus.iter().map(|x| x.to_owned().into()).collect() + } + + fn cpus(&mut self) -> Vec<&mut dyn TCpu> { + self.cpus.iter_mut().map(|x| x as &mut dyn TCpu).collect() + } + + fn len(&self) -> usize { + self.cpus.len() + } +} + +#[derive(Debug, Clone)] +pub struct Cpu { + pub online: bool, + pub clock_limits: Option>, + pub governor: String, + index: usize, + state: crate::state::steam_deck::Cpu, +} + +const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +const CPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; + +impl Cpu { + #[inline] + pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { + match version { + 0 => Self { + online: other.online, + clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + _ => Self { + online: other.online, + clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + // set cpu online/offline + if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled + let online_path = cpu_online_path(self.index); + usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", &online_path, e), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + // set clock limits + log::debug!("Setting {} to manual", CPU_FORCE_LIMITS_PATH); + let mode: String = usdpl_back::api::files::read_single(CPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); + if mode != "manual" { + // set manual control + usdpl_back::api::files::write_single(CPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `manual` to `{}`: {}", + CPU_FORCE_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + if let Some(clock_limits) = &self.clock_limits { + log::debug!("Setting CPU {} (min, max) clockspeed to ({}, {})", self.index, clock_limits.min, clock_limits.max); + self.state.clock_limits_set = true; + // max clock + let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max); + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_max, CPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + }, + )?; + // min clock + let payload_min = format!("p {} 0 {}\n", self.index / 2, clock_limits.min); + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_min, CPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + }, + )?; + } else if self.state.clock_limits_set || self.state.is_resuming { + self.state.clock_limits_set = false; + // disable manual clock limits + log::debug!("Setting CPU {} to default clockspeed", self.index); + // max clock + let payload_max = format!("p {} 1 {}\n", self.index / 2, Self::max().clock_limits.unwrap().max); + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_max, CPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + }, + )?; + // min clock + let payload_min = format!("p {} 0 {}\n", self.index / 2, Self::min().clock_limits.unwrap().min); + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_min, CPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + }, + )?; + } + // commit changes + usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { + SettingError { + msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + + // set governor + if self.index == 0 || self.online { + let governor_path = cpu_governor_path(self.index); + usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &self.governor, &governor_path, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + Ok(()) + } + + fn clamp_all(&mut self) { + let min = Self::min(); + let max = Self::max(); + if let Some(clock_limits) = &mut self.clock_limits { + let max_boost = max.clock_limits.as_ref().unwrap(); + let min_boost = min.clock_limits.as_ref().unwrap(); + clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); + clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); + } + } + + fn from_sys(cpu_index: usize) -> Self { + Self { + online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, + clock_limits: None, + governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) + .unwrap_or("schedutil".to_owned()), + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } + } + + fn limits(&self) -> crate::api::CpuLimits { + let max = Self::max(); + let max_clocks = max.clock_limits.unwrap(); + + let min = Self::min(); + let min_clocks = min.clock_limits.unwrap(); + crate::api::CpuLimits { + clock_min_limits: Some(RangeLimit { + min: min_clocks.min, + max: max_clocks.min + }), + clock_max_limits: Some(RangeLimit { + min: min_clocks.max, + max: max_clocks.max + }), + clock_step: 100, + governors: self.governors(), + } + } + + fn governors(&self) -> Vec { + // NOTE: this eats errors + let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { + Ok(s) => s, + Err((Some(e), None)) => { + log::warn!("Error getting available CPU governors: {}", e); + return vec![]; + }, + Err((None, Some(e))) => { + log::warn!("Error getting available CPU governors: {}", e); + return vec![]; + }, + Err(_) => return vec![], + }; + gov_str.split(' ').map(|s| s.to_owned()).collect() + } +} + +impl Into for Cpu { + #[inline] + fn into(self) -> CpuJson { + CpuJson { + online: self.online, + clock_limits: self.clock_limits.map(|x| x.into()), + governor: self.governor, + } + } +} + +impl OnSet for Cpu { + fn on_set(&mut self) -> Result<(), SettingError> { + self.clamp_all(); + self.set_all() + } +} + +impl OnResume for Cpu { + fn on_resume(&self) -> Result<(), SettingError> { + let mut copy = self.clone(); + copy.state.is_resuming = true; + copy.set_all() + } +} + +impl TCpu for Cpu { + fn online(&mut self) -> &mut bool { + &mut self.online + } + + fn governor(&mut self, governor: String) { + self.governor = governor; + } + + fn get_governor(&self) -> &'_ str { + &self.governor + } + + fn clock_limits(&mut self, limits: Option>) { + self.clock_limits = limits; + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.clock_limits.as_ref() + } +} + +impl SettingsRange for Cpu { + #[inline] + fn max() -> Self { + Self { + online: true, + clock_limits: Some(MinMax { + max: 3500, + min: 3500, + }), + governor: "schedutil".to_owned(), + index: usize::MAX, + state: crate::state::steam_deck::Cpu::default(), + } + } + + #[inline] + fn min() -> Self { + Self { + online: false, + clock_limits: Some(MinMax { max: 500, min: 1400 }), + governor: "schedutil".to_owned(), + index: usize::MIN, + state: crate::state::steam_deck::Cpu::default(), + } + } +} + +#[inline] +fn cpu_online_path(index: usize) -> String { + format!("/sys/devices/system/cpu/cpu{}/online", index) +} + +#[inline] +fn cpu_governor_path(index: usize) -> String { + format!( + "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor", + index + ) +} + + +#[inline] +fn cpu_available_governors_path(index: usize) -> String { + format!( + "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_available_governors", + index + ) +} diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs new file mode 100644 index 0000000..665a7df --- /dev/null +++ b/backend/src/settings/steam_deck/gpu.rs @@ -0,0 +1,308 @@ +use std::convert::Into; + +use crate::api::RangeLimit; +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::TGpu; +use crate::persist::GpuJson; + +const SLOW_PPT: u8 = 1; +const FAST_PPT: u8 = 2; + +#[derive(Debug, Clone)] +pub struct Gpu { + pub fast_ppt: Option, + pub slow_ppt: Option, + pub clock_limits: Option>, + pub slow_memory: bool, + state: crate::state::steam_deck::Gpu, +} + +// same as CPU +const GPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +const GPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; +const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk"; + +impl Gpu { + #[inline] + pub fn from_json(other: GpuJson, version: u64) -> Self { + match version { + 0 => Self { + fast_ppt: other.fast_ppt, + slow_ppt: other.slow_ppt, + clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + slow_memory: other.slow_memory, + state: crate::state::steam_deck::Gpu::default(), + }, + _ => Self { + fast_ppt: other.fast_ppt, + slow_ppt: other.slow_ppt, + clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + slow_memory: other.slow_memory, + state: crate::state::steam_deck::Gpu::default(), + }, + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + // set fast PPT + if let Some(fast_ppt) = &self.fast_ppt { + let fast_ppt_path = gpu_power_path(FAST_PPT); + usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + fast_ppt, &fast_ppt_path, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + })?; + } + // set slow PPT + if let Some(slow_ppt) = &self.slow_ppt { + let slow_ppt_path = gpu_power_path(SLOW_PPT); + usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + slow_ppt, &slow_ppt_path, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + })?; + } + // settings using force_performance_level + let mode: String = usdpl_back::api::files::read_single(GPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); + if mode != "manual" { + // set manual control + usdpl_back::api::files::write_single(GPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `manual` to `{}`: {}", + GPU_FORCE_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + } + })?; + } + // enable/disable downclock of GPU memory (to 400Mhz?) + usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) + .map_err(|e| SettingError { + msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), + setting: crate::settings::SettingVariant::Gpu, + })?; + if let Some(clock_limits) = &self.clock_limits { + // set clock limits + self.state.clock_limits_set = true; + // max clock + let payload_max = format!("s 1 {}\n", clock_limits.max); + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_max, GPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + }, + )?; + // min clock + let payload_min = format!("s 0 {}\n", clock_limits.min); + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_min, GPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + }, + )?; + } else if self.state.clock_limits_set || self.state.is_resuming { + self.state.clock_limits_set = false; + // disable manual clock limits + // max clock + let payload_max = format!("s 1 {}\n", Self::max().clock_limits.unwrap().max); + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_max, GPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + }, + )?; + // min clock + let payload_min = format!("s 0 {}\n", Self::min().clock_limits.unwrap().min); + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( + |e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload_min, GPU_CLOCK_LIMITS_PATH, e + ), + setting: crate::settings::SettingVariant::Gpu, + }, + )?; + } + // commit changes + usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { + SettingError { + msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), + setting: crate::settings::SettingVariant::Gpu, + } + })?; + + Ok(()) + } + + fn clamp_all(&mut self) { + let min = Self::min(); + let max = Self::max(); + if let Some(fast_ppt) = &mut self.fast_ppt { + *fast_ppt = (*fast_ppt).clamp( + *min.fast_ppt.as_ref().unwrap(), + *max.fast_ppt.as_ref().unwrap(), + ); + } + if let Some(slow_ppt) = &mut self.slow_ppt { + *slow_ppt = (*slow_ppt).clamp( + *min.slow_ppt.as_ref().unwrap(), + *max.slow_ppt.as_ref().unwrap(), + ); + } + if let Some(clock_limits) = &mut self.clock_limits { + let max_boost = max.clock_limits.as_ref().unwrap(); + let min_boost = min.clock_limits.as_ref().unwrap(); + clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); + clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); + } + } + + pub fn system_default() -> Self { + Self { + fast_ppt: None, + slow_ppt: None, + clock_limits: None, + slow_memory: false, + state: crate::state::steam_deck::Gpu::default(), + } + } +} + +impl Into for Gpu { + #[inline] + fn into(self) -> GpuJson { + GpuJson { + fast_ppt: self.fast_ppt, + slow_ppt: self.slow_ppt, + clock_limits: self.clock_limits.map(|x| x.into()), + slow_memory: self.slow_memory, + } + } +} + +impl OnSet for Gpu { + fn on_set(&mut self) -> Result<(), SettingError> { + self.clamp_all(); + self.set_all() + } +} + +impl OnResume for Gpu { + fn on_resume(&self) -> Result<(), SettingError> { + let mut copy = self.clone(); + copy.state.is_resuming = true; + copy.set_all() + } +} + +impl SettingsRange for Gpu { + #[inline] + fn max() -> Self { + Self { + fast_ppt: Some(30_000_000), + slow_ppt: Some(29_000_000), + clock_limits: Some(MinMax { + min: 1600, + max: 1600, + }), + slow_memory: false, + state: crate::state::steam_deck::Gpu::default(), + } + } + + #[inline] + fn min() -> Self { + Self { + fast_ppt: Some(0), + slow_ppt: Some(1000000), + clock_limits: Some(MinMax { min: 200, max: 200 }), + slow_memory: true, + state: crate::state::steam_deck::Gpu::default(), + } + } +} + +const PPT_DIVISOR: u64 = 1_000_000; + +impl TGpu for Gpu { + fn limits(&self) -> crate::api::GpuLimits { + let max = Self::max(); + let max_clock_limits = max.clock_limits.unwrap(); + + let min = Self::min(); + let min_clock_limits = min.clock_limits.unwrap(); + crate::api::GpuLimits { + fast_ppt_limits: Some(RangeLimit { + min: min.fast_ppt.unwrap() / PPT_DIVISOR, + max: max.fast_ppt.unwrap() / PPT_DIVISOR, + }), + slow_ppt_limits: Some(RangeLimit { + min: min.slow_ppt.unwrap() / PPT_DIVISOR, + max: max.slow_ppt.unwrap() / PPT_DIVISOR, + }), + ppt_step: 1, + tdp_limits: None, + tdp_boost_limits: None, + tdp_step: 42, + clock_min_limits: Some(RangeLimit { + min: min_clock_limits.min, + max: max_clock_limits.max, + }), + clock_max_limits: Some(RangeLimit { + min: min_clock_limits.min, + max: max_clock_limits.max, + }), + clock_step: 100, + memory_control_capable: true, + } + } + + fn json(&self) -> crate::persist::GpuJson { + self.clone().into() + } + + fn ppt(&mut self, fast: Option, slow: Option) { + self.fast_ppt = fast.map(|x| x * PPT_DIVISOR); + self.slow_ppt = slow.map(|x| x * PPT_DIVISOR); + } + + fn get_ppt(&self) -> (Option, Option) { + (self.fast_ppt.map(|x| x / PPT_DIVISOR), self.slow_ppt.map(|x| x / PPT_DIVISOR)) + } + + fn clock_limits(&mut self, limits: Option>) { + self.clock_limits = limits; + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.clock_limits.as_ref() + } + + fn slow_memory(&mut self) -> &mut bool { + &mut self.slow_memory + } +} + +#[inline] +fn gpu_power_path(power_number: u8) -> String { + format!("/sys/class/hwmon/hwmon4/power{}_cap", power_number) +} diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs new file mode 100644 index 0000000..2039cae --- /dev/null +++ b/backend/src/settings/steam_deck/mod.rs @@ -0,0 +1,7 @@ +mod battery; +mod cpu; +mod gpu; + +pub use battery::Battery; +pub use cpu::{Cpu, Cpus}; +pub use gpu::Gpu; diff --git a/backend/src/settings/steam_deck_adv/battery.rs b/backend/src/settings/steam_deck_adv/battery.rs new file mode 100644 index 0000000..a002bca --- /dev/null +++ b/backend/src/settings/steam_deck_adv/battery.rs @@ -0,0 +1,216 @@ +use std::convert::Into; + +use crate::api::RangeLimit; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::TBattery; +use crate::persist::BatteryJson; + +#[derive(Debug, Clone)] +pub struct Battery { + pub charge_rate: Option, + state: crate::state::steam_deck::Battery, +} + +const BATTERY_VOLTAGE: f64 = 7.7; + +const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only +const BATTERY_CURRENT_NOW_PATH: &str = "/sys/class/power_supply/BAT1/current_now"; // read-only +const BATTERY_CHARGE_NOW_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_now"; // read-only +const BATTERY_CHARGE_FULL_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full"; // read-only +const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full_design"; // read-only + +impl Battery { + #[inline] + pub fn from_json(other: BatteryJson, version: u64) -> Self { + match version { + 0 => Self { + charge_rate: other.charge_rate, + state: crate::state::steam_deck::Battery::default(), + }, + _ => Self { + charge_rate: other.charge_rate, + state: crate::state::steam_deck::Battery::default(), + }, + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + if let Some(charge_rate) = self.charge_rate { + self.state.charge_rate_set = true; + usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( + |e| SettingError { + msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }, + ) + } else if self.state.charge_rate_set { + self.state.charge_rate_set = false; + usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, Self::max().charge_rate.unwrap()).map_err( + |e| SettingError { + msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }, + ) + } else { + Ok(()) + } + } + + fn clamp_all(&mut self) { + let min = Self::min(); + let max = Self::max(); + if let Some(charge_rate) = &mut self.charge_rate { + *charge_rate = (*charge_rate).clamp(min.charge_rate.unwrap(), max.charge_rate.unwrap()); + } + } + + pub fn read_current_now() -> Result { + match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) { + Err((Some(e), None)) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err((None, Some(e))) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err(_) => panic!( + "Invalid error while reading from `{}`", + BATTERY_CURRENT_NOW_PATH + ), + // this value is in uA, while it's set in mA + // so convert this to mA for consistency + Ok(val) => Ok(val / 1000), + } + } + + pub fn read_charge_now() -> Result { + match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) { + Err((Some(e), None)) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err((None, Some(e))) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err(_) => panic!( + "Invalid error while reading from `{}`", + BATTERY_CHARGE_NOW_PATH + ), + // convert to Wh + Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), + } + } + + pub fn read_charge_full() -> Result { + match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) { + Err((Some(e), None)) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err((None, Some(e))) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err(_) => panic!( + "Invalid error while reading from `{}`", + BATTERY_CHARGE_NOW_PATH + ), + // convert to Wh + Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), + } + } + + pub fn read_charge_design() -> Result { + match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { + Err((Some(e), None)) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err((None, Some(e))) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), + setting: crate::settings::SettingVariant::Battery, + }), + Err(_) => panic!( + "Invalid error while reading from `{}`", + BATTERY_CHARGE_NOW_PATH + ), + // convert to Wh + Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), + } + } + + pub fn system_default() -> Self { + Self { + charge_rate: None, + state: crate::state::steam_deck::Battery::default(), + } + } +} + +impl Into for Battery { + #[inline] + fn into(self) -> BatteryJson { + BatteryJson { + charge_rate: self.charge_rate, + } + } +} + +impl OnSet for Battery { + fn on_set(&mut self) -> Result<(), SettingError> { + self.clamp_all(); + self.set_all() + } +} + +impl OnResume for Battery { + fn on_resume(&self) -> Result<(), SettingError> { + self.clone().set_all() + } +} + +impl SettingsRange for Battery { + #[inline] + fn max() -> Self { + Self { + charge_rate: Some(2500), + state: crate::state::steam_deck::Battery::default(), + } + } + + #[inline] + fn min() -> Self { + Self { + charge_rate: Some(250), + state: crate::state::steam_deck::Battery::default(), + } + } +} + +impl TBattery for Battery { + fn limits(&self) -> crate::api::BatteryLimits { + let max = Self::max(); + let min = Self::min(); + crate::api::BatteryLimits { + charge_rate: Some(RangeLimit{ + min: min.charge_rate.unwrap(), + max: max.charge_rate.unwrap(), + }), + charge_step: 50, + } + } + + fn json(&self) -> crate::persist::BatteryJson { + self.clone().into() + } + + fn charge_rate(&mut self, rate: Option) { + self.charge_rate = rate; + } + + fn get_charge_rate(&self) -> Option { + self.charge_rate + } +} diff --git a/backend/src/settings/cpu.rs b/backend/src/settings/steam_deck_adv/cpu.rs similarity index 79% rename from backend/src/settings/cpu.rs rename to backend/src/settings/steam_deck_adv/cpu.rs index b2d1efe..1d04a27 100644 --- a/backend/src/settings/cpu.rs +++ b/backend/src/settings/steam_deck_adv/cpu.rs @@ -1,7 +1,9 @@ use std::convert::Into; -use super::MinMax; -use super::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::api::RangeLimit; +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::{TCpus, TCpu}; use crate::persist::CpuJson; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; @@ -25,7 +27,7 @@ impl OnSet for Cpus { "Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; } else { @@ -35,7 +37,7 @@ impl OnSet for Cpus { "Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; } @@ -129,13 +131,35 @@ impl Cpus { } } +impl TCpus for Cpus { + fn limits(&self) -> crate::api::CpusLimits { + crate::api::CpusLimits { + cpus: self.cpus.iter().map(|x| x.limits()).collect(), + count: self.cpus.len(), + smt_capable: self.smt_capable, + } + } + + fn json(&self) -> Vec { + self.cpus.iter().map(|x| x.to_owned().into()).collect() + } + + fn cpus(&mut self) -> Vec<&mut dyn TCpu> { + self.cpus.iter_mut().map(|x| x as &mut dyn TCpu).collect() + } + + fn len(&self) -> usize { + self.cpus.len() + } +} + #[derive(Debug, Clone)] pub struct Cpu { pub online: bool, pub clock_limits: Option>, pub governor: String, index: usize, - state: crate::state::Cpu, + state: crate::state::steam_deck::Cpu, } const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; @@ -150,14 +174,14 @@ impl Cpu { clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), governor: other.governor, index: i, - state: crate::state::Cpu::default(), + state: crate::state::steam_deck::Cpu::default(), }, _ => Self { online: other.online, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), governor: other.governor, index: i, - state: crate::state::Cpu::default(), + state: crate::state::steam_deck::Cpu::default(), }, } } @@ -169,7 +193,7 @@ impl Cpu { usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { SettingError { msg: format!("Failed to write to `{}`: {}", &online_path, e), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; } @@ -184,7 +208,7 @@ impl Cpu { "Failed to write `manual` to `{}`: {}", CPU_FORCE_LIMITS_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; } @@ -199,7 +223,7 @@ impl Cpu { "Failed to write `{}` to `{}`: {}", &payload_max, CPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, }, )?; // min clock @@ -210,7 +234,7 @@ impl Cpu { "Failed to write `{}` to `{}`: {}", &payload_min, CPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, }, )?; } else if self.state.clock_limits_set || self.state.is_resuming { @@ -225,7 +249,7 @@ impl Cpu { "Failed to write `{}` to `{}`: {}", &payload_max, CPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, }, )?; // min clock @@ -236,7 +260,7 @@ impl Cpu { "Failed to write `{}` to `{}`: {}", &payload_min, CPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, }, )?; } @@ -244,7 +268,7 @@ impl Cpu { usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { SettingError { msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; @@ -257,7 +281,7 @@ impl Cpu { "Failed to write `{}` to `{}`: {}", &self.governor, &governor_path, e ), - setting: super::SettingVariant::Cpu, + setting: crate::settings::SettingVariant::Cpu, } })?; } @@ -275,14 +299,34 @@ impl Cpu { } } - fn from_sys(index: usize) -> Self { + fn from_sys(cpu_index: usize) -> Self { Self { - online: usdpl_back::api::files::read_single(cpu_online_path(index)).unwrap_or(1u8) != 0, + online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, clock_limits: None, - governor: usdpl_back::api::files::read_single(cpu_governor_path(index)) + governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) .unwrap_or("schedutil".to_owned()), - index: index, - state: crate::state::Cpu::default(), + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } + } + + fn limits(&self) -> crate::api::CpuLimits { + let max = Self::max(); + let max_clocks = max.clock_limits.unwrap(); + + let min = Self::min(); + let min_clocks = min.clock_limits.unwrap(); + crate::api::CpuLimits { + clock_min_limits: Some(RangeLimit { + min: min_clocks.min, + max: max_clocks.min + }), + clock_max_limits: Some(RangeLimit { + min: min_clocks.max, + max: max_clocks.max + }), + clock_step: 100, + governors: vec![], // TODO } } } @@ -313,6 +357,28 @@ impl OnResume for Cpu { } } +impl TCpu for Cpu { + fn online(&mut self) -> &mut bool { + &mut self.online + } + + fn governor(&mut self, governor: String) { + self.governor = governor; + } + + fn get_governor(&self) -> &'_ str { + &self.governor + } + + fn clock_limits(&mut self, limits: Option>) { + self.clock_limits = limits; + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.clock_limits.as_ref() + } +} + impl SettingsRange for Cpu { #[inline] fn max() -> Self { @@ -324,7 +390,7 @@ impl SettingsRange for Cpu { }), governor: "schedutil".to_owned(), index: usize::MAX, - state: crate::state::Cpu::default(), + state: crate::state::steam_deck::Cpu::default(), } } @@ -335,7 +401,7 @@ impl SettingsRange for Cpu { clock_limits: Some(MinMax { max: 500, min: 1400 }), governor: "schedutil".to_owned(), index: usize::MIN, - state: crate::state::Cpu::default(), + state: crate::state::steam_deck::Cpu::default(), } } } diff --git a/backend/src/settings/gpu.rs b/backend/src/settings/steam_deck_adv/gpu.rs similarity index 72% rename from backend/src/settings/gpu.rs rename to backend/src/settings/steam_deck_adv/gpu.rs index 3a3b15a..fccd598 100644 --- a/backend/src/settings/gpu.rs +++ b/backend/src/settings/steam_deck_adv/gpu.rs @@ -1,7 +1,9 @@ use std::convert::Into; -use super::MinMax; -use super::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::api::RangeLimit; +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::TGpu; use crate::persist::GpuJson; const SLOW_PPT: u8 = 1; @@ -13,7 +15,7 @@ pub struct Gpu { pub slow_ppt: Option, pub clock_limits: Option>, pub slow_memory: bool, - state: crate::state::Gpu, + state: crate::state::steam_deck::Gpu, } // same as CPU @@ -30,14 +32,14 @@ impl Gpu { slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), slow_memory: other.slow_memory, - state: crate::state::Gpu::default(), + state: crate::state::steam_deck::Gpu::default(), }, _ => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), slow_memory: other.slow_memory, - state: crate::state::Gpu::default(), + state: crate::state::steam_deck::Gpu::default(), }, } } @@ -52,7 +54,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", fast_ppt, &fast_ppt_path, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, } })?; } @@ -65,7 +67,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", slow_ppt, &slow_ppt_path, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, } })?; } @@ -79,7 +81,7 @@ impl Gpu { "Failed to write `manual` to `{}`: {}", GPU_FORCE_LIMITS_PATH, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, } })?; } @@ -87,7 +89,7 @@ impl Gpu { usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) .map_err(|e| SettingError { msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, })?; if let Some(clock_limits) = &self.clock_limits { // set clock limits @@ -100,7 +102,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", &payload_max, GPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, }, )?; // min clock @@ -111,7 +113,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", &payload_min, GPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, }, )?; } else if self.state.clock_limits_set || self.state.is_resuming { @@ -125,7 +127,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", &payload_max, GPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, }, )?; // min clock @@ -136,7 +138,7 @@ impl Gpu { "Failed to write `{}` to `{}`: {}", &payload_min, GPU_CLOCK_LIMITS_PATH, e ), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, }, )?; } @@ -144,7 +146,7 @@ impl Gpu { usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { SettingError { msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: super::SettingVariant::Gpu, + setting: crate::settings::SettingVariant::Gpu, } })?; @@ -180,7 +182,7 @@ impl Gpu { slow_ppt: None, clock_limits: None, slow_memory: false, - state: crate::state::Gpu::default(), + state: crate::state::steam_deck::Gpu::default(), } } } @@ -216,14 +218,14 @@ impl SettingsRange for Gpu { #[inline] fn max() -> Self { Self { - fast_ppt: Some(30000000), - slow_ppt: Some(29000000), + fast_ppt: Some(30_000_000), + slow_ppt: Some(29_000_000), clock_limits: Some(MinMax { min: 1600, max: 1600, }), slow_memory: false, - state: crate::state::Gpu::default(), + state: crate::state::steam_deck::Gpu::default(), } } @@ -234,11 +236,70 @@ impl SettingsRange for Gpu { slow_ppt: Some(1000000), clock_limits: Some(MinMax { min: 200, max: 200 }), slow_memory: true, - state: crate::state::Gpu::default(), + state: crate::state::steam_deck::Gpu::default(), } } } +impl TGpu for Gpu { + fn limits(&self) -> crate::api::GpuLimits { + let max = Self::max(); + let max_clock_limits = max.clock_limits.unwrap(); + + let min = Self::min(); + let min_clock_limits = min.clock_limits.unwrap(); + crate::api::GpuLimits { + fast_ppt_limits: Some(RangeLimit { + min: min.fast_ppt.unwrap(), + max: max.fast_ppt.unwrap(), + }), + slow_ppt_limits: Some(RangeLimit { + min: min.slow_ppt.unwrap(), + max: max.slow_ppt.unwrap(), + }), + ppt_step: 1_000_000, + tdp_limits: None, + tdp_boost_limits: None, + tdp_step: 42, + clock_min_limits: Some(RangeLimit { + min: min_clock_limits.min, + max: max_clock_limits.max, + }), + clock_max_limits: Some(RangeLimit { + min: min_clock_limits.min, + max: max_clock_limits.max, + }), + clock_step: 100, + memory_control_capable: true, + } + } + + fn json(&self) -> crate::persist::GpuJson { + self.clone().into() + } + + fn ppt(&mut self, fast: Option, slow: Option) { + self.fast_ppt = fast; + self.slow_ppt = slow; + } + + fn get_ppt(&self) -> (Option, Option) { + (self.fast_ppt, self.slow_ppt) + } + + fn clock_limits(&mut self, limits: Option>) { + self.clock_limits = limits; + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.clock_limits.as_ref() + } + + fn slow_memory(&mut self) -> &mut bool { + &mut self.slow_memory + } +} + #[inline] fn gpu_power_path(power_number: u8) -> String { format!("/sys/class/hwmon/hwmon4/power{}_cap", power_number) diff --git a/backend/src/settings/steam_deck_adv/mod.rs b/backend/src/settings/steam_deck_adv/mod.rs new file mode 100644 index 0000000..2039cae --- /dev/null +++ b/backend/src/settings/steam_deck_adv/mod.rs @@ -0,0 +1,7 @@ +mod battery; +mod cpu; +mod gpu; + +pub use battery::Battery; +pub use cpu::{Cpu, Cpus}; +pub use gpu::Gpu; diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index 56450df..8c49385 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -1,4 +1,6 @@ +use std::fmt::Debug; use super::SettingError; +use super::MinMax; pub trait OnSet { fn on_set(&mut self) -> Result<(), SettingError>; @@ -12,3 +14,69 @@ pub trait SettingsRange { fn max() -> Self; fn min() -> Self; } + +pub trait TGpu: OnResume + OnSet + Debug + Send { + fn limits(&self) -> crate::api::GpuLimits; + + fn json(&self) -> crate::persist::GpuJson; + + fn ppt(&mut self, fast: Option, slow: Option); + + fn get_ppt(&self) -> (Option, Option); + + fn clock_limits(&mut self, limits: Option>); + + fn get_clock_limits(&self) -> Option<&MinMax>; + + fn slow_memory(&mut self) -> &mut bool; +} + +pub trait TCpus: OnResume + OnSet + Debug + Send { + fn limits(&self) -> crate::api::CpusLimits; + + fn json(&self) -> Vec; + + fn cpus(&mut self) -> Vec<&mut dyn TCpu>; + + fn len(&self) -> usize; +} + +pub trait TCpu: Debug + Send { + fn online(&mut self) -> &mut bool; + + fn governor(&mut self, governor: String); + + fn get_governor(&self) -> &'_ str; + + fn clock_limits(&mut self, limits: Option>); + + fn get_clock_limits(&self) -> Option<&MinMax>; +} + +pub trait TGeneral: OnResume + OnSet + Debug + Send { + fn limits(&self) -> crate::api::GeneralLimits; + + fn get_persistent(&self) -> bool; + + fn persistent(&mut self) -> &'_ mut bool; + + fn get_path(&self) -> &'_ std::path::Path; + + fn path(&mut self, path: std::path::PathBuf); + + fn get_name(&self) -> &'_ str; + + fn name(&mut self, name: String); + + fn provider(&self) -> crate::persist::DriverJson; +} + +pub trait TBattery: OnResume + OnSet + Debug + Send { + fn limits(&self) -> crate::api::BatteryLimits; + + fn json(&self) -> crate::persist::BatteryJson; + + fn charge_rate(&mut self, rate: Option); + + fn get_charge_rate(&self) -> Option; +} diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs new file mode 100644 index 0000000..e2cca2f --- /dev/null +++ b/backend/src/settings/unknown/battery.rs @@ -0,0 +1,49 @@ +use std::convert::Into; + +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::TBattery; +use crate::persist::BatteryJson; + +#[derive(Debug, Clone)] +pub struct Battery; + +impl Into for Battery { + #[inline] + fn into(self) -> BatteryJson { + BatteryJson { + charge_rate: None, + } + } +} + +impl OnSet for Battery { + fn on_set(&mut self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl OnResume for Battery { + fn on_resume(&self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl TBattery for Battery { + fn limits(&self) -> crate::api::BatteryLimits { + crate::api::BatteryLimits { + charge_rate: None, + charge_step: 50, + } + } + + fn json(&self) -> crate::persist::BatteryJson { + self.clone().into() + } + + fn charge_rate(&mut self, _rate: Option) { + } + + fn get_charge_rate(&self) -> Option { + None + } +} diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs new file mode 100644 index 0000000..48d4b99 --- /dev/null +++ b/backend/src/settings/unknown/cpu.rs @@ -0,0 +1,289 @@ +use std::convert::Into; + +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{TCpus, TCpu}; +use crate::persist::CpuJson; + +const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; +const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; + +#[derive(Debug, Clone)] +pub struct Cpus { + pub cpus: Vec, + pub smt: bool, + pub smt_capable: bool, +} + +impl OnSet for Cpus { + fn on_set(&mut self) -> Result<(), SettingError> { + if self.smt_capable { + // toggle SMT + if self.smt { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `on` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } else { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `off` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + } + for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { + cpu.state.do_set_online = self.smt || i % 2 == 0; + cpu.on_set()?; + } + Ok(()) + } +} + +impl OnResume for Cpus { + fn on_resume(&self) -> Result<(), SettingError> { + for cpu in &self.cpus { + cpu.on_resume()?; + } + Ok(()) + } +} + +impl Cpus { + pub fn cpu_count() -> Option { + let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) + .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); + if let Some(dash_index) = data.find('-') { + let data = data.split_off(dash_index + 1); + if let Ok(max_cpu) = data.parse::() { + return Some(max_cpu + 1); + } + } + log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); + None + } + + fn system_smt_capabilities() -> (bool, bool) { + match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { + Ok(val) => (val.trim().to_lowercase() == "on", true), + Err(_) => (false, false) + } + } + + pub fn system_default() -> Self { + if let Some(max_cpu) = Self::cpu_count() { + let mut sys_cpus = Vec::with_capacity(max_cpu); + for i in 0..max_cpu { + sys_cpus.push(Cpu::from_sys(i)); + } + let (smt_status, can_smt) = Self::system_smt_capabilities(); + Self { + cpus: sys_cpus, + smt: smt_status, + smt_capable: can_smt, + } + } else { + Self { + cpus: vec![], + smt: false, + smt_capable: false, + } + } + } + + #[inline] + pub fn from_json(mut other: Vec, version: u64) -> Self { + let (_, can_smt) = Self::system_smt_capabilities(); + let mut result = Vec::with_capacity(other.len()); + let max_cpus = Self::cpu_count(); + for (i, cpu) in other.drain(..).enumerate() { + // prevent having more CPUs than available + if let Some(max_cpus) = max_cpus { + if i == max_cpus { + break; + } + } + result.push(Cpu::from_json(cpu, version, i)); + } + if let Some(max_cpus) = max_cpus { + if result.len() != max_cpus { + let mut sys_cpus = Cpus::system_default(); + for i in result.len()..sys_cpus.cpus.len() { + result.push(sys_cpus.cpus.remove(i)); + } + } + } + Self { + cpus: result, + smt: true, + smt_capable: can_smt, + } + } +} + +impl TCpus for Cpus { + fn limits(&self) -> crate::api::CpusLimits { + crate::api::CpusLimits { + cpus: self.cpus.iter().map(|x| x.limits()).collect(), + count: self.cpus.len(), + smt_capable: self.smt_capable, + } + } + + fn json(&self) -> Vec { + self.cpus.iter().map(|x| x.to_owned().into()).collect() + } + + fn cpus(&mut self) -> Vec<&mut dyn TCpu> { + self.cpus.iter_mut().map(|x| x as &mut dyn TCpu).collect() + } + + fn len(&self) -> usize { + self.cpus.len() + } +} + +#[derive(Debug, Clone)] +pub struct Cpu { + pub online: bool, + pub governor: String, + index: usize, + state: crate::state::steam_deck::Cpu, +} + + +impl Cpu { + #[inline] + pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { + match version { + 0 => Self { + online: other.online, + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + _ => Self { + online: other.online, + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + // set cpu online/offline + if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled + let online_path = cpu_online_path(self.index); + usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", &online_path, e), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + + // set governor + if self.index == 0 || self.online { + let governor_path = cpu_governor_path(self.index); + usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &self.governor, &governor_path, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + Ok(()) + } + + fn from_sys(cpu_index: usize) -> Self { + Self { + online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, + governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) + .unwrap_or("schedutil".to_owned()), + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } + } + + fn limits(&self) -> crate::api::CpuLimits { + crate::api::CpuLimits { + clock_min_limits: None, + clock_max_limits: None, + clock_step: 100, + governors: vec![], // TODO + } + } +} + +impl Into for Cpu { + #[inline] + fn into(self) -> CpuJson { + CpuJson { + online: self.online, + clock_limits: None, + governor: self.governor, + } + } +} + +impl OnSet for Cpu { + fn on_set(&mut self) -> Result<(), SettingError> { + //self.clamp_all(); + self.set_all() + } +} + +impl OnResume for Cpu { + fn on_resume(&self) -> Result<(), SettingError> { + let mut copy = self.clone(); + copy.state.is_resuming = true; + copy.set_all() + } +} + +impl TCpu for Cpu { + fn online(&mut self) -> &mut bool { + &mut self.online + } + + fn governor(&mut self, governor: String) { + self.governor = governor; + } + + fn get_governor(&self) -> &'_ str { + &self.governor + } + + fn clock_limits(&mut self, _limits: Option>) { + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + None + } +} + +#[inline] +fn cpu_online_path(index: usize) -> String { + format!("/sys/devices/system/cpu/cpu{}/online", index) +} + +#[inline] +fn cpu_governor_path(index: usize) -> String { + format!( + "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor", + index + ) +} diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs new file mode 100644 index 0000000..9733cc8 --- /dev/null +++ b/backend/src/settings/unknown/gpu.rs @@ -0,0 +1,89 @@ +use std::convert::Into; + +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::TGpu; +use crate::persist::GpuJson; + +#[derive(Debug, Clone)] +pub struct Gpu { + slow_memory: bool, // ignored +} + +impl Gpu { + #[inline] + pub fn from_json(_other: GpuJson, _version: u64) -> Self { + Self { + slow_memory: false, + } + } + + pub fn system_default() -> Self { + Self { + slow_memory: false, + } + } +} + +impl Into for Gpu { + #[inline] + fn into(self) -> GpuJson { + GpuJson { + fast_ppt: None, + slow_ppt: None, + clock_limits: None, + slow_memory: false, + } + } +} + +impl OnSet for Gpu { + fn on_set(&mut self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl OnResume for Gpu { + fn on_resume(&self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl TGpu for Gpu { + fn limits(&self) -> crate::api::GpuLimits { + crate::api::GpuLimits { + fast_ppt_limits: None, + slow_ppt_limits: None, + ppt_step: 1_000_000, + tdp_limits: None, + tdp_boost_limits: None, + tdp_step: 42, + clock_min_limits: None, + clock_max_limits: None, + clock_step: 100, + memory_control_capable: false, + } + } + + fn json(&self) -> crate::persist::GpuJson { + self.clone().into() + } + + fn ppt(&mut self, _fast: Option, _slow: Option) { + } + + fn get_ppt(&self) -> (Option, Option) { + (None, None) + } + + fn clock_limits(&mut self, _limits: Option>) { + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + None + } + + fn slow_memory(&mut self) -> &mut bool { + &mut self.slow_memory + } +} diff --git a/backend/src/settings/unknown/mod.rs b/backend/src/settings/unknown/mod.rs new file mode 100644 index 0000000..2039cae --- /dev/null +++ b/backend/src/settings/unknown/mod.rs @@ -0,0 +1,7 @@ +mod battery; +mod cpu; +mod gpu; + +pub use battery::Battery; +pub use cpu::{Cpu, Cpus}; +pub use gpu::Gpu; diff --git a/backend/src/state/mod.rs b/backend/src/state/mod.rs index 1eb1e58..72ca58f 100644 --- a/backend/src/state/mod.rs +++ b/backend/src/state/mod.rs @@ -1,11 +1,7 @@ -mod battery; -mod cpu; mod error; -mod gpu; mod traits; -pub use battery::Battery; -pub use cpu::Cpu; +pub mod steam_deck; + pub use error::StateError; -pub use gpu::Gpu; pub use traits::OnPoll; diff --git a/backend/src/state/battery.rs b/backend/src/state/steam_deck/battery.rs similarity index 100% rename from backend/src/state/battery.rs rename to backend/src/state/steam_deck/battery.rs diff --git a/backend/src/state/cpu.rs b/backend/src/state/steam_deck/cpu.rs similarity index 100% rename from backend/src/state/cpu.rs rename to backend/src/state/steam_deck/cpu.rs diff --git a/backend/src/state/gpu.rs b/backend/src/state/steam_deck/gpu.rs similarity index 100% rename from backend/src/state/gpu.rs rename to backend/src/state/steam_deck/gpu.rs diff --git a/backend/src/state/steam_deck/mod.rs b/backend/src/state/steam_deck/mod.rs new file mode 100644 index 0000000..c7dca59 --- /dev/null +++ b/backend/src/state/steam_deck/mod.rs @@ -0,0 +1,7 @@ +mod battery; +mod cpu; +mod gpu; + +pub use battery::Battery; +pub use cpu::Cpu; +pub use gpu::Gpu; diff --git a/src/backend.ts b/src/backend.ts index 2e50f60..d985380 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -24,6 +24,50 @@ export async function initBackend() { //setReady(true); } +// API limit types + +export type RangeLimit = { + min: number; + max: number; +}; + +export type SettingsLimits = { + battery: BatteryLimits; + cpu: CpusLimits; + gpu: GpuLimits; + general: GeneralLimits; +}; + +export type BatteryLimits = { + charge_rate: RangeLimit | null; + charge_step: number; +}; + +export type CpuLimits = { + clock_min_limits: RangeLimit | null; + clock_max_limits: RangeLimit | null; + clock_step: number; + governors: string[]; +}; + +export type CpusLimits = { + cpus: CpuLimits[]; + count: number; + smt_capable: boolean; +}; + +export type GeneralLimits = {}; + +export type GpuLimits = { + fast_ppt_limits: RangeLimit | null; + slow_ppt_limits: RangeLimit | null; + ppt_step: number; + clock_min_limits: RangeLimit | null; + clock_max_limits: RangeLimit | null; + clock_step: number; + memory_control_capable: boolean; +}; + // API export async function getInfo(): Promise { @@ -66,9 +110,9 @@ export async function setCpuSmt(status: boolean): Promise { return (await call_backend("CPU_set_smt", [status]))[0]; } -export async function getCpuCount(): Promise { +/*export async function getCpuCount(): Promise { return (await call_backend("CPU_count", []))[0]; -} +}*/ export async function setCpuOnline(index: number, online: boolean): Promise { return (await call_backend("CPU_set_online", [index, online]))[0]; @@ -165,3 +209,7 @@ export async function getGeneralSettingsName(): Promise { export async function waitForComplete(): Promise { return (await call_backend("GENERAL_wait_for_unlocks", []))[0]; } + +export async function getLimits(): Promise { + return (await call_backend("GENERAL_get_limits", []))[0]; +} diff --git a/src/index.tsx b/src/index.tsx index 8a33f52..98352c4 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,7 +6,7 @@ import { //MenuItem, PanelSection, PanelSectionRow, - //Router, + Router, ServerAPI, //showContextMenu, staticClasses, @@ -17,8 +17,8 @@ import { //DropdownOption, SingleDropdownOption, //NotchLabel - gamepadDialogClasses, - joinClassNames, + //gamepadDialogClasses, + //joinClassNames, } from "decky-frontend-lib"; import { VFC, useState } from "react"; import { GiDrill } from "react-icons/gi"; @@ -32,7 +32,9 @@ var lifetimeHook: any = null; var startHook: any = null; var usdplReady = false; -var smtAllowed = true; +var eggCount = 0; + +//var smtAllowed = true; var advancedMode = false; var advancedCpu = 1; @@ -41,44 +43,19 @@ type MinMax = { max: number | null; } -const governorOptions: SingleDropdownOption[] = [ - { - data: "conservative", - label: conservative, - }, - { - data: "ondemand", - label: ondemand, - }, - { - data: "userspace", - label: userspace, - }, - { - data: "powersave", - label: powersave, - }, - { - data: "performance", - label: performance, - }, - { - data: "schedutil", - label: schedutil, - }, -]; - // usdpl persistent store keys const BACKEND_INFO = "VINFO"; +const LIMITS_INFO = "LIMITS_all"; + const CURRENT_BATT = "BATTERY_current_now"; const CHARGE_RATE_BATT = "BATTERY_charge_rate"; const CHARGE_NOW_BATT = "BATTERY_charge_now"; const CHARGE_FULL_BATT = "BATTERY_charge_full"; const CHARGE_DESIGN_BATT = "BATTERY_charge_design" -const TOTAL_CPUS = "CPUs_total"; +//const TOTAL_CPUS = "CPUs_total"; const ONLINE_CPUS = "CPUs_online"; const ONLINE_STATUS_CPUS = "CPUs_status_online"; const SMT_CPU = "CPUs_SMT"; @@ -107,7 +84,7 @@ function countCpus(statii: boolean[]): number { } function syncPlebClockToAdvanced() { - const cpuCount = get_value(TOTAL_CPUS); + const cpuCount = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.count; const minClock = get_value(CLOCK_MIN_CPU); const maxClock = get_value(CLOCK_MAX_CPU); let clockArr = []; @@ -123,18 +100,23 @@ function syncPlebClockToAdvanced() { const reload = function() { if (!usdplReady) {return;} + backend.resolve(backend.getLimits(), (limits) => { + set_value(LIMITS_INFO, limits); + console.debug("POWERTOOLS: got limits", limits); + }); + backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) }); backend.resolve(backend.getBatteryChargeRate(), (rate: number) => { set_value(CHARGE_RATE_BATT, rate) }); backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) }); backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) }); backend.resolve(backend.getBatteryChargeDesign(), (rate: number) => { set_value(CHARGE_DESIGN_BATT, rate) }); - backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)}); + //backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)}); backend.resolve(backend.getCpusOnline(), (statii: boolean[]) => { set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); - set_value(SMT_CPU, statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3] && smtAllowed); + set_value(SMT_CPU, statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3]); }); backend.resolve(backend.getCpuClockLimits(0), (limits: number[]) => { set_value(CLOCK_MIN_CPU, limits[0]); @@ -144,7 +126,6 @@ const reload = function() { backend.resolve(backend.getCpusGovernor(), (governors: string[]) => { set_value(GOVERNOR_CPU, governors); console.log("POWERTOOLS: Governors from backend", governors); - console.log("POWERTOOLS: Governors in dropdown", governorOptions); }); backend.resolve(backend.getGpuPpt(), (ppts: number[]) => { @@ -226,10 +207,16 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { reloadGUI("periodic" + (new Date()).getTime().toString()); }, 1000); - const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard); + //const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard); - const total_cpus = get_value(TOTAL_CPUS); + const total_cpus = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.count ?? 8; const advancedCpuIndex = advancedCpu - 1; + const smtAllowed = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.smt_capable ?? true; + + const governorOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.map((elem) => {return { + data: elem, + label: {elem}, + };}); return ( @@ -280,7 +267,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Threads" value={get_value(ONLINE_CPUS)} step={1} - max={get_value(SMT_CPU)? total_cpus : total_cpus/2} + max={get_value(SMT_CPU) || !smtAllowed ? total_cpus : total_cpus/2} min={1} showValue={true} onChange={(cpus: number) => { @@ -307,13 +294,17 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } {!advancedMode && { if (value) { - set_value(CLOCK_MIN_CPU, 1400); - set_value(CLOCK_MAX_CPU, 3500); + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { + set_value(CLOCK_MIN_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits!.min); + } + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null) { + set_value(CLOCK_MAX_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits!.max); + } syncPlebClockToAdvanced(); reloadGUI("CPUFreqToggle"); } else { @@ -330,13 +321,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} /> } - {!advancedMode && + {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null && {get_value(CLOCK_MIN_CPU) != null && { @@ -360,13 +351,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} } - {!advancedMode && + {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null && {get_value(CLOCK_MAX_CPU) != null && { @@ -393,10 +384,10 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {/* CPU advanced mode */} {advancedMode && { @@ -406,9 +397,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } {advancedMode && { console.debug("CPU " + advancedCpu.toString() + " is now " + status.toString()); if (get_value(SMT_CPU)) { @@ -426,14 +417,19 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } {advancedMode && { if (value) { const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = 1400; - clocks[advancedCpuIndex].max = 3500; + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null) { + clocks[advancedCpuIndex].min = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits!.min; + } + + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null) { + clocks[advancedCpuIndex].max = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits!.max; + } set_value(CLOCK_MIN_MAX_CPU, clocks); reloadGUI("CPUFreqToggle"); } else { @@ -448,13 +444,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} /> } - {advancedMode && + {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null && {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min != null && { @@ -473,13 +469,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} } - {advancedMode && + {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null && {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max != null && { @@ -498,7 +494,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} } - {advancedMode && + {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.length != 0 && @@ -527,15 +523,20 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
GPU
- + { ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null ||(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) && { if (value) { - set_value(SLOW_PPT_GPU, 15000000); - set_value(FAST_PPT_GPU, 15000000); + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) { + set_value(SLOW_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits!.max); + } + + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null) { + set_value(FAST_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits!.max); + } reloadGUI("GPUPPTToggle"); } else { set_value(SLOW_PPT_GPU, null); @@ -546,21 +547,22 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} /> - + } { get_value(SLOW_PPT_GPU) != null && { console.debug("SlowPPT is now " + ppt.toString()); const pptNow = get_value(SLOW_PPT_GPU); - if (ppt != pptNow) { - backend.resolve(backend.setGpuPpt(get_value(FAST_PPT_GPU), ppt), + const realPpt = ppt; + if (realPpt != pptNow) { + backend.resolve(backend.setGpuPpt(get_value(FAST_PPT_GPU), realPpt), (limits: number[]) => { set_value(FAST_PPT_GPU, limits[0]); set_value(SLOW_PPT_GPU, limits[1]); @@ -572,18 +574,19 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {get_value(FAST_PPT_GPU) != null && { console.debug("FastPPT is now " + ppt.toString()); const pptNow = get_value(FAST_PPT_GPU); - if (ppt != pptNow) { - backend.resolve(backend.setGpuPpt(get_value(SLOW_PPT_GPU), ppt), + const realPpt = ppt; + if (realPpt != pptNow) { + backend.resolve(backend.setGpuPpt(realPpt, get_value(SLOW_PPT_GPU)), (limits: number[]) => { set_value(FAST_PPT_GPU, limits[0]); set_value(SLOW_PPT_GPU, limits[1]); @@ -593,15 +596,21 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} - + {((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits != null || (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits != null) && { if (value) { - set_value(CLOCK_MIN_GPU, 200); - set_value(CLOCK_MAX_GPU, 1600); + let clock_min_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits; + let clock_max_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits; + if (clock_min_limits != null) { + set_value(CLOCK_MIN_GPU, clock_min_limits.min); + } + if (clock_max_limits != null) { + set_value(CLOCK_MAX_GPU, clock_max_limits.max); + } reloadGUI("GPUFreqToggle"); } else { set_value(CLOCK_MIN_GPU, null); @@ -612,14 +621,14 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} /> - + } { get_value(CLOCK_MIN_GPU) != null && { @@ -640,9 +649,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {get_value(CLOCK_MAX_GPU) != null && { @@ -659,7 +668,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} - + {(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control_capable && = ({}) => { }) }} /> - + } {/* Battery */}
Battery
- -
-
-
- Now (Charge) -
-
- {get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%) -
-
-
-
- -
-
-
- Max (Design) -
-
- {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) -
-
-
-
- + {get_value(CHARGE_NOW_BATT) != null && get_value(CHARGE_FULL_BATT) != null && + eggCount++} + focusable={false}> + {get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%) + + } + {get_value(CHARGE_FULL_BATT) != null && get_value(CHARGE_DESIGN_BATT) != null && + eggCount++} + focusable={false}> + {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) + + } + {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_rate != null && = ({}) => { { get_value(CHARGE_RATE_BATT) != null && { @@ -737,18 +738,14 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { } }} />} - + } -
-
-
- Current -
-
- {get_value(CURRENT_BATT)} mA -
-
-
+ eggCount++} + focusable={false}> + {get_value(CURRENT_BATT)} mA +
{/* Persistence */}
@@ -769,56 +766,51 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { /> -
-
-
- Profile -
-
- {get_value(NAME_GEN)} -
-
-
+ eggCount++} + focusable={false}> + {get_value(NAME_GEN)} +
{/* Version Info */}
- Debug + {eggCount % 10 == 9 ? "Ha! Nerd" : "Debug"}
-
-
-
- Native -
-
- {get_value(BACKEND_INFO)} -
-
-
+ { + if (eggCount % 10 == 9) { + // you know you're bored and/or conceited when you spend time adding an easter egg + // that just sends people to your own project's repo + Router.NavigateToExternalWeb("https://github.com/NGnius/PowerTools"); + } + eggCount++; + }}> + {eggCount % 10 == 9 ? "by NGnius" : get_value(BACKEND_INFO)} +
-
-
-
- Framework -
-
- {target_usdpl()} -
-
-
+ eggCount++}> + {eggCount % 10 == 9 ? "<3 <3 <3" : target_usdpl()} +
-
-
-
- USDPL -
-
- v{version_usdpl()} -
-
-
+ { + if (eggCount % 10 == 9) { + // you know you're bored and/or conceited when you spend time adding an easter egg + // that just sends people to your own project's repo + Router.NavigateToExternalWeb("https://github.com/NGnius/usdpl-rs"); + } + eggCount++; + }}> + v{version_usdpl()} +
Date: Mon, 21 Nov 2022 17:00:43 -0500 Subject: [PATCH 07/44] Add battery charge mode back-end support (untested) --- backend/src/api/api_types.rs | 5 +- backend/src/api/battery.rs | 48 ++++ backend/src/api/general.rs | 9 + backend/src/api/handler.rs | 4 + backend/src/main.rs | 17 +- backend/src/persist/battery.rs | 6 +- backend/src/settings/driver.rs | 34 ++- backend/src/settings/steam_deck/battery.rs | 64 +++++- backend/src/settings/steam_deck/mod.rs | 3 + backend/src/settings/steam_deck/util.rs | 93 ++++++++ .../src/settings/steam_deck_adv/battery.rs | 216 ------------------ backend/src/settings/steam_deck_adv/mod.rs | 4 +- backend/src/settings/traits.rs | 4 + backend/src/settings/unknown/battery.rs | 13 +- backend/src/state/steam_deck/battery.rs | 2 + main.py | 2 +- src/backend.ts | 21 +- src/index.tsx | 18 +- 18 files changed, 319 insertions(+), 244 deletions(-) create mode 100644 backend/src/settings/steam_deck/util.rs delete mode 100644 backend/src/settings/steam_deck_adv/battery.rs diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index 1210ece..0be7136 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -16,8 +16,9 @@ pub struct SettingsLimits { #[derive(Serialize, Deserialize)] pub struct BatteryLimits { - pub charge_rate: Option>, - pub charge_step: u64, + pub charge_current: Option>, + pub charge_current_step: u64, + pub charge_modes: Vec, } #[derive(Serialize, Deserialize)] diff --git a/backend/src/api/battery.rs b/backend/src/api/battery.rs index caa35d4..b2bbe87 100644 --- a/backend/src/api/battery.rs +++ b/backend/src/api/battery.rs @@ -71,3 +71,51 @@ pub fn unset_charge_rate( vec![true.into()] } } + +/// Generate set battery charge mode web method +pub fn set_charge_mode( + sender: Sender, +) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move |mode: String| + sender.lock() + .unwrap() + .send(ApiMessage::Battery(BatteryMessage::SetChargeMode(Some(mode)))) + .expect("set_charge_mode send failed"); + move |params_in: super::ApiParameterType| { + if let Some(Primitive::String(new_val)) = params_in.get(0) { + setter(new_val.to_owned()); + vec![new_val.to_owned().into()] + } else { + vec!["set_charge_rate missing parameter".into()] + } + } +} + +/// Generate get battery charge mode web method +pub fn get_charge_mode( + sender: Sender, +) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let getter = move || { + let (tx, rx) = mpsc::channel(); + let callback = move |mode: Option| tx.send(mode).expect("get_charge_mode callback send failed"); + sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeMode(Box::new(callback)))).expect("get_charge_mode send failed"); + rx.recv().expect("get_charge_mode callback recv failed") + }; + move |_: super::ApiParameterType| { + vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)] + } +} + +/// Generate unset battery charge mode web method +pub fn unset_charge_mode( + sender: Sender, +) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety + let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeMode(None))).expect("unset_charge_mode send failed"); + move |_params_in: super::ApiParameterType| { + setter(); + vec![true.into()] + } +} diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index 9dc765f..32e040b 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -177,3 +177,12 @@ pub fn get_limits( vec![Primitive::Json(serde_json::to_string(&getter()).unwrap())] } } + +pub fn gunter(_: super::ApiParameterType) -> super::ApiParameterType { + std::thread::spawn(|| { + log::info!("Zhu Li, do the thing!"); + crate::settings::driver::maybe_do_button(); + log::info!("Thing done.") + }); + vec![true.into()] +} diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index aa3e683..c930ec7 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -22,6 +22,8 @@ pub enum ApiMessage { pub enum BatteryMessage { SetChargeRate(Option), GetChargeRate(Callback>), + SetChargeMode(Option), + GetChargeMode(Callback>), } impl BatteryMessage { @@ -29,6 +31,8 @@ impl BatteryMessage { match self { Self::SetChargeRate(rate) => settings.charge_rate(rate), Self::GetChargeRate(cb) => cb(settings.get_charge_rate()), + Self::SetChargeMode(mode) => settings.charge_mode(mode), + Self::GetChargeMode(cb) => cb(settings.get_charge_mode()), } } } diff --git a/backend/src/main.rs b/backend/src/main.rs index 884d519..c3e07a8 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -82,6 +82,18 @@ fn main() -> Result<(), ()> { "BATTERY_unset_charge_rate", api::battery::unset_charge_rate(api_sender.clone()), ) + .register( + "BATTERY_set_charge_mode", + api::battery::set_charge_mode(api_sender.clone()), + ) + .register( + "BATTERY_get_charge_mode", + api::battery::get_charge_mode(api_sender.clone()), + ) + .register( + "BATTERY_unset_charge_mode", + api::battery::unset_charge_mode(api_sender.clone()), + ) // cpu API functions .register("CPU_count", api::cpu::max_cpus) .register( @@ -186,10 +198,11 @@ fn main() -> Result<(), ()> { "GENERAL_wait_for_unlocks", api::general::lock_unlock_all(api_sender.clone()) ) - .register( + .register_blocking( "GENERAL_get_limits", api::general::get_limits(api_sender.clone()) - ); + ) + .register("GENERAL_idk", api::general::gunter); api_worker::spawn(loaded_settings, api_handler); diff --git a/backend/src/persist/battery.rs b/backend/src/persist/battery.rs index 259e327..e5c08c7 100644 --- a/backend/src/persist/battery.rs +++ b/backend/src/persist/battery.rs @@ -6,10 +6,14 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct BatteryJson { pub charge_rate: Option, + pub charge_mode: Option, } impl Default for BatteryJson { fn default() -> Self { - Self { charge_rate: None } + Self { + charge_rate: None, + charge_mode: None, + } } } diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index 921c7a7..654d41f 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -15,6 +15,8 @@ fn auto_detect() -> DriverJson { log::debug!("Read from /etc/os-release:\n{}", os_info); if let Some(_) = lscpu.find("model name\t: AMD Custom APU 0405\n") { // definitely a Steam Deck, check if it's overclocked + // TODO: this auto-detect doesn't work + // look for a file instead? let max_freq: u64 = match usdpl_back::api::files::read_single("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq") { Ok(u) => u, Err(_) => return DriverJson::SteamDeck, @@ -84,7 +86,7 @@ impl Driver { }), cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)), gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::steam_deck_adv::Battery::from_json(settings.battery, settings.version)), + battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), DriverJson::Unknown => Ok(Self { general: Box::new(General { @@ -123,7 +125,7 @@ impl Driver { }), cpus: Box::new(super::steam_deck_adv::Cpus::system_default()), gpu: Box::new(super::steam_deck_adv::Gpu::system_default()), - battery: Box::new(super::steam_deck_adv::Battery::system_default()), + battery: Box::new(super::steam_deck::Battery::system_default()), }, DriverJson::Unknown => Self { general: Box::new(General { @@ -146,7 +148,7 @@ impl Driver { pub fn read_current_now() -> Result, SettingError> { match auto_detect() { DriverJson::SteamDeck => super::steam_deck::Battery::read_current_now().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_current_now().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_current_now().map(|x| Some(x)), DriverJson::Unknown => Ok(None), } } @@ -155,7 +157,7 @@ pub fn read_current_now() -> Result, SettingError> { pub fn read_charge_now() -> Result, SettingError> { match auto_detect() { DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_now().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)), DriverJson::Unknown => Ok(None), } } @@ -164,7 +166,7 @@ pub fn read_charge_now() -> Result, SettingError> { pub fn read_charge_full() -> Result, SettingError> { match auto_detect() { DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_full().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)), DriverJson::Unknown => Ok(None), } } @@ -173,7 +175,27 @@ pub fn read_charge_full() -> Result, SettingError> { pub fn read_charge_design() -> Result, SettingError> { match auto_detect() { DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck_adv::Battery::read_charge_design().map(|x| Some(x)), + DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)), DriverJson::Unknown => Ok(None), } } + +#[inline] +pub fn maybe_do_button() { + match auto_detect() { + DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => { + let period = std::time::Duration::from_millis(500); + for _ in 0..10 { + if let Err(e) = crate::settings::steam_deck::set_led(false, true, false) { + log::error!("Thing err: {}", e); + } + std::thread::sleep(period); + if let Err(e) = crate::settings::steam_deck::set_led(false, false, false) { + log::error!("Thing err: {}", e); + }; + std::thread::sleep(period); + } + }, + DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), + } +} diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index a002bca..ca93a2f 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -4,10 +4,12 @@ use crate::api::RangeLimit; use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; use crate::settings::TBattery; use crate::persist::BatteryJson; +use super::util::ChargeMode; #[derive(Debug, Clone)] pub struct Battery { pub charge_rate: Option, + pub charge_mode: Option, state: crate::state::steam_deck::Battery, } @@ -25,15 +27,36 @@ impl Battery { match version { 0 => Self { charge_rate: other.charge_rate, + charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), state: crate::state::steam_deck::Battery::default(), }, _ => Self { charge_rate: other.charge_rate, + charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), state: crate::state::steam_deck::Battery::default(), }, } } + #[inline] + fn charge_mode_to_str(mode: ChargeMode) -> String { + match mode { + ChargeMode::Normal => "normal", + ChargeMode::Idle => "idle", + ChargeMode::Discharge => "discharge", + }.to_owned() + } + + #[inline] + fn str_to_charge_mode(s: &str) -> Option { + match s { + "normal" => Some(ChargeMode::Normal), + "idle" => Some(ChargeMode::Idle), + "discharge" | "disacharge" => Some(ChargeMode::Discharge), + _ => None, + } + } + fn set_all(&mut self) -> Result<(), SettingError> { if let Some(charge_rate) = self.charge_rate { self.state.charge_rate_set = true; @@ -42,7 +65,7 @@ impl Battery { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), setting: crate::settings::SettingVariant::Battery, }, - ) + )?; } else if self.state.charge_rate_set { self.state.charge_rate_set = false; usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, Self::max().charge_rate.unwrap()).map_err( @@ -50,10 +73,26 @@ impl Battery { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), setting: crate::settings::SettingVariant::Battery, }, - ) - } else { - Ok(()) + )?; + } + if let Some(charge_mode) = self.charge_mode { + self.state.charge_mode_set = true; + super::util::set(super::util::Setting::ChargeMode, charge_mode as _).map_err( + |e| SettingError { + msg: format!("Failed to set charge mode: {}", e), + setting: crate::settings::SettingVariant::Battery, + }, + )?; + } else if self.state.charge_mode_set { + self.state.charge_mode_set = false; + super::util::set(super::util::Setting::ChargeMode, ChargeMode::Normal as _).map_err( + |e| SettingError { + msg: format!("Failed to set charge mode: {}", e), + setting: crate::settings::SettingVariant::Battery, + }, + )?; } + Ok(()) } fn clamp_all(&mut self) { @@ -144,6 +183,7 @@ impl Battery { pub fn system_default() -> Self { Self { charge_rate: None, + charge_mode: None, state: crate::state::steam_deck::Battery::default(), } } @@ -154,6 +194,7 @@ impl Into for Battery { fn into(self) -> BatteryJson { BatteryJson { charge_rate: self.charge_rate, + charge_mode: self.charge_mode.map(Self::charge_mode_to_str), } } } @@ -176,6 +217,7 @@ impl SettingsRange for Battery { fn max() -> Self { Self { charge_rate: Some(2500), + charge_mode: None, state: crate::state::steam_deck::Battery::default(), } } @@ -184,6 +226,7 @@ impl SettingsRange for Battery { fn min() -> Self { Self { charge_rate: Some(250), + charge_mode: None, state: crate::state::steam_deck::Battery::default(), } } @@ -194,11 +237,12 @@ impl TBattery for Battery { let max = Self::max(); let min = Self::min(); crate::api::BatteryLimits { - charge_rate: Some(RangeLimit{ + charge_current: Some(RangeLimit{ min: min.charge_rate.unwrap(), max: max.charge_rate.unwrap(), }), - charge_step: 50, + charge_current_step: 50, + charge_modes: vec!["discharge".to_owned(), "idle".to_owned(), "normal".to_owned()], } } @@ -213,4 +257,12 @@ impl TBattery for Battery { fn get_charge_rate(&self) -> Option { self.charge_rate } + + fn charge_mode(&mut self, mode: Option) { + self.charge_mode = mode.map(|s| Self::str_to_charge_mode(&s)).flatten() + } + + fn get_charge_mode(&self) -> Option { + self.charge_mode.map(Self::charge_mode_to_str) + } } diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs index 2039cae..a49088e 100644 --- a/backend/src/settings/steam_deck/mod.rs +++ b/backend/src/settings/steam_deck/mod.rs @@ -1,7 +1,10 @@ mod battery; mod cpu; mod gpu; +mod util; pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; + +pub use util::set_led; diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs new file mode 100644 index 0000000..a8cd99e --- /dev/null +++ b/backend/src/settings/steam_deck/util.rs @@ -0,0 +1,93 @@ +//! Rough Rust port of some BatCtrl functionality +//! I do not have access to the source code, so this is my own interpretation of what it does. +//! +//! But also Quanta is based in a place with some questionable copyright practices, so... +#![allow(dead_code)] + +use std::fs::OpenOptions; +use std::io::{Error, Seek, SeekFrom, Read, Write}; + +#[inline] +fn write2(p0: u8, p1: u8) -> Result { + write_to(0x6c, 0x81)?; + wait_ready_for_write()?; + let count0 = write_to(0x68, p0)?; + wait_ready_for_write()?; + let count1 = write_to(0x68, p1)?; + Ok(count0 + count1) +} + +fn write_read(p0: u8) -> Result { + write_to(0x6c, 0x81)?; + wait_ready_for_write()?; + write_to(0x68, p0)?; + wait_ready_for_read()?; + read_from(0x68) +} + +fn write_to(location: u64, value: u8) -> Result { + let mut file = OpenOptions::new() + .write(true) + .open("/dev/port")?; + file.seek(SeekFrom::Start(location))?; + file.write(&[value]) +} + +fn read_from(location: u64) -> Result { + let mut file = OpenOptions::new() + .read(true) + .open("/dev/port")?; + file.seek(SeekFrom::Start(location))?; + let mut buffer = [0]; + file.read(&mut buffer)?; + Ok(buffer[0]) +} + +fn wait_ready_for_write() -> Result<(), Error> { + let mut count = 0; + while count < 0x1ffff && (read_from(0x6c)? & 2) != 0 { + count += 1; + } + Ok(()) +} + +fn wait_ready_for_read() -> Result<(), Error> { + let mut count = 0; + while count < 0x1ffff && (read_from(0x6c)? & 1) == 0 { + count += 1; + } + Ok(()) +} + +pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result { + let payload: u8 = 0x80 + (red_unused as u8 & 1) + ((green_aka_white as u8 & 1) << 1) + ((blue_unused as u8 & 1) << 2); + //log::info!("Payload: {:b}", payload); + write2(Setting::LEDStatus as _, payload) +} + +pub fn set(setting: Setting, mode: u8) -> Result { + write2(setting as u8, mode) +} + +#[derive(Copy, Clone)] +#[repr(u8)] +pub enum Setting { + Charge = 0xA6, + ChargeMode = 0x76, + LEDStatus = 199, +} + +#[derive(Copy, Clone, Debug)] +#[repr(u8)] +pub enum ChargeMode { + Normal = 0, + Discharge = 0x42, + Idle = 0x45, +} + +#[derive(Copy, Clone)] +#[repr(u8)] +pub enum Charge { + Enable = 0, + Disable = 4, +} diff --git a/backend/src/settings/steam_deck_adv/battery.rs b/backend/src/settings/steam_deck_adv/battery.rs deleted file mode 100644 index a002bca..0000000 --- a/backend/src/settings/steam_deck_adv/battery.rs +++ /dev/null @@ -1,216 +0,0 @@ -use std::convert::Into; - -use crate::api::RangeLimit; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; -use crate::settings::TBattery; -use crate::persist::BatteryJson; - -#[derive(Debug, Clone)] -pub struct Battery { - pub charge_rate: Option, - state: crate::state::steam_deck::Battery, -} - -const BATTERY_VOLTAGE: f64 = 7.7; - -const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only -const BATTERY_CURRENT_NOW_PATH: &str = "/sys/class/power_supply/BAT1/current_now"; // read-only -const BATTERY_CHARGE_NOW_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_now"; // read-only -const BATTERY_CHARGE_FULL_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full"; // read-only -const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full_design"; // read-only - -impl Battery { - #[inline] - pub fn from_json(other: BatteryJson, version: u64) -> Self { - match version { - 0 => Self { - charge_rate: other.charge_rate, - state: crate::state::steam_deck::Battery::default(), - }, - _ => Self { - charge_rate: other.charge_rate, - state: crate::state::steam_deck::Battery::default(), - }, - } - } - - fn set_all(&mut self) -> Result<(), SettingError> { - if let Some(charge_rate) = self.charge_rate { - self.state.charge_rate_set = true; - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( - |e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }, - ) - } else if self.state.charge_rate_set { - self.state.charge_rate_set = false; - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, Self::max().charge_rate.unwrap()).map_err( - |e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }, - ) - } else { - Ok(()) - } - } - - fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); - if let Some(charge_rate) = &mut self.charge_rate { - *charge_rate = (*charge_rate).clamp(min.charge_rate.unwrap(), max.charge_rate.unwrap()); - } - } - - pub fn read_current_now() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CURRENT_NOW_PATH - ), - // this value is in uA, while it's set in mA - // so convert this to mA for consistency - Ok(val) => Ok(val / 1000), - } - } - - pub fn read_charge_now() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), - // convert to Wh - Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), - } - } - - pub fn read_charge_full() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), - // convert to Wh - Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), - } - } - - pub fn read_charge_design() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), - // convert to Wh - Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), - } - } - - pub fn system_default() -> Self { - Self { - charge_rate: None, - state: crate::state::steam_deck::Battery::default(), - } - } -} - -impl Into for Battery { - #[inline] - fn into(self) -> BatteryJson { - BatteryJson { - charge_rate: self.charge_rate, - } - } -} - -impl OnSet for Battery { - fn on_set(&mut self) -> Result<(), SettingError> { - self.clamp_all(); - self.set_all() - } -} - -impl OnResume for Battery { - fn on_resume(&self) -> Result<(), SettingError> { - self.clone().set_all() - } -} - -impl SettingsRange for Battery { - #[inline] - fn max() -> Self { - Self { - charge_rate: Some(2500), - state: crate::state::steam_deck::Battery::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - charge_rate: Some(250), - state: crate::state::steam_deck::Battery::default(), - } - } -} - -impl TBattery for Battery { - fn limits(&self) -> crate::api::BatteryLimits { - let max = Self::max(); - let min = Self::min(); - crate::api::BatteryLimits { - charge_rate: Some(RangeLimit{ - min: min.charge_rate.unwrap(), - max: max.charge_rate.unwrap(), - }), - charge_step: 50, - } - } - - fn json(&self) -> crate::persist::BatteryJson { - self.clone().into() - } - - fn charge_rate(&mut self, rate: Option) { - self.charge_rate = rate; - } - - fn get_charge_rate(&self) -> Option { - self.charge_rate - } -} diff --git a/backend/src/settings/steam_deck_adv/mod.rs b/backend/src/settings/steam_deck_adv/mod.rs index 2039cae..4a6bb90 100644 --- a/backend/src/settings/steam_deck_adv/mod.rs +++ b/backend/src/settings/steam_deck_adv/mod.rs @@ -1,7 +1,7 @@ -mod battery; +//mod battery; mod cpu; mod gpu; -pub use battery::Battery; +//pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index 8c49385..b6087f7 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -79,4 +79,8 @@ pub trait TBattery: OnResume + OnSet + Debug + Send { fn charge_rate(&mut self, rate: Option); fn get_charge_rate(&self) -> Option; + + fn charge_mode(&mut self, mode: Option); + + fn get_charge_mode(&self) -> Option; } diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index e2cca2f..967a098 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -12,6 +12,7 @@ impl Into for Battery { fn into(self) -> BatteryJson { BatteryJson { charge_rate: None, + charge_mode: None, } } } @@ -31,8 +32,9 @@ impl OnResume for Battery { impl TBattery for Battery { fn limits(&self) -> crate::api::BatteryLimits { crate::api::BatteryLimits { - charge_rate: None, - charge_step: 50, + charge_current: None, + charge_current_step: 50, + charge_modes: vec![], } } @@ -46,4 +48,11 @@ impl TBattery for Battery { fn get_charge_rate(&self) -> Option { None } + + fn charge_mode(&mut self, _rate: Option) { + } + + fn get_charge_mode(&self) -> Option { + None + } } diff --git a/backend/src/state/steam_deck/battery.rs b/backend/src/state/steam_deck/battery.rs index ab4c9f0..83826a2 100644 --- a/backend/src/state/steam_deck/battery.rs +++ b/backend/src/state/steam_deck/battery.rs @@ -1,12 +1,14 @@ #[derive(Debug, Clone)] pub struct Battery { pub charge_rate_set: bool, + pub charge_mode_set: bool, } impl std::default::Default for Battery { fn default() -> Self { Self { charge_rate_set: false, + charge_mode_set: false, } } } diff --git a/main.py b/main.py index 3e7acb9..6c1ab39 100644 --- a/main.py +++ b/main.py @@ -11,6 +11,6 @@ class Plugin: # Asyncio-compatible long-running code, executed in a task when the plugin is loaded async def _main(self): # startup - self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"]) + #self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"]) while True: await asyncio.sleep(1) diff --git a/src/backend.ts b/src/backend.ts index d985380..1f626cb 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -39,8 +39,9 @@ export type SettingsLimits = { }; export type BatteryLimits = { - charge_rate: RangeLimit | null; - charge_step: number; + charge_current: RangeLimit | null; + charge_current_step: number; + charge_modes: number; }; export type CpuLimits = { @@ -104,6 +105,18 @@ export async function unsetBatteryChargeRate(): Promise { return await call_backend("BATTERY_unset_charge_rate", []); } +export async function getBatteryChargeMode(): Promise { + return (await call_backend("BATTERY_get_charge_mode", []))[0]; +} + +export async function setBatteryChargeMode(val: number): Promise { + return (await call_backend("BATTERY_set_charge_mode", [val]))[0]; +} + +export async function unsetBatteryChargeMode(): Promise { + return await call_backend("BATTERY_unset_charge_mode", []); +} + // CPU export async function setCpuSmt(status: boolean): Promise { @@ -213,3 +226,7 @@ export async function waitForComplete(): Promise { export async function getLimits(): Promise { return (await call_backend("GENERAL_get_limits", []))[0]; } + +export async function idk(): Promise { + return (await call_backend("GENERAL_idk", []))[0]; +} diff --git a/src/index.tsx b/src/index.tsx index 98352c4..88e0062 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -701,7 +701,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) } - {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_rate != null && + {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_current != null && = ({}) => { { get_value(CHARGE_RATE_BATT) != null && { @@ -812,6 +812,16 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { v{version_usdpl()} + {eggCount % 10 == 9 && + { + backend.idk(); + }} + > + ??? + + } Date: Mon, 21 Nov 2022 20:58:35 -0500 Subject: [PATCH 08/44] Add charge mode setting for SD, move static battery readings into driver --- backend/src/api/battery.rs | 92 +++++++++++++++++++--- backend/src/api/handler.rs | 8 ++ backend/src/main.rs | 8 +- backend/src/settings/driver.rs | 39 +-------- backend/src/settings/steam_deck/battery.rs | 42 +++++++++- backend/src/settings/traits.rs | 8 ++ backend/src/settings/unknown/battery.rs | 8 ++ src/backend.ts | 6 +- src/index.tsx | 46 ++++++++++- 9 files changed, 201 insertions(+), 56 deletions(-) diff --git a/backend/src/api/battery.rs b/backend/src/api/battery.rs index b2bbe87..e7c4638 100644 --- a/backend/src/api/battery.rs +++ b/backend/src/api/battery.rs @@ -1,27 +1,101 @@ use std::sync::mpsc::{Sender, self}; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; use super::handler::{ApiMessage, BatteryMessage}; /// Current current (ha!) web method -pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_optional_result(crate::settings::driver::read_current_now()) +pub fn current_now( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |val: Option| tx.send(val).expect("current_now callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadCurrentNow(Box::new(callback)))).expect("current_now send failed"); + rx.recv().expect("current_now callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + super::utility::map_optional_result(Ok(result)) + } + } } +/// Current current (ha!) web method +/*pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { + super::utility::map_optional_result(crate::settings::driver::read_current_now()) +}*/ + /// Charge now web method -pub fn charge_now(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_optional_result(crate::settings::driver::read_charge_now()) +pub fn charge_now( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |val: Option| tx.send(val).expect("charge_now callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeNow(Box::new(callback)))).expect("charge_now send failed"); + rx.recv().expect("charge_now callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + super::utility::map_optional_result(Ok(result)) + } + } } /// Charge full web method -pub fn charge_full(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_optional_result(crate::settings::driver::read_charge_full()) +pub fn charge_full( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |val: Option| tx.send(val).expect("charge_full callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeFull(Box::new(callback)))).expect("charge_full send failed"); + rx.recv().expect("charge_full callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + super::utility::map_optional_result(Ok(result)) + } + } } /// Charge design web method -pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_optional_result(crate::settings::driver::read_charge_design()) +pub fn charge_design( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |val: Option| tx.send(val).expect("charge_design callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeDesign(Box::new(callback)))).expect("charge_design send failed"); + rx.recv().expect("charge_design callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + super::utility::map_optional_result(Ok(result)) + } + } } /// Generate set battery charge rate web method diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index c930ec7..49067ba 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -24,6 +24,10 @@ pub enum BatteryMessage { GetChargeRate(Callback>), SetChargeMode(Option), GetChargeMode(Callback>), + ReadChargeFull(Callback>), + ReadChargeNow(Callback>), + ReadChargeDesign(Callback>), + ReadCurrentNow(Callback>), } impl BatteryMessage { @@ -33,6 +37,10 @@ impl BatteryMessage { Self::GetChargeRate(cb) => cb(settings.get_charge_rate()), Self::SetChargeMode(mode) => settings.charge_mode(mode), Self::GetChargeMode(cb) => cb(settings.get_charge_mode()), + Self::ReadChargeFull(cb) => cb(settings.read_charge_full()), + Self::ReadChargeNow(cb) => cb(settings.read_charge_now()), + Self::ReadChargeDesign(cb) => cb(settings.read_charge_design()), + Self::ReadCurrentNow(cb) => cb(settings.read_current_now()), } } } diff --git a/backend/src/main.rs b/backend/src/main.rs index c3e07a8..b0fed4b 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -66,10 +66,10 @@ fn main() -> Result<(), ()> { vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()] }) // battery API functions - .register("BATTERY_current_now", api::battery::current_now) - .register("BATTERY_charge_now", api::battery::charge_now) - .register("BATTERY_charge_full", api::battery::charge_full) - .register("BATTERY_charge_design", api::battery::charge_design) + .register_async("BATTERY_current_now", api::battery::current_now(api_sender.clone())) + .register_async("BATTERY_charge_now", api::battery::charge_now(api_sender.clone())) + .register_async("BATTERY_charge_full", api::battery::charge_full(api_sender.clone())) + .register_async("BATTERY_charge_design", api::battery::charge_design(api_sender.clone())) .register( "BATTERY_set_charge_rate", api::battery::set_charge_rate(api_sender.clone()), diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index 654d41f..7f8b160 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -142,44 +142,7 @@ impl Driver { } } -// static battery calls - -#[inline] -pub fn read_current_now() -> Result, SettingError> { - match auto_detect() { - DriverJson::SteamDeck => super::steam_deck::Battery::read_current_now().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_current_now().map(|x| Some(x)), - DriverJson::Unknown => Ok(None), - } -} - -#[inline] -pub fn read_charge_now() -> Result, SettingError> { - match auto_detect() { - DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)), - DriverJson::Unknown => Ok(None), - } -} - -#[inline] -pub fn read_charge_full() -> Result, SettingError> { - match auto_detect() { - DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)), - DriverJson::Unknown => Ok(None), - } -} - -#[inline] -pub fn read_charge_design() -> Result, SettingError> { - match auto_detect() { - DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)), - DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)), - DriverJson::Unknown => Ok(None), - } -} - +// sshhhh, this function isn't here ;) #[inline] pub fn maybe_do_button() { match auto_detect() { diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index ca93a2f..8cee15e 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -242,7 +242,7 @@ impl TBattery for Battery { max: max.charge_rate.unwrap(), }), charge_current_step: 50, - charge_modes: vec!["discharge".to_owned(), "idle".to_owned(), "normal".to_owned()], + charge_modes: vec!["normal".to_owned(), "discharge".to_owned(), "idle".to_owned()], } } @@ -265,4 +265,44 @@ impl TBattery for Battery { fn get_charge_mode(&self) -> Option { self.charge_mode.map(Self::charge_mode_to_str) } + + fn read_charge_full(&self) -> Option { + match Self::read_charge_full() { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_full err: {}", e.msg); + None + } + } + } + + fn read_charge_now(&self) -> Option { + match Self::read_charge_now() { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_now err: {}", e.msg); + None + } + } + } + + fn read_charge_design(&self) -> Option { + match Self::read_charge_design() { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_design err: {}", e.msg); + None + } + } + } + + fn read_current_now(&self) -> Option { + match Self::read_current_now() { + Ok(x) => Some(x as f64), + Err(e) => { + log::warn!("read_current_now err: {}", e.msg); + None + } + } + } } diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index b6087f7..dd0b433 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -83,4 +83,12 @@ pub trait TBattery: OnResume + OnSet + Debug + Send { fn charge_mode(&mut self, mode: Option); fn get_charge_mode(&self) -> Option; + + fn read_charge_full(&self) -> Option; + + fn read_charge_now(&self) -> Option; + + fn read_charge_design(&self) -> Option; + + fn read_current_now(&self) -> Option; } diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index 967a098..e7edb11 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -55,4 +55,12 @@ impl TBattery for Battery { fn get_charge_mode(&self) -> Option { None } + + fn read_charge_full(&self) -> Option { None } + + fn read_charge_now(&self) -> Option { None } + + fn read_charge_design(&self) -> Option { None } + + fn read_current_now(&self) -> Option { None } } diff --git a/src/backend.ts b/src/backend.ts index 1f626cb..d736630 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -41,7 +41,7 @@ export type SettingsLimits = { export type BatteryLimits = { charge_current: RangeLimit | null; charge_current_step: number; - charge_modes: number; + charge_modes: string[]; }; export type CpuLimits = { @@ -105,11 +105,11 @@ export async function unsetBatteryChargeRate(): Promise { return await call_backend("BATTERY_unset_charge_rate", []); } -export async function getBatteryChargeMode(): Promise { +export async function getBatteryChargeMode(): Promise { return (await call_backend("BATTERY_get_charge_mode", []))[0]; } -export async function setBatteryChargeMode(val: number): Promise { +export async function setBatteryChargeMode(val: string): Promise { return (await call_backend("BATTERY_set_charge_mode", [val]))[0]; } diff --git a/src/index.tsx b/src/index.tsx index 88e0062..0391718 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -51,6 +51,7 @@ const LIMITS_INFO = "LIMITS_all"; const CURRENT_BATT = "BATTERY_current_now"; const CHARGE_RATE_BATT = "BATTERY_charge_rate"; +const CHARGE_MODE_BATT = "BATTERY_charge_mode"; const CHARGE_NOW_BATT = "BATTERY_charge_now"; const CHARGE_FULL_BATT = "BATTERY_charge_full"; const CHARGE_DESIGN_BATT = "BATTERY_charge_design" @@ -107,6 +108,7 @@ const reload = function() { backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) }); backend.resolve(backend.getBatteryChargeRate(), (rate: number) => { set_value(CHARGE_RATE_BATT, rate) }); + backend.resolve(backend.getBatteryChargeMode(), (mode: string) => { set_value(CHARGE_MODE_BATT, mode) }); backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) }); backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) }); backend.resolve(backend.getBatteryChargeDesign(), (rate: number) => { set_value(CHARGE_DESIGN_BATT, rate) }); @@ -218,6 +220,11 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label: {elem}, };}); + const chargeModeOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_modes.map((elem) => {return { + data: elem, + label: {elem}, + };}); + return ( {/* CPU */} @@ -494,7 +501,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} } - {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.length != 0 && + {advancedMode && governorOptions.length != 0 && @@ -739,6 +746,43 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { }} />} } + {chargeModeOptions.length != 0 && + { + if (value) { + set_value(CHARGE_MODE_BATT, chargeModeOptions[0].data as string); + reloadGUI("BATTChargeModeToggle"); + } else { + set_value(CHARGE_MODE_BATT, null); + backend.resolve(backend.unsetBatteryChargeMode(), (_: any[]) => { + reloadGUI("BATTUnsetChargeMode"); + }); + } + }} + /> + {get_value(CHARGE_MODE_BATT) != null && + { + return val.data == get_value(CHARGE_MODE_BATT); + })} + strDefaultLabel={get_value(CHARGE_MODE_BATT)} + onChange={(elem: SingleDropdownOption) => { + console.debug("Charge mode dropdown selected", elem); + backend.resolve(backend.setBatteryChargeMode(elem.data as string), (mode: string) => { + set_value(CHARGE_MODE_BATT, mode); + reloadGUI("BATTChargeMode"); + }); + }} + /> + } + } Date: Mon, 28 Nov 2022 16:04:03 -0800 Subject: [PATCH 09/44] Multiplatform Dev (#52) * Use environment home instead of hard coding home_path * Fix Makefile * Use PathBuf instead of format. Catch else fore /tmp/ default directory * Restore logpath for deployment. Resolve warning from copy() not having err handled. * Undo add #[cfg(debug_assertions)] in wrong place. --- Makefile | 87 ++++++++++++++++++++++++++++++++++++++++++ backend/Cargo.lock | 4 +- backend/Cargo.toml | 2 +- backend/src/main.rs | 15 ++++++-- backend/src/utility.rs | 2 +- 5 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..88237ef --- /dev/null +++ b/Makefile @@ -0,0 +1,87 @@ +# Configuration settings +PLUGIN_NAME ?= $(shell basename $(PWD)) +PLUGIN_VERSION ?= 0.3.0 + +# Source files +TS_FILES := $(shell find src -name *.ts) +TSX_FILES := $(shell find src -name *.tsx) +SRC_FILES := $(TS_FILES) $(TSX_FILES) plugin.json + +TAR_FILES := bin dist main.py package.json plugin.json + +# plugin dir +DATA_PATH ?= homebrew + +# SSH Configuration +SSH_USER ?= gamer +SSH_HOST ?= 192.168.0.246 +SSH_MOUNT_PATH ?= /tmp/remote +SSH_DATA_PATH ?= /home/$(SSH_USER)/$(DATA_PATH) + +# Default target is to build and restart crankshaft +.PHONY: default +default: build restart + +.PHONY: build +build: build ## Builds the project + cd backend && ./build.sh && cd .. + +dist: $(SRC_FILES) node_modules + npm run build + +.PHONY: watch +watch: ## Build and watch for source code changes + npm run build-watch + +package-lock.json: package.json + npm i + +node_modules: node_modules/installed ## Install dependencies +node_modules/installed: package-lock.json + npm ci + touch $@ + +.PHONY: restart +restart: ## Restart crankshaft + ssh $(SSH_USER)@$(SSH_HOST) sudo systemctl restart plugin_loader -S + +.PHONY: debug +debug: ## Show Makefile variables + @echo "Source Files: $(SRC_FILES)" + +.PHONY: cef-debug +cef-debug: ## Open Chrome CEF debugging. Add a network target: localhost:8080 + chromium "chrome://inspect/#devices" + +.PHONY: tunnel +tunnel: ## Create an SSH tunnel to remote Steam Client (accessible on localhost:4040) + ssh $(SSH_USER)@$(SSH_HOST) -N -f -L 4040:localhost:8080 + +$(SSH_MOUNT_PATH)/.mounted: + mkdir -p $(SSH_MOUNT_PATH) + sshfs -o default_permissions $(SSH_USER)@$(SSH_HOST):$(SSH_DATA_PATH) $(SSH_MOUNT_PATH) + touch $(SSH_MOUNT_PATH)/.mounted + $(MAKE) tunnel + +# Cleans and transfers the project +$(SSH_MOUNT_PATH)/plugins/$(PLUGIN_NAME): $(SRC_FILES) + rsync -avh $(PWD)/ $(SSH_MOUNT_PATH)/plugins/$(PLUGIN_NAME) --delete + +.PHONY: remote-restart +remote-restart: ## Restart remote crankshaft + ssh $(SSH_USER)@$(SSH_HOST) sudo systemctl restart plugin_loader + +.PHONY: mount +mount: $(SSH_MOUNT_PATH)/.mounted + +.PHONY: remote-update +remote-update: $(SSH_MOUNT_PATH)/plugins/$(PLUGIN_NAME) + +.PHONY: clean +clean: ## Clean all build artifacts + rm -rf build dist bin + +.PHONY: help +help: ## Show this help message + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 0dfa192..94ef8d0 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1077,9 +1077,9 @@ dependencies = [ [[package]] name = "usdpl-back" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca96dac4ee471e9534940f99cb36f5212cbfaf4e7779eb3ba970d3c511d9583" +checksum = "58928ed65332c30b9b9be5140fcdab97e45db679a5845d829aa26492765272e5" dependencies = [ "async-recursion", "async-trait", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 9fbf9bd..5b9f403 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -usdpl-back = { version = "0.7.0", features = ["blocking"]} +usdpl-back = { version = "0.7.2", features = ["blocking"]} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/backend/src/main.rs b/backend/src/main.rs index b0fed4b..3985ca0 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -18,14 +18,21 @@ use usdpl_back::core::serdes::Primitive; use usdpl_back::Instance; fn main() -> Result<(), ()> { + #[cfg(debug_assertions)] - let log_filepath = format!("/home/deck/{}.log", PACKAGE_NAME); + let log_filepath = usdpl_back::api::dirs::home() + .unwrap_or_else(|| "/tmp/".into()) + .join(PACKAGE_NAME.to_owned()+".log"); #[cfg(not(debug_assertions))] - let log_filepath = format!("/tmp/{}.log", PACKAGE_NAME); + let log_filepath = std::path::PathBuf.new("/tmp/"+PACKAGE_NAME.to_owned()+".log"); + #[cfg(debug_assertions)] + let old_log_filepath = usdpl_back::api::dirs::home() + .unwrap_or_else(|| "/tmp/".into()) + .join(PACKAGE_NAME.to_owned()+".log.old"); #[cfg(debug_assertions)] { if std::path::Path::new(&log_filepath).exists() { - std::fs::copy(&log_filepath, format!("/home/deck/{}.log.old", PACKAGE_NAME)).unwrap(); + std::fs::copy(&log_filepath, &old_log_filepath).expect("Unable to increment logs. Do you have write permissions?"); } } WriteLogger::init( @@ -41,6 +48,8 @@ fn main() -> Result<(), ()> { std::fs::File::create(&log_filepath).unwrap(), ) .unwrap(); + log::debug!("Logging to: {:?}.", log_filepath); + println!("Logging to: {:?}", log_filepath); log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); diff --git a/backend/src/utility.rs b/backend/src/utility.rs index 1c1f90c..aed4673 100644 --- a/backend/src/utility.rs +++ b/backend/src/utility.rs @@ -26,6 +26,6 @@ pub fn unwrap_maybe_fatal(result: Result, message: & pub fn settings_dir() -> std::path::PathBuf { usdpl_back::api::dirs::home() - .unwrap_or_else(|| "/home/deck".into()) + .unwrap_or_else(|| "/tmp/".into()) .join(".config/powertools/") } From d1d52652245358c46e6acc6c53f7bfbdeca264b9 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 28 Nov 2022 19:31:01 -0500 Subject: [PATCH 10/44] Create basic generic (placeholder) driver --- backend/src/persist/driver.rs | 2 + backend/src/settings/driver.rs | 25 ++ backend/src/settings/generic/battery.rs | 115 ++++++++++ backend/src/settings/generic/cpu.rs | 289 ++++++++++++++++++++++++ backend/src/settings/generic/gpu.rs | 89 ++++++++ backend/src/settings/generic/mod.rs | 7 + backend/src/settings/mod.rs | 1 + 7 files changed, 528 insertions(+) create mode 100644 backend/src/settings/generic/battery.rs create mode 100644 backend/src/settings/generic/cpu.rs create mode 100644 backend/src/settings/generic/gpu.rs create mode 100644 backend/src/settings/generic/mod.rs diff --git a/backend/src/persist/driver.rs b/backend/src/persist/driver.rs index bf8b891..91244a2 100644 --- a/backend/src/persist/driver.rs +++ b/backend/src/persist/driver.rs @@ -9,6 +9,8 @@ pub enum DriverJson { SteamDeck, #[serde(rename = "steam-deck-oc", alias = "gabe-boy-advance")] SteamDeckAdvance, + #[serde(rename = "generic")] + Generic, #[serde(rename = "unknown")] Unknown, } diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index 7f8b160..a9a5d09 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -26,6 +26,8 @@ fn auto_detect() -> DriverJson { } else { DriverJson::SteamDeckAdvance } + } else if let Some(_) = lscpu.find("model name\t: AMD Ryzen") { + DriverJson::Generic } else { DriverJson::Unknown } @@ -88,6 +90,17 @@ impl Driver { gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), + DriverJson::Generic => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::Unknown, + }), + cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::generic::Battery), + }), DriverJson::Unknown => Ok(Self { general: Box::new(General { persistent: settings.persistent, @@ -127,6 +140,17 @@ impl Driver { gpu: Box::new(super::steam_deck_adv::Gpu::system_default()), battery: Box::new(super::steam_deck::Battery::system_default()), }, + DriverJson::Generic => Self { + general: Box::new(General { + persistent: false, + path: json_path, + name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + driver: DriverJson::Unknown, + }), + cpus: Box::new(super::generic::Cpus::system_default()), + gpu: Box::new(super::generic::Gpu::system_default()), + battery: Box::new(super::generic::Battery), + }, DriverJson::Unknown => Self { general: Box::new(General { persistent: false, @@ -159,6 +183,7 @@ pub fn maybe_do_button() { std::thread::sleep(period); } }, + DriverJson::Generic => log::warn!("You need to come up with something fun on generic"), DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), } } diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs new file mode 100644 index 0000000..6b6ad6b --- /dev/null +++ b/backend/src/settings/generic/battery.rs @@ -0,0 +1,115 @@ +use std::convert::Into; + +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::TBattery; +use crate::persist::BatteryJson; + +#[derive(Debug, Clone)] +pub struct Battery; + +impl Into for Battery { + #[inline] + fn into(self) -> BatteryJson { + BatteryJson { + charge_rate: None, + charge_mode: None, + } + } +} + +impl Battery { + fn read_f64>(path: P) -> Result { + let path = path.as_ref(); + match usdpl_back::api::files::read_single::<_, f64, _>(path) { + Err((Some(e), None)) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Battery, + }), + Err((None, Some(e))) => Err(SettingError { + msg: format!("Failed to read from `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Battery, + }), + Err(_) => panic!( + "Invalid error while reading from `{}`", + path.display() + ), + // this value is in uA, while it's set in mA + // so convert this to mA for consistency + Ok(val) => Ok(val / 1000.0), + } + } +} + +impl OnSet for Battery { + fn on_set(&mut self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl OnResume for Battery { + fn on_resume(&self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl TBattery for Battery { + fn limits(&self) -> crate::api::BatteryLimits { + crate::api::BatteryLimits { + charge_current: None, + charge_current_step: 50, + charge_modes: vec![], + } + } + + fn json(&self) -> crate::persist::BatteryJson { + self.clone().into() + } + + fn charge_rate(&mut self, _rate: Option) { + } + + fn get_charge_rate(&self) -> Option { + None + } + + fn charge_mode(&mut self, _rate: Option) { + } + + fn get_charge_mode(&self) -> Option { + None + } + + fn read_charge_full(&self) -> Option { + match Self::read_f64("/sys/class/power_supply/BAT0/energy_full") { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_full err: {}", e.msg); + None + } + } + } + + fn read_charge_now(&self) -> Option { + match Self::read_f64("/sys/class/power_supply/BAT0/energy_now") { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_now err: {}", e.msg); + None + } + } + } + + fn read_charge_design(&self) -> Option { + match Self::read_f64("/sys/class/power_supply/BAT0/energy_design") { + Ok(x) => Some(x), + Err(e) => { + log::warn!("read_charge_design err: {}", e.msg); + None + } + } + } + + fn read_current_now(&self) -> Option { + None + } +} diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs new file mode 100644 index 0000000..48d4b99 --- /dev/null +++ b/backend/src/settings/generic/cpu.rs @@ -0,0 +1,289 @@ +use std::convert::Into; + +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{TCpus, TCpu}; +use crate::persist::CpuJson; + +const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; +const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; + +#[derive(Debug, Clone)] +pub struct Cpus { + pub cpus: Vec, + pub smt: bool, + pub smt_capable: bool, +} + +impl OnSet for Cpus { + fn on_set(&mut self) -> Result<(), SettingError> { + if self.smt_capable { + // toggle SMT + if self.smt { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `on` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } else { + usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { + SettingError { + msg: format!( + "Failed to write `off` to `{}`: {}", + CPU_SMT_PATH, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + } + for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { + cpu.state.do_set_online = self.smt || i % 2 == 0; + cpu.on_set()?; + } + Ok(()) + } +} + +impl OnResume for Cpus { + fn on_resume(&self) -> Result<(), SettingError> { + for cpu in &self.cpus { + cpu.on_resume()?; + } + Ok(()) + } +} + +impl Cpus { + pub fn cpu_count() -> Option { + let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) + .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); + if let Some(dash_index) = data.find('-') { + let data = data.split_off(dash_index + 1); + if let Ok(max_cpu) = data.parse::() { + return Some(max_cpu + 1); + } + } + log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); + None + } + + fn system_smt_capabilities() -> (bool, bool) { + match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { + Ok(val) => (val.trim().to_lowercase() == "on", true), + Err(_) => (false, false) + } + } + + pub fn system_default() -> Self { + if let Some(max_cpu) = Self::cpu_count() { + let mut sys_cpus = Vec::with_capacity(max_cpu); + for i in 0..max_cpu { + sys_cpus.push(Cpu::from_sys(i)); + } + let (smt_status, can_smt) = Self::system_smt_capabilities(); + Self { + cpus: sys_cpus, + smt: smt_status, + smt_capable: can_smt, + } + } else { + Self { + cpus: vec![], + smt: false, + smt_capable: false, + } + } + } + + #[inline] + pub fn from_json(mut other: Vec, version: u64) -> Self { + let (_, can_smt) = Self::system_smt_capabilities(); + let mut result = Vec::with_capacity(other.len()); + let max_cpus = Self::cpu_count(); + for (i, cpu) in other.drain(..).enumerate() { + // prevent having more CPUs than available + if let Some(max_cpus) = max_cpus { + if i == max_cpus { + break; + } + } + result.push(Cpu::from_json(cpu, version, i)); + } + if let Some(max_cpus) = max_cpus { + if result.len() != max_cpus { + let mut sys_cpus = Cpus::system_default(); + for i in result.len()..sys_cpus.cpus.len() { + result.push(sys_cpus.cpus.remove(i)); + } + } + } + Self { + cpus: result, + smt: true, + smt_capable: can_smt, + } + } +} + +impl TCpus for Cpus { + fn limits(&self) -> crate::api::CpusLimits { + crate::api::CpusLimits { + cpus: self.cpus.iter().map(|x| x.limits()).collect(), + count: self.cpus.len(), + smt_capable: self.smt_capable, + } + } + + fn json(&self) -> Vec { + self.cpus.iter().map(|x| x.to_owned().into()).collect() + } + + fn cpus(&mut self) -> Vec<&mut dyn TCpu> { + self.cpus.iter_mut().map(|x| x as &mut dyn TCpu).collect() + } + + fn len(&self) -> usize { + self.cpus.len() + } +} + +#[derive(Debug, Clone)] +pub struct Cpu { + pub online: bool, + pub governor: String, + index: usize, + state: crate::state::steam_deck::Cpu, +} + + +impl Cpu { + #[inline] + pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { + match version { + 0 => Self { + online: other.online, + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + _ => Self { + online: other.online, + governor: other.governor, + index: i, + state: crate::state::steam_deck::Cpu::default(), + }, + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + // set cpu online/offline + if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled + let online_path = cpu_online_path(self.index); + usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", &online_path, e), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + + // set governor + if self.index == 0 || self.online { + let governor_path = cpu_governor_path(self.index); + usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &self.governor, &governor_path, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + })?; + } + Ok(()) + } + + fn from_sys(cpu_index: usize) -> Self { + Self { + online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, + governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) + .unwrap_or("schedutil".to_owned()), + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } + } + + fn limits(&self) -> crate::api::CpuLimits { + crate::api::CpuLimits { + clock_min_limits: None, + clock_max_limits: None, + clock_step: 100, + governors: vec![], // TODO + } + } +} + +impl Into for Cpu { + #[inline] + fn into(self) -> CpuJson { + CpuJson { + online: self.online, + clock_limits: None, + governor: self.governor, + } + } +} + +impl OnSet for Cpu { + fn on_set(&mut self) -> Result<(), SettingError> { + //self.clamp_all(); + self.set_all() + } +} + +impl OnResume for Cpu { + fn on_resume(&self) -> Result<(), SettingError> { + let mut copy = self.clone(); + copy.state.is_resuming = true; + copy.set_all() + } +} + +impl TCpu for Cpu { + fn online(&mut self) -> &mut bool { + &mut self.online + } + + fn governor(&mut self, governor: String) { + self.governor = governor; + } + + fn get_governor(&self) -> &'_ str { + &self.governor + } + + fn clock_limits(&mut self, _limits: Option>) { + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + None + } +} + +#[inline] +fn cpu_online_path(index: usize) -> String { + format!("/sys/devices/system/cpu/cpu{}/online", index) +} + +#[inline] +fn cpu_governor_path(index: usize) -> String { + format!( + "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor", + index + ) +} diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs new file mode 100644 index 0000000..9733cc8 --- /dev/null +++ b/backend/src/settings/generic/gpu.rs @@ -0,0 +1,89 @@ +use std::convert::Into; + +use crate::settings::MinMax; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::TGpu; +use crate::persist::GpuJson; + +#[derive(Debug, Clone)] +pub struct Gpu { + slow_memory: bool, // ignored +} + +impl Gpu { + #[inline] + pub fn from_json(_other: GpuJson, _version: u64) -> Self { + Self { + slow_memory: false, + } + } + + pub fn system_default() -> Self { + Self { + slow_memory: false, + } + } +} + +impl Into for Gpu { + #[inline] + fn into(self) -> GpuJson { + GpuJson { + fast_ppt: None, + slow_ppt: None, + clock_limits: None, + slow_memory: false, + } + } +} + +impl OnSet for Gpu { + fn on_set(&mut self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl OnResume for Gpu { + fn on_resume(&self) -> Result<(), SettingError> { + Ok(()) + } +} + +impl TGpu for Gpu { + fn limits(&self) -> crate::api::GpuLimits { + crate::api::GpuLimits { + fast_ppt_limits: None, + slow_ppt_limits: None, + ppt_step: 1_000_000, + tdp_limits: None, + tdp_boost_limits: None, + tdp_step: 42, + clock_min_limits: None, + clock_max_limits: None, + clock_step: 100, + memory_control_capable: false, + } + } + + fn json(&self) -> crate::persist::GpuJson { + self.clone().into() + } + + fn ppt(&mut self, _fast: Option, _slow: Option) { + } + + fn get_ppt(&self) -> (Option, Option) { + (None, None) + } + + fn clock_limits(&mut self, _limits: Option>) { + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + None + } + + fn slow_memory(&mut self) -> &mut bool { + &mut self.slow_memory + } +} diff --git a/backend/src/settings/generic/mod.rs b/backend/src/settings/generic/mod.rs new file mode 100644 index 0000000..2039cae --- /dev/null +++ b/backend/src/settings/generic/mod.rs @@ -0,0 +1,7 @@ +mod battery; +mod cpu; +mod gpu; + +pub use battery::Battery; +pub use cpu::{Cpu, Cpus}; +pub use gpu::Gpu; diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 5dd569c..c12cf12 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -4,6 +4,7 @@ mod general; mod min_max; mod traits; +pub mod generic; pub mod steam_deck; pub mod steam_deck_adv; pub mod unknown; From 376638672659659f6cd5ea5c7e142cc9d06f6b7a Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Fri, 2 Dec 2022 21:12:13 -0500 Subject: [PATCH 11/44] Add hardware limits provider and auto detection with online updater (cached locally) --- .gitignore | 1 + backend/Cargo.lock | 129 +++ backend/Cargo.toml | 9 +- backend/limits_core/Cargo.toml | 10 + backend/limits_core/src/json/base.rs | 49 + backend/limits_core/src/json/battery_limit.rs | 15 + backend/limits_core/src/json/conditions.rs | 20 + backend/limits_core/src/json/config.rs | 8 + backend/limits_core/src/json/cpu_limit.rs | 15 + backend/limits_core/src/json/gpu_limit.rs | 15 + backend/limits_core/src/json/limits.rs | 9 + backend/limits_core/src/json/mod.rs | 17 + backend/limits_core/src/json/target.rs | 9 + backend/limits_core/src/lib.rs | 1 + backend/limits_srv/Cargo.lock | 1026 +++++++++++++++++ backend/limits_srv/Cargo.toml | 12 + backend/limits_srv/pt_limits.json | 43 + backend/limits_srv/src/main.rs | 53 + backend/src/consts.rs | 2 + backend/src/main.rs | 3 +- backend/src/persist/battery.rs | 2 +- backend/src/persist/cpu.rs | 2 +- backend/src/persist/driver.rs | 4 +- backend/src/persist/general.rs | 2 +- backend/src/persist/gpu.rs | 2 +- backend/src/settings/detect/auto_detect.rs | 191 +++ backend/src/settings/detect/limits_worker.rs | 110 ++ backend/src/settings/detect/mod.rs | 5 + backend/src/settings/detect/utility.rs | 3 + backend/src/settings/driver.rs | 172 +-- backend/src/settings/generic/battery.rs | 10 + backend/src/settings/generic/cpu.rs | 37 + backend/src/settings/generic/gpu.rs | 15 +- backend/src/settings/mod.rs | 2 + 34 files changed, 1864 insertions(+), 139 deletions(-) create mode 100644 backend/limits_core/Cargo.toml create mode 100644 backend/limits_core/src/json/base.rs create mode 100644 backend/limits_core/src/json/battery_limit.rs create mode 100644 backend/limits_core/src/json/conditions.rs create mode 100644 backend/limits_core/src/json/config.rs create mode 100644 backend/limits_core/src/json/cpu_limit.rs create mode 100644 backend/limits_core/src/json/gpu_limit.rs create mode 100644 backend/limits_core/src/json/limits.rs create mode 100644 backend/limits_core/src/json/mod.rs create mode 100644 backend/limits_core/src/json/target.rs create mode 100644 backend/limits_core/src/lib.rs create mode 100644 backend/limits_srv/Cargo.lock create mode 100644 backend/limits_srv/Cargo.toml create mode 100644 backend/limits_srv/pt_limits.json create mode 100644 backend/limits_srv/src/main.rs create mode 100644 backend/src/settings/detect/auto_detect.rs create mode 100644 backend/src/settings/detect/limits_worker.rs create mode 100644 backend/src/settings/detect/mod.rs create mode 100644 backend/src/settings/detect/utility.rs diff --git a/.gitignore b/.gitignore index ed38553..22cbe24 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ yalc.lock /backend/target /bin /backend/out +/**/target diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 94ef8d0..3093cd0 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aead" version = "0.4.3" @@ -38,6 +44,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "async-recursion" version = "1.0.0" @@ -96,6 +126,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "buf_redux" version = "0.8.4" @@ -124,6 +164,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chunked_transfer" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" + [[package]] name = "cipher" version = "0.3.0" @@ -142,6 +188,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -180,6 +235,15 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -189,6 +253,16 @@ dependencies = [ "instant", ] +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -433,6 +507,14 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "limits_core" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "log" version = "0.4.17" @@ -470,6 +552,15 @@ dependencies = [ "unicase", ] +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.4" @@ -592,11 +683,14 @@ name = "powertools-rs" version = "1.1.0" dependencies = [ "async-trait", + "limits_core", "log", + "regex", "serde", "serde_json", "simplelog", "tokio", + "ureq", "usdpl-back", ] @@ -669,6 +763,23 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1063,6 +1174,24 @@ dependencies = [ "subtle", ] +[[package]] +name = "ureq" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f" +dependencies = [ + "base64", + "brotli-decompressor", + "chunked_transfer", + "encoding_rs", + "flate2", + "log", + "once_cell", + "serde", + "serde_json", + "url", +] + [[package]] name = "url" version = "2.2.2" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 5b9f403..ae4ad1e 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -18,11 +18,18 @@ async-trait = { version = "0.1" } log = "0.4" simplelog = "0.12" +# limits & driver functionality +limits_core = { version = "0.1.0", path = "./limits_core" } +regex = "1" +# ureq's tls feature does not like musl targets +ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } + [features] -default = [] +default = ["online"] decky = ["usdpl-back/decky"] crankshaft = ["usdpl-back/crankshaft"] encrypt = ["usdpl-back/encrypt"] +online = ["ureq"] [profile.release] debug = false diff --git a/backend/limits_core/Cargo.toml b/backend/limits_core/Cargo.toml new file mode 100644 index 0000000..58ceabd --- /dev/null +++ b/backend/limits_core/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "limits_core" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/backend/limits_core/src/json/base.rs b/backend/limits_core/src/json/base.rs new file mode 100644 index 0000000..c25e5de --- /dev/null +++ b/backend/limits_core/src/json/base.rs @@ -0,0 +1,49 @@ +use std::default::Default; +use serde::{Deserialize, Serialize}; + +/// Base JSON limits information +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Base { + /// System-specific configurations + pub configs: Vec, + /// URL from which to grab the next update + pub refresh: Option, +} + +impl Default for Base { + fn default() -> Self { + Base { + configs: vec![ + super::Config { + name: "Steam Deck".to_owned(), + conditions: super::Conditions { + dmi: None, + cpuinfo: Some("model name\t: AMD Custom APU 0405\n".to_owned()), + os: None, + command: None, + }, + limits: vec![ + super::Limits::Cpu(super::CpuLimit::SteamDeck), + super::Limits::Gpu(super::GpuLimit::SteamDeck), + super::Limits::Battery(super::BatteryLimit::SteamDeck), + ] + }, + super::Config { + name: "Fallback".to_owned(), + conditions: super::Conditions { + dmi: None, + cpuinfo: None, + os: None, + command: None, + }, + limits: vec![ + super::Limits::Cpu(super::CpuLimit::Unknown), + super::Limits::Gpu(super::GpuLimit::Unknown), + super::Limits::Battery(super::BatteryLimit::Unknown), + ] + } + ], + refresh: Some("http://limits.ngni.us:45000/powertools/v1".to_owned()) + } + } +} diff --git a/backend/limits_core/src/json/battery_limit.rs b/backend/limits_core/src/json/battery_limit.rs new file mode 100644 index 0000000..ca44689 --- /dev/null +++ b/backend/limits_core/src/json/battery_limit.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "target")] +pub enum BatteryLimit { + SteamDeck, + SteamDeckAdvance, + Generic(GenericBatteryLimit), + Unknown, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GenericBatteryLimit { + /* TODO */ +} diff --git a/backend/limits_core/src/json/conditions.rs b/backend/limits_core/src/json/conditions.rs new file mode 100644 index 0000000..2016cb9 --- /dev/null +++ b/backend/limits_core/src/json/conditions.rs @@ -0,0 +1,20 @@ +use serde::{Deserialize, Serialize}; + +/// Conditions under which a config applies +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Conditions { + /// Regex pattern for dmidecode output + pub dmi: Option, + /// Regex pattern for /proc/cpuinfo reading + pub cpuinfo: Option, + /// Regex pattern for /etc/os-release reading + pub os: Option, + /// Custom command to run, where an exit code of 0 means a successful match + pub command: Option, +} + +impl Conditions { + pub fn is_empty(&self) -> bool { + self.dmi.is_none() && self.cpuinfo.is_none() && self.os.is_none() && self.command.is_none() + } +} diff --git a/backend/limits_core/src/json/config.rs b/backend/limits_core/src/json/config.rs new file mode 100644 index 0000000..57d70ac --- /dev/null +++ b/backend/limits_core/src/json/config.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Config { + pub name: String, + pub conditions: super::Conditions, + pub limits: Vec, +} diff --git a/backend/limits_core/src/json/cpu_limit.rs b/backend/limits_core/src/json/cpu_limit.rs new file mode 100644 index 0000000..d413cda --- /dev/null +++ b/backend/limits_core/src/json/cpu_limit.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "target")] +pub enum CpuLimit { + SteamDeck, + SteamDeckAdvance, + Generic(GenericCpuLimit), + Unknown, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GenericCpuLimit { + /* TODO */ +} diff --git a/backend/limits_core/src/json/gpu_limit.rs b/backend/limits_core/src/json/gpu_limit.rs new file mode 100644 index 0000000..712b8b1 --- /dev/null +++ b/backend/limits_core/src/json/gpu_limit.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "target")] +pub enum GpuLimit { + SteamDeck, + SteamDeckAdvance, + Generic(GenericGpuLimit), + Unknown, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GenericGpuLimit { + /* TODO */ +} diff --git a/backend/limits_core/src/json/limits.rs b/backend/limits_core/src/json/limits.rs new file mode 100644 index 0000000..10abd4e --- /dev/null +++ b/backend/limits_core/src/json/limits.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "limits")] +pub enum Limits { + Cpu(super::CpuLimit), + Gpu(super::GpuLimit), + Battery(super::BatteryLimit), +} diff --git a/backend/limits_core/src/json/mod.rs b/backend/limits_core/src/json/mod.rs new file mode 100644 index 0000000..250e218 --- /dev/null +++ b/backend/limits_core/src/json/mod.rs @@ -0,0 +1,17 @@ +mod base; +mod battery_limit; +mod conditions; +mod config; +mod cpu_limit; +mod gpu_limit; +mod limits; +mod target; + +pub use base::Base; +pub use battery_limit::{BatteryLimit, GenericBatteryLimit}; +pub use conditions::Conditions; +pub use cpu_limit::{CpuLimit, GenericCpuLimit}; +pub use gpu_limit::{GpuLimit, GenericGpuLimit}; +pub use config::Config; +pub use limits::Limits; +pub use target::Target; diff --git a/backend/limits_core/src/json/target.rs b/backend/limits_core/src/json/target.rs new file mode 100644 index 0000000..768df6f --- /dev/null +++ b/backend/limits_core/src/json/target.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum Target { + SteamDeck, + SteamDeckAdvance, + Generic, + Unknown, +} diff --git a/backend/limits_core/src/lib.rs b/backend/limits_core/src/lib.rs new file mode 100644 index 0000000..22fdbb3 --- /dev/null +++ b/backend/limits_core/src/lib.rs @@ -0,0 +1 @@ +pub mod json; diff --git a/backend/limits_srv/Cargo.lock b/backend/limits_srv/Cargo.lock new file mode 100644 index 0000000..0bb3b66 --- /dev/null +++ b/backend/limits_srv/Cargo.lock @@ -0,0 +1,1026 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" + +[[package]] +name = "futures-sink" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" + +[[package]] +name = "futures-task" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" + +[[package]] +name = "futures-util" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "headers" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +dependencies = [ + "base64", + "bitflags", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "libc" +version = "0.2.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "limits_core" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "limits_srv" +version = "0.1.0" +dependencies = [ + "limits_core", + "serde_json", + "tokio", + "warp", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "multipart" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand", + "safemem", + "tempfile", + "twoway", +] + +[[package]] +name = "num_cpus" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "serde" +version = "1.0.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "sha-1", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "warp" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "headers", + "http", + "hyper", + "log", + "mime", + "mime_guess", + "multipart", + "percent-encoding", + "pin-project", + "rustls-pemfile", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util", + "tower-service", + "tracing", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/backend/limits_srv/Cargo.toml b/backend/limits_srv/Cargo.toml new file mode 100644 index 0000000..48989d9 --- /dev/null +++ b/backend/limits_srv/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "limits_srv" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +limits_core = { version = "0.1.0", path = "../limits_core" } +serde_json = "1.0" +warp = { version = "0.3" } +tokio = { version = "1.22", features = ["macros", "rt", "rt-multi-thread"] } diff --git a/backend/limits_srv/pt_limits.json b/backend/limits_srv/pt_limits.json new file mode 100644 index 0000000..4dcef89 --- /dev/null +++ b/backend/limits_srv/pt_limits.json @@ -0,0 +1,43 @@ +{ + "configs": [ + { + "name": "Steam Deck", + "conditions": { + "cpuinfo": "model name\t: AMD Custom APU 0405\n" + }, + "limits": [ + { + "limits": "Cpu", + "target": "SteamDeck" + }, + { + "limits": "Gpu", + "target": "SteamDeck" + }, + { + "limits": "Battery", + "target": "SteamDeck" + } + ] + }, + { + "name": "Fallback", + "conditions": {}, + "limits": [ + { + "limits": "Cpu", + "target": "Unknown" + }, + { + "limits": "Gpu", + "target": "Unknown" + }, + { + "limits": "Battery", + "target": "Unknown" + } + ] + } + ], + "refresh": "http://limits.ngni.us:45000/powertools/v1" +} diff --git a/backend/limits_srv/src/main.rs b/backend/limits_srv/src/main.rs new file mode 100644 index 0000000..7f423f3 --- /dev/null +++ b/backend/limits_srv/src/main.rs @@ -0,0 +1,53 @@ +use std::sync::atomic::{Ordering, AtomicU64}; +use std::sync::{RwLock, Arc}; + +use warp::Filter; + +use limits_core::json::Base; + +static VISIT_COUNT: AtomicU64 = AtomicU64::new(0); + +fn get_limits(base: Base) -> impl warp::Reply { + VISIT_COUNT.fetch_add(1, Ordering::AcqRel); + //println!("Count: {} + 1", old_count); + warp::reply::json(&base) +} + +fn get_visits() -> impl warp::Reply { + let count = VISIT_COUNT.load(Ordering::Relaxed); + //println!("Count: {}", count); + warp::reply::json(&count) +} + +fn routes(base: Arc>) -> impl Filter + Clone { + warp::get().and( + warp::path!("powertools" / "v1") + .map(move || { + let base = base.read().expect("Failed to acquire base limits read lock").clone(); + get_limits(base) + }) + .or( + warp::path!("powertools" / "count") + .map(get_visits) + ) + ).recover(recovery) +} + +pub async fn recovery(reject: warp::Rejection) -> Result { + if reject.is_not_found() { + Ok(warp::hyper::StatusCode::NOT_FOUND) + } else { + Err(reject) + } +} + +#[tokio::main] +async fn main() { + let file = std::fs::File::open("./pt_limits.json").expect("Failed to read limits file"); + let limits: Base = serde_json::from_reader(file).expect("Failed to parse limits file"); + assert!(limits.refresh.is_some(), "`refresh` cannot be null, since it will brick future refreshes"); + + warp::serve(routes(Arc::new(RwLock::new(limits)))) + .run(([0, 0, 0, 0], 8080)) + .await; +} diff --git a/backend/src/consts.rs b/backend/src/consts.rs index 055d0ff..842051a 100644 --- a/backend/src/consts.rs +++ b/backend/src/consts.rs @@ -5,3 +5,5 @@ pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION"); pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json"; pub const DEFAULT_SETTINGS_NAME: &str = "Main"; + +pub const LIMITS_FILE: &str = "limits_cache.json"; diff --git a/backend/src/main.rs b/backend/src/main.rs index 3985ca0..2d25c95 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -53,7 +53,8 @@ fn main() -> Result<(), ()> { log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); - crate::settings::driver::auto_detect_loud(); + let _limits_handle = crate::settings::limits_worker_spawn(); + log::info!("Detected device automatically, starting with driver: {:?} (This can be overriden)", crate::settings::auto_detect_provider()); let mut loaded_settings = persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE)) .map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into())) diff --git a/backend/src/persist/battery.rs b/backend/src/persist/battery.rs index e5c08c7..962cfbb 100644 --- a/backend/src/persist/battery.rs +++ b/backend/src/persist/battery.rs @@ -3,7 +3,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct BatteryJson { pub charge_rate: Option, pub charge_mode: Option, diff --git a/backend/src/persist/cpu.rs b/backend/src/persist/cpu.rs index 0af2781..442206a 100644 --- a/backend/src/persist/cpu.rs +++ b/backend/src/persist/cpu.rs @@ -7,7 +7,7 @@ use super::MinMaxJson; //const SCALING_FREQUENCIES: &[u64] = &[1700000, 2400000, 2800000]; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct CpuJson { pub online: bool, pub clock_limits: Option>, diff --git a/backend/src/persist/driver.rs b/backend/src/persist/driver.rs index 91244a2..f1486b5 100644 --- a/backend/src/persist/driver.rs +++ b/backend/src/persist/driver.rs @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Default, Debug, Clone)] pub enum DriverJson { - #[default] #[serde(rename = "steam-deck", alias = "gabe-boy")] SteamDeck, #[serde(rename = "steam-deck-oc", alias = "gabe-boy-advance")] @@ -13,4 +12,7 @@ pub enum DriverJson { Generic, #[serde(rename = "unknown")] Unknown, + #[default] + #[serde(rename = "auto")] + AutoDetect, } diff --git a/backend/src/persist/general.rs b/backend/src/persist/general.rs index b85df70..22f94da 100644 --- a/backend/src/persist/general.rs +++ b/backend/src/persist/general.rs @@ -56,7 +56,7 @@ impl SettingsJson { } } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct MinMaxJson { pub max: T, pub min: T, diff --git a/backend/src/persist/gpu.rs b/backend/src/persist/gpu.rs index ecb352f..933f2c4 100644 --- a/backend/src/persist/gpu.rs +++ b/backend/src/persist/gpu.rs @@ -4,7 +4,7 @@ use std::default::Default; use super::MinMaxJson; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct GpuJson { pub fast_ppt: Option, pub slow_ppt: Option, diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs new file mode 100644 index 0000000..9a3c550 --- /dev/null +++ b/backend/src/settings/detect/auto_detect.rs @@ -0,0 +1,191 @@ +use std::fs::File; + +use regex::RegexBuilder; + +use limits_core::json::{Limits, BatteryLimit, CpuLimit, GpuLimit}; + +use crate::persist::{DriverJson, SettingsJson}; +use crate::settings::{TGeneral, TCpus, TGpu, TBattery, Driver, General}; + +#[inline] +pub fn auto_detect_provider() -> DriverJson { + let provider = auto_detect0(None, crate::utility::settings_dir().join("autodetect.json")) + .general + .provider(); + //log::info!("Detected device automatically, compatible driver: {:?}", provider); + provider +} + +/// Device detection logic +pub fn auto_detect0(settings_opt: Option, json_path: std::path::PathBuf) -> Driver { + let mut builder = DriverBuilder::new(json_path); + + let cpu_info: String = usdpl_back::api::files::read_single("/proc/cpuinfo").unwrap_or_default(); + log::debug!("Read from /proc/cpuinfo:\n{}", cpu_info); + let os_info: String = usdpl_back::api::files::read_single("/etc/os-release").unwrap_or_default(); + log::debug!("Read from /etc/os-release:\n{}", os_info); + let dmi_info: String = std::process::Command::new("dmidecode").output().map(|out| String::from_utf8_lossy(&out.stdout).into_owned()).unwrap_or_default(); + log::debug!("Read dmidecode:\n{}", dmi_info); + + let limits_path = super::utility::limits_path(); + let limits = match File::open(&limits_path) { + Ok(f) => { + match serde_json::from_reader(f) { + Ok(lim) => lim, + Err(e) => { + log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e); + limits_core::json::Base::default() + } + } + }, + Err(e) => { + log::warn!("Failed to open limits file `{}` (trying force refresh...): {}", limits_path.display(), e); + super::limits_worker::get_limits_blocking() + } + }; + + // build driver based on limits conditions + for conf in limits.configs { + let conditions = conf.conditions; + let mut matches = true; + if conditions.is_empty() { + matches = !builder.is_complete(); + } else { + if let Some(dmi) = &conditions.dmi { + let pattern = RegexBuilder::new(dmi) + .multi_line(true) + .build() + .expect("Invalid DMI regex"); + matches &=pattern.is_match(&dmi_info); + } + if let Some(cpuinfo) = &conditions.cpuinfo { + let pattern = RegexBuilder::new(cpuinfo) + .multi_line(true) + .build() + .expect("Invalid CPU regex"); + matches &=pattern.is_match(&cpu_info); + } + if let Some(os) = &conditions.os { + let pattern = RegexBuilder::new(os) + .multi_line(true) + .build() + .expect("Invalid OS regex"); + matches &=pattern.is_match(&os_info); + } + if let Some(cmd) = &conditions.command { + match std::process::Command::new("bash") + .args(["-c", cmd]) + .status() { + Ok(status) => matches &= status.code().map(|c| c == 0).unwrap_or(false), + Err(e) => log::warn!("Ignoring bash limits error: {}", e), + } + } + } + if matches { + if let Some(settings) = &settings_opt { + for limit in conf.limits { + match limit { + Limits::Cpu(cpus) => { + let cpu_driver: Box = match cpus { + CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), + CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::from_json(settings.cpus.clone(), settings.version)), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), + CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), + }; + builder.cpus = Some(cpu_driver); + }, + Limits::Gpu(gpu) => { + let driver: Box = match gpu { + GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), + GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::from_json(settings.gpu.clone(), settings.version)), + GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), + GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::from_json(settings.gpu.clone(), settings.version)), + }; + builder.gpu = Some(driver); + }, + Limits::Battery(batt) => { + let driver: Box = match batt { + BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)), + BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)), + BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_json_and_limits(settings.battery.clone(), settings.version, x)), + BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery), + }; + builder.battery = Some(driver); + } + } + } + } else { + for limit in conf.limits { + match limit { + Limits::Cpu(cpus) => { + let cpu_driver: Box = match cpus { + CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), + CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::system_default()), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)), + CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), + }; + builder.cpus = Some(cpu_driver); + }, + Limits::Gpu(gpu) => { + let driver: Box = match gpu { + GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()), + GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::system_default()), + GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_limits(x)), + GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::system_default()), + }; + builder.gpu = Some(driver); + }, + Limits::Battery(batt) => { + let driver: Box = match batt { + BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::system_default()), + BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::system_default()), + BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_limits(x)), + BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery), + }; + builder.battery = Some(driver); + } + } + } + } + + } + } + + builder.build() +} + +struct DriverBuilder { + general: Box, + cpus: Option>, + gpu: Option>, + battery: Option>, +} + +impl DriverBuilder { + fn new(json_path: std::path::PathBuf) -> Self { + Self { + general: Box::new(General { + persistent: false, + path: json_path, + name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), + driver: DriverJson::AutoDetect, + }), + cpus: None, + gpu: None, + battery: None, + } + } + + fn is_complete(&self) -> bool { + self.cpus.is_some() && self.gpu.is_some() && self.battery.is_some() + } + + fn build(self) -> Driver { + Driver { + general: self.general, + cpus: self.cpus.unwrap_or_else(|| Box::new(crate::settings::unknown::Cpus::system_default())), + gpu: self.gpu.unwrap_or_else(|| Box::new(crate::settings::unknown::Gpu::system_default())), + battery: self.battery.unwrap_or_else(|| Box::new(crate::settings::unknown::Battery)) + } + } +} diff --git a/backend/src/settings/detect/limits_worker.rs b/backend/src/settings/detect/limits_worker.rs new file mode 100644 index 0000000..0ee61a3 --- /dev/null +++ b/backend/src/settings/detect/limits_worker.rs @@ -0,0 +1,110 @@ +use std::thread::{self, JoinHandle}; +#[cfg(feature = "online")] +use std::time::Duration; + +use limits_core::json::Base; + +#[cfg(feature = "online")] +pub fn spawn() -> JoinHandle<()> { + thread::spawn(move || { + log::info!("limits_worker starting..."); + let sleep_dur = Duration::from_secs(60*60*24); // 1 day + let limits_path = super::utility::limits_path(); + loop { + thread::sleep(sleep_dur); + if (limits_path.exists() && limits_path.is_file()) || !limits_path.exists() { + // try to load limits from file, fallback to built-in default + let base = match std::fs::File::open(&limits_path) { + Ok(f) => { + match serde_json::from_reader(f) { + Ok(b) => b, + Err(e) => { + log::error!("Cannot parse {}: {}", limits_path.display(), e); + Base::default() + } + } + }, + Err(e) => { + log::error!("Cannot open {}: {}", limits_path.display(), e); + Base::default() + } + }; + if let Some(refresh) = &base.refresh { + // try to retrieve newer version + match ureq::get(refresh) + .call() { + Ok(response) => { + let json_res: std::io::Result = response.into_json(); + match json_res { + Ok(new_base) => { + match std::fs::File::create(&limits_path) { + Ok(f) => { + match serde_json::to_writer_pretty(f, &new_base) { + Ok(_) => log::info!("Successfully updated limits from `{}`, cached at {}", refresh, limits_path.display()), + Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e), + } + }, + Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e) + } + }, + Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e), + } + }, + Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e), + } + } else { + log::info!("limits_worker refresh is empty, terminating..."); + break; + } + } else if !limits_path.is_file() { + log::error!("Path for storing limits is not a file!"); + } + } + log::warn!("limits_worker completed!"); + }) +} + +#[cfg(not(feature = "online"))] +pub fn spawn() -> JoinHandle<()> { + thread::spawn(move || { + log::info!("limits_worker disabled..."); + }) +} + +pub fn get_limits_blocking() -> Base { + let limits_path = super::utility::limits_path(); + if limits_path.is_file() { + match std::fs::File::open(&limits_path) { + Ok(f) => { + match serde_json::from_reader(f) { + Ok(b) => b, + Err(e) => { + log::error!("Cannot parse {}: {}", limits_path.display(), e); + Base::default() + } + } + }, + Err(e) => { + log::error!("Cannot open {}: {}", limits_path.display(), e); + Base::default() + } + } + } else { + #[cfg(feature = "online")] + { + let refresh = Base::default().refresh.unwrap(); + match ureq::get(&refresh) // try to retrieve newer version + .call() { + Ok(response) => { + let json_res: std::io::Result = response.into_json(); + match json_res { + Ok(new_base) => return new_base, + Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e) + } + }, + Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e), + } + } + Base::default() + } +} diff --git a/backend/src/settings/detect/mod.rs b/backend/src/settings/detect/mod.rs new file mode 100644 index 0000000..1bb27fc --- /dev/null +++ b/backend/src/settings/detect/mod.rs @@ -0,0 +1,5 @@ +mod auto_detect; +pub mod limits_worker; +mod utility; + +pub use auto_detect::{auto_detect_provider, auto_detect0}; diff --git a/backend/src/settings/detect/utility.rs b/backend/src/settings/detect/utility.rs new file mode 100644 index 0000000..16aec42 --- /dev/null +++ b/backend/src/settings/detect/utility.rs @@ -0,0 +1,3 @@ +pub fn limits_path() -> std::path::PathBuf { + crate::utility::settings_dir().join(crate::consts::LIMITS_FILE) +} diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index a9a5d09..7a2e498 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -1,44 +1,5 @@ use crate::persist::{DriverJson, SettingsJson}; -use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General}; - -/// Device detection logic -fn auto_detect() -> DriverJson { - let lscpu: String = match usdpl_back::api::files::read_single("/proc/cpuinfo") { - Ok(s) => s, - Err(_) => return DriverJson::Unknown, - }; - log::debug!("Read from /proc/cpuinfo:\n{}", lscpu); - let os_info: String = match usdpl_back::api::files::read_single("/etc/os-release") { - Ok(s) => s, - Err(_) => return DriverJson::Unknown, - }; - log::debug!("Read from /etc/os-release:\n{}", os_info); - if let Some(_) = lscpu.find("model name\t: AMD Custom APU 0405\n") { - // definitely a Steam Deck, check if it's overclocked - // TODO: this auto-detect doesn't work - // look for a file instead? - let max_freq: u64 = match usdpl_back::api::files::read_single("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq") { - Ok(u) => u, - Err(_) => return DriverJson::SteamDeck, - }; - if max_freq == 2800000 { // default clock speed - DriverJson::SteamDeck - } else { - DriverJson::SteamDeckAdvance - } - } else if let Some(_) = lscpu.find("model name\t: AMD Ryzen") { - DriverJson::Generic - } else { - DriverJson::Unknown - } -} - -#[inline] -pub fn auto_detect_loud() -> DriverJson { - let provider = auto_detect(); - log::info!("Detected device automatically, compatible driver: {:?}", provider); - provider -} +use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General, auto_detect0}; pub struct Driver { pub general: Box, @@ -66,110 +27,58 @@ impl Driver { } fn version0(settings: SettingsJson, json_path: std::path::PathBuf) -> Result { - let provider = settings.provider.unwrap_or_else(auto_detect); - match provider { - DriverJson::SteamDeck => Ok(Self { - general: Box::new(General { - persistent: settings.persistent, - path: json_path, - name: settings.name, - driver: DriverJson::SteamDeck, + if let Some(provider) = &settings.provider { + match provider { + DriverJson::SteamDeck => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::SteamDeck, + }), + cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), - cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), - }), - DriverJson::SteamDeckAdvance => Ok(Self { - general: Box::new(General { - persistent: settings.persistent, - path: json_path, - name: settings.name, - driver: DriverJson::SteamDeckAdvance, + DriverJson::SteamDeckAdvance => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::SteamDeckAdvance, + }), + cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), - cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), - }), - DriverJson::Generic => Ok(Self { - general: Box::new(General { - persistent: settings.persistent, - path: json_path, - name: settings.name, - driver: DriverJson::Unknown, + DriverJson::Generic => Ok(Self { + general: Box::new(General { + persistent: settings.persistent, + path: json_path, + name: settings.name, + driver: DriverJson::Unknown, + }), + cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)), + battery: Box::new(super::generic::Battery), }), - cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::generic::Battery), - }), - DriverJson::Unknown => Ok(Self { - general: Box::new(General { - persistent: settings.persistent, - path: json_path, - name: settings.name, - driver: DriverJson::Unknown, - }), - cpus: Box::new(super::unknown::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::unknown::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::unknown::Battery), - }), + DriverJson::Unknown => Ok(super::detect::auto_detect0(Some(settings), json_path)), + DriverJson::AutoDetect => Ok(super::detect::auto_detect0(Some(settings), json_path)), + } + } else { + Ok(super::detect::auto_detect0(Some(settings), json_path)) } } pub fn system_default(json_path: std::path::PathBuf) -> Self { - let provider = auto_detect(); - match provider { - DriverJson::SteamDeck => Self { - general: Box::new(General { - persistent: false, - path: json_path, - name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - driver: DriverJson::SteamDeck, - }), - cpus: Box::new(super::steam_deck::Cpus::system_default()), - gpu: Box::new(super::steam_deck::Gpu::system_default()), - battery: Box::new(super::steam_deck::Battery::system_default()), - }, - DriverJson::SteamDeckAdvance => Self { - general: Box::new(General { - persistent: false, - path: json_path, - name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - driver: DriverJson::SteamDeck, - }), - cpus: Box::new(super::steam_deck_adv::Cpus::system_default()), - gpu: Box::new(super::steam_deck_adv::Gpu::system_default()), - battery: Box::new(super::steam_deck::Battery::system_default()), - }, - DriverJson::Generic => Self { - general: Box::new(General { - persistent: false, - path: json_path, - name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - driver: DriverJson::Unknown, - }), - cpus: Box::new(super::generic::Cpus::system_default()), - gpu: Box::new(super::generic::Gpu::system_default()), - battery: Box::new(super::generic::Battery), - }, - DriverJson::Unknown => Self { - general: Box::new(General { - persistent: false, - path: json_path, - name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), - driver: DriverJson::Unknown, - }), - cpus: Box::new(super::unknown::Cpus::system_default()), - gpu: Box::new(super::unknown::Gpu::system_default()), - battery: Box::new(super::unknown::Battery), - } - } + auto_detect0(None, json_path) } } // sshhhh, this function isn't here ;) #[inline] pub fn maybe_do_button() { - match auto_detect() { + match super::auto_detect_provider() { DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => { let period = std::time::Duration::from_millis(500); for _ in 0..10 { @@ -185,5 +94,6 @@ pub fn maybe_do_button() { }, DriverJson::Generic => log::warn!("You need to come up with something fun on generic"), DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), + DriverJson::AutoDetect => log::warn!("WTF, why is auto_detect detecting AutoDetect???") } } diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index 6b6ad6b..6eb99c2 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -38,6 +38,16 @@ impl Battery { Ok(val) => Ok(val / 1000.0), } } + + pub fn from_limits(_limits: limits_core::json::GenericBatteryLimit) -> Self { + // TODO + Self + } + + pub fn from_json_and_limits(_other: BatteryJson, _version: u64, _limits: limits_core::json::GenericBatteryLimit) -> Self { + // TODO + Self + } } impl OnSet for Battery { diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 48d4b99..d29153e 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -128,6 +128,43 @@ impl Cpus { smt_capable: can_smt, } } + + pub fn from_limits(_limits: limits_core::json::GenericCpuLimit) -> Self { + // TODO + Self { + cpus: vec![], + smt: false, + smt_capable: false, + } + } + + pub fn from_json_and_limits(mut other: Vec, version: u64, _limits: limits_core::json::GenericCpuLimit) -> Self { + let (_, can_smt) = Self::system_smt_capabilities(); + let mut result = Vec::with_capacity(other.len()); + let max_cpus = Self::cpu_count(); + for (i, cpu) in other.drain(..).enumerate() { + // prevent having more CPUs than available + if let Some(max_cpus) = max_cpus { + if i == max_cpus { + break; + } + } + result.push(Cpu::from_json(cpu, version, i)); + } + if let Some(max_cpus) = max_cpus { + if result.len() != max_cpus { + let mut sys_cpus = Cpus::system_default(); + for i in result.len()..sys_cpus.cpus.len() { + result.push(sys_cpus.cpus.remove(i)); + } + } + } + Self { + cpus: result, + smt: true, + smt_capable: can_smt, + } + } } impl TCpus for Cpus { diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 9733cc8..1782ac5 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -18,7 +18,20 @@ impl Gpu { } } - pub fn system_default() -> Self { + /*pub fn system_default() -> Self { + Self { + slow_memory: false, + } + }*/ + + pub fn from_limits(_limits: limits_core::json::GenericGpuLimit) -> Self { + // TODO + Self { + slow_memory: false, + } + } + + pub fn from_json_and_limits(_other: GpuJson, _version: u64, _limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, } diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index c12cf12..68e5bd7 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -1,3 +1,4 @@ +mod detect; pub mod driver; mod error; mod general; @@ -9,6 +10,7 @@ pub mod steam_deck; pub mod steam_deck_adv; pub mod unknown; +pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn}; pub use driver::Driver; pub use general::{SettingVariant, Settings, General}; pub use min_max::MinMax; From 9ef710a966057950bc5a5945a99b98f8f122f478 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 3 Dec 2022 13:58:08 -0500 Subject: [PATCH 12/44] Fix auto_detect_provider to only return AutoDetect on default/unknown hardware --- backend/src/settings/detect/auto_detect.rs | 38 +++++++++++--------- backend/src/settings/detect/limits_worker.rs | 29 +++++++++------ backend/src/settings/generic/battery.rs | 4 +++ backend/src/settings/generic/cpu.rs | 4 +++ backend/src/settings/generic/gpu.rs | 4 +++ backend/src/settings/steam_deck/battery.rs | 4 +++ backend/src/settings/steam_deck/cpu.rs | 4 +++ backend/src/settings/steam_deck/gpu.rs | 4 +++ backend/src/settings/steam_deck_adv/cpu.rs | 4 +++ backend/src/settings/steam_deck_adv/gpu.rs | 4 +++ backend/src/settings/traits.rs | 12 +++++++ backend/src/settings/unknown/battery.rs | 4 +++ backend/src/settings/unknown/cpu.rs | 4 +++ backend/src/settings/unknown/gpu.rs | 4 +++ 14 files changed, 96 insertions(+), 27 deletions(-) diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index 9a3c550..18a6fd2 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -7,10 +7,29 @@ use limits_core::json::{Limits, BatteryLimit, CpuLimit, GpuLimit}; use crate::persist::{DriverJson, SettingsJson}; use crate::settings::{TGeneral, TCpus, TGpu, TBattery, Driver, General}; +fn get_limits() -> limits_core::json::Base { + let limits_path = super::utility::limits_path(); + match File::open(&limits_path) { + Ok(f) => { + match serde_json::from_reader(f) { + Ok(lim) => lim, + Err(e) => { + log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e); + limits_core::json::Base::default() + } + } + }, + Err(e) => { + log::warn!("Failed to open limits file `{}` (trying force refresh...): {}", limits_path.display(), e); + super::limits_worker::get_limits_blocking() + } + } +} + #[inline] pub fn auto_detect_provider() -> DriverJson { let provider = auto_detect0(None, crate::utility::settings_dir().join("autodetect.json")) - .general + .battery .provider(); //log::info!("Detected device automatically, compatible driver: {:?}", provider); provider @@ -27,22 +46,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa let dmi_info: String = std::process::Command::new("dmidecode").output().map(|out| String::from_utf8_lossy(&out.stdout).into_owned()).unwrap_or_default(); log::debug!("Read dmidecode:\n{}", dmi_info); - let limits_path = super::utility::limits_path(); - let limits = match File::open(&limits_path) { - Ok(f) => { - match serde_json::from_reader(f) { - Ok(lim) => lim, - Err(e) => { - log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e); - limits_core::json::Base::default() - } - } - }, - Err(e) => { - log::warn!("Failed to open limits file `{}` (trying force refresh...): {}", limits_path.display(), e); - super::limits_worker::get_limits_blocking() - } - }; + let limits = get_limits(); // build driver based on limits conditions for conf in limits.configs { diff --git a/backend/src/settings/detect/limits_worker.rs b/backend/src/settings/detect/limits_worker.rs index 0ee61a3..ef1f0f2 100644 --- a/backend/src/settings/detect/limits_worker.rs +++ b/backend/src/settings/detect/limits_worker.rs @@ -37,15 +37,7 @@ pub fn spawn() -> JoinHandle<()> { let json_res: std::io::Result = response.into_json(); match json_res { Ok(new_base) => { - match std::fs::File::create(&limits_path) { - Ok(f) => { - match serde_json::to_writer_pretty(f, &new_base) { - Ok(_) => log::info!("Successfully updated limits from `{}`, cached at {}", refresh, limits_path.display()), - Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e), - } - }, - Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e) - } + save_base(&new_base, &limits_path); }, Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e), } @@ -98,7 +90,10 @@ pub fn get_limits_blocking() -> Base { Ok(response) => { let json_res: std::io::Result = response.into_json(); match json_res { - Ok(new_base) => return new_base, + Ok(new_base) => { + save_base(&new_base, &limits_path); + return new_base; + }, Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e) } }, @@ -108,3 +103,17 @@ pub fn get_limits_blocking() -> Base { Base::default() } } + +#[cfg(feature = "online")] +fn save_base(new_base: &Base, path: impl AsRef) { + let limits_path = path.as_ref(); + match std::fs::File::create(&limits_path) { + Ok(f) => { + match serde_json::to_writer_pretty(f, &new_base) { + Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()), + Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e), + } + }, + Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e) + } +} diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index 6eb99c2..bd300b7 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -122,4 +122,8 @@ impl TBattery for Battery { fn read_current_now(&self) -> Option { None } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Generic + } } diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index d29153e..df5a6d4 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -187,6 +187,10 @@ impl TCpus for Cpus { fn len(&self) -> usize { self.cpus.len() } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Generic + } } #[derive(Debug, Clone)] diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 1782ac5..3344915 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -99,4 +99,8 @@ impl TGpu for Gpu { fn slow_memory(&mut self) -> &mut bool { &mut self.slow_memory } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Generic + } } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 8cee15e..13fe425 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -305,4 +305,8 @@ impl TBattery for Battery { } } } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::SteamDeck + } } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 845e3fe..8f02867 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -151,6 +151,10 @@ impl TCpus for Cpus { fn len(&self) -> usize { self.cpus.len() } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::SteamDeck + } } #[derive(Debug, Clone)] diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 665a7df..59827fe 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -300,6 +300,10 @@ impl TGpu for Gpu { fn slow_memory(&mut self) -> &mut bool { &mut self.slow_memory } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::SteamDeck + } } #[inline] diff --git a/backend/src/settings/steam_deck_adv/cpu.rs b/backend/src/settings/steam_deck_adv/cpu.rs index 1d04a27..2b13c23 100644 --- a/backend/src/settings/steam_deck_adv/cpu.rs +++ b/backend/src/settings/steam_deck_adv/cpu.rs @@ -151,6 +151,10 @@ impl TCpus for Cpus { fn len(&self) -> usize { self.cpus.len() } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::SteamDeckAdvance + } } #[derive(Debug, Clone)] diff --git a/backend/src/settings/steam_deck_adv/gpu.rs b/backend/src/settings/steam_deck_adv/gpu.rs index fccd598..7ae25b8 100644 --- a/backend/src/settings/steam_deck_adv/gpu.rs +++ b/backend/src/settings/steam_deck_adv/gpu.rs @@ -298,6 +298,10 @@ impl TGpu for Gpu { fn slow_memory(&mut self) -> &mut bool { &mut self.slow_memory } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::SteamDeckAdvance + } } #[inline] diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index dd0b433..219cc95 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -29,6 +29,10 @@ pub trait TGpu: OnResume + OnSet + Debug + Send { fn get_clock_limits(&self) -> Option<&MinMax>; fn slow_memory(&mut self) -> &mut bool; + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::AutoDetect + } } pub trait TCpus: OnResume + OnSet + Debug + Send { @@ -39,6 +43,10 @@ pub trait TCpus: OnResume + OnSet + Debug + Send { fn cpus(&mut self) -> Vec<&mut dyn TCpu>; fn len(&self) -> usize; + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::AutoDetect + } } pub trait TCpu: Debug + Send { @@ -91,4 +99,8 @@ pub trait TBattery: OnResume + OnSet + Debug + Send { fn read_charge_design(&self) -> Option; fn read_current_now(&self) -> Option; + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::AutoDetect + } } diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index e7edb11..dfc57ce 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -63,4 +63,8 @@ impl TBattery for Battery { fn read_charge_design(&self) -> Option { None } fn read_current_now(&self) -> Option { None } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Unknown + } } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 48d4b99..d4c183a 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -150,6 +150,10 @@ impl TCpus for Cpus { fn len(&self) -> usize { self.cpus.len() } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Unknown + } } #[derive(Debug, Clone)] diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs index 9733cc8..fecc4ed 100644 --- a/backend/src/settings/unknown/gpu.rs +++ b/backend/src/settings/unknown/gpu.rs @@ -86,4 +86,8 @@ impl TGpu for Gpu { fn slow_memory(&mut self) -> &mut bool { &mut self.slow_memory } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::Unknown + } } From 469d2a4eeddf51270bff2db038bc35b27717eee2 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 3 Dec 2022 13:59:23 -0500 Subject: [PATCH 13/44] Delete persistent settings files when persistence disabled; fix #55 --- backend/src/api/handler.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 49067ba..bf31495 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -161,15 +161,23 @@ impl ApiMessageHandler { // save log::debug!("api_worker is saving..."); let is_persistent = *settings.general.persistent(); + let save_path = crate::utility::settings_dir() + .join(settings.general.get_path().clone()); if is_persistent { - let save_path = crate::utility::settings_dir() - .join(settings.general.get_path().clone()); let settings_clone = settings.json(); let save_json: SettingsJson = settings_clone.into(); unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); log::debug!("Saved settings to {}", save_path.display()); } else { - log::debug!("Ignored save request for non-persistent settings"); + if save_path.exists() { + if let Err(e) = std::fs::remove_file(&save_path) { + log::warn!("Failed to delete persistent settings file {}: {}", save_path.display(), e); + } else { + log::debug!("Deleted persistent settings file {}", save_path.display()); + } + } else { + log::debug!("Ignored save request for non-persistent settings"); + } } } } From 892a0b0ab64968335568271e9e3c3ea1401196c3 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 5 Dec 2022 18:51:49 -0500 Subject: [PATCH 14/44] Update dependencies and create faster build profile for decky's CI --- backend/Cargo.lock | 350 ++++++++++++++-------------- backend/Cargo.toml | 12 +- backend/build-docker.sh | 2 +- backend/src/main.rs | 2 +- src/usdpl_front/package.json | 2 +- src/usdpl_front/usdpl_front.d.ts | 8 +- src/usdpl_front/usdpl_front.js | 131 ++++++----- src/usdpl_front/usdpl_front_bg.wasm | Bin 84752 -> 84394 bytes 8 files changed, 264 insertions(+), 243 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 3093cd0..290e4a9 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" dependencies = [ "proc-macro2", "quote", @@ -98,9 +98,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" @@ -110,18 +110,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -154,9 +145,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cfg-if" @@ -181,9 +172,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -218,20 +209,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.9.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", + "block-buffer", "crypto-common", ] @@ -271,19 +253,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -291,27 +272,27 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-sink", @@ -323,9 +304,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -333,9 +314,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -344,9 +325,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -357,7 +338,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.3", + "tokio-util", "tracing", ] @@ -369,9 +350,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "headers" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64", "bitflags", @@ -380,7 +361,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha-1 0.10.0", + "sha1", ] [[package]] @@ -431,9 +412,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -443,9 +424,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -467,20 +448,19 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -497,15 +477,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "limits_core" @@ -524,12 +504,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.5.0" @@ -563,9 +537,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", @@ -593,9 +567,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -618,9 +592,9 @@ checksum = "7b2b2cbbfd8defa51ff24450a61d73b3ff3e158484ddd274a883e886e6fbaa78" [[package]] name = "once_cell" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opaque-debug" @@ -630,24 +604,24 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -696,15 +670,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -717,9 +691,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -747,9 +721,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -789,11 +763,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "safemem" @@ -803,24 +786,24 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "serde" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" +checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" +checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" dependencies = [ "proc-macro2", "quote", @@ -829,9 +812,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", @@ -852,26 +835,24 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.8" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ - "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] -name = "sha-1" -version = "0.10.0" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest", ] [[package]] @@ -896,9 +877,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -912,9 +893,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.98" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", @@ -946,18 +927,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -966,21 +947,32 @@ dependencies = [ [[package]] name = "time" -version = "0.3.11" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ "itoa", "libc", "num_threads", + "serde", + "time-core", "time-macros", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] [[package]] name = "tinyvec" @@ -999,9 +991,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.1" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" dependencies = [ "autocfg", "bytes", @@ -1009,17 +1001,16 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "pin-project-lite", "socket2", - "winapi", + "windows-sys", ] [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -1028,36 +1019,21 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.15.0" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", "log", - "pin-project", "tokio", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.6.10" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -1075,9 +1051,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", @@ -1087,9 +1063,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -1102,9 +1078,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.14.0" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64", "byteorder", @@ -1113,7 +1089,7 @@ dependencies = [ "httparse", "log", "rand", - "sha-1 0.9.8", + "sha-1", "thiserror", "url", "utf-8", @@ -1130,9 +1106,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicase" @@ -1151,15 +1127,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] @@ -1194,13 +1170,12 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -1255,9 +1230,9 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e" +checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" dependencies = [ "bytes", "futures-channel", @@ -1271,6 +1246,7 @@ dependencies = [ "multipart", "percent-encoding", "pin-project", + "rustls-pemfile", "scoped-tls", "serde", "serde_json", @@ -1278,7 +1254,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tungstenite", - "tokio-util 0.6.10", + "tokio-util", "tower-service", "tracing", ] @@ -1322,46 +1298,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "zeroize" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index ae4ad1e..fab0846 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -35,4 +35,14 @@ online = ["ureq"] debug = false strip = true lto = true -codegen-units = 4 +codegen-units = 1 + +[profile.docker] +inherits = "release" +debug = false +strip = true +lto = "thin" +codegen-units = 16 +opt-level = 2 +debug-assertions = false +overflow-checks = false diff --git a/backend/build-docker.sh b/backend/build-docker.sh index c6074a9..58ae2f9 100755 --- a/backend/build-docker.sh +++ b/backend/build-docker.sh @@ -6,7 +6,7 @@ rustc --version cargo --version echo "--- Building plugin backend ---" -cargo build --release +cargo build --profile docker mkdir -p out cp target/release/powertools-rs out/backend diff --git a/backend/src/main.rs b/backend/src/main.rs index 2d25c95..e949d30 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -24,7 +24,7 @@ fn main() -> Result<(), ()> { .unwrap_or_else(|| "/tmp/".into()) .join(PACKAGE_NAME.to_owned()+".log"); #[cfg(not(debug_assertions))] - let log_filepath = std::path::PathBuf.new("/tmp/"+PACKAGE_NAME.to_owned()+".log"); + let log_filepath = std::path::Path::new("/tmp").join(format!("{}.log", PACKAGE_NAME)); #[cfg(debug_assertions)] let old_log_filepath = usdpl_back::api::dirs::home() .unwrap_or_else(|| "/tmp/".into()) diff --git a/src/usdpl_front/package.json b/src/usdpl_front/package.json index fd8c535..a769587 100644 --- a/src/usdpl_front/package.json +++ b/src/usdpl_front/package.json @@ -4,7 +4,7 @@ "NGnius (Graham) " ], "description": "Universal Steam Deck Plugin Library front-end designed for WASM", - "version": "0.6.2", + "version": "0.7.0", "license": "GPL-3.0-only", "repository": { "type": "git", diff --git a/src/usdpl_front/usdpl_front.d.ts b/src/usdpl_front/usdpl_front.d.ts index b986bed..8e30d2a 100644 --- a/src/usdpl_front/usdpl_front.d.ts +++ b/src/usdpl_front/usdpl_front.d.ts @@ -57,14 +57,16 @@ export interface InitOutput { readonly __wbindgen_export_6: (a: number, b: number, c: number, d: number) => void; } +export type SyncInitInput = BufferSource | WebAssembly.Module; /** -* Synchronously compiles the given `bytes` and instantiates the WebAssembly module. +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. * -* @param {BufferSource} bytes +* @param {SyncInitInput} module * * @returns {InitOutput} */ -export function initSync(bytes: BufferSource): InitOutput; +export function initSync(module: SyncInitInput): InitOutput; /** * If `module_or_path` is {RequestInfo} or {URL}, makes a request and diff --git a/src/usdpl_front/usdpl_front.js b/src/usdpl_front/usdpl_front.js index 98ebff0..be37538 100644 --- a/src/usdpl_front/usdpl_front.js +++ b/src/usdpl_front/usdpl_front.js @@ -21,6 +21,23 @@ function takeObject(idx) { return ret; } +const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + +cachedTextDecoder.decode(); + +let cachedUint8Memory0 = new Uint8Array(); + +function getUint8Memory0() { + if (cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + function addHeapObject(obj) { if (heap_next === heap.length) heap.push(heap.length + 1); const idx = heap_next; @@ -32,14 +49,6 @@ function addHeapObject(obj) { let WASM_VECTOR_LEN = 0; -let cachedUint8Memory0; -function getUint8Memory0() { - if (cachedUint8Memory0.byteLength === 0) { - cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); - } - return cachedUint8Memory0; -} - const cachedTextEncoder = new TextEncoder('utf-8'); const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' @@ -97,7 +106,8 @@ function isLikeNone(x) { return x === undefined || x === null; } -let cachedInt32Memory0; +let cachedInt32Memory0 = new Int32Array(); + function getInt32Memory0() { if (cachedInt32Memory0.byteLength === 0) { cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); @@ -105,15 +115,8 @@ function getInt32Memory0() { return cachedInt32Memory0; } -const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); - -cachedTextDecoder.decode(); - -function getStringFromWasm0(ptr, len) { - return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); -} +let cachedFloat64Memory0 = new Float64Array(); -let cachedFloat64Memory0; function getFloat64Memory0() { if (cachedFloat64Memory0.byteLength === 0) { cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); @@ -216,7 +219,8 @@ export function get_value(key) { return takeObject(ret); } -let cachedUint32Memory0; +let cachedUint32Memory0 = new Uint32Array(); + function getUint32Memory0() { if (cachedUint32Memory0.byteLength === 0) { cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); @@ -297,6 +301,10 @@ function getImports() { imports.wbg.__wbindgen_object_drop_ref = function(arg0) { takeObject(arg0); }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; imports.wbg.__wbindgen_object_clone_ref = function(arg0) { const ret = getObject(arg0); return addHeapObject(ret); @@ -309,10 +317,6 @@ function getImports() { getInt32Memory0()[arg0 / 4 + 1] = len0; getInt32Memory0()[arg0 / 4 + 0] = ptr0; }; - imports.wbg.__wbindgen_string_new = function(arg0, arg1) { - const ret = getStringFromWasm0(arg0, arg1); - return addHeapObject(ret); - }; imports.wbg.__wbindgen_number_new = function(arg0) { const ret = arg0; return addHeapObject(ret); @@ -336,30 +340,42 @@ function getImports() { const ret = getObject(arg0) === undefined; return ret; }; - imports.wbg.__wbg_instanceof_Window_a2a08d3918d7d4d0 = function(arg0) { - const ret = getObject(arg0) instanceof Window; + imports.wbg.__wbg_instanceof_Window_acc97ff9f5d2c7b4 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; return ret; }; - imports.wbg.__wbg_fetch_23507368eed8d838 = function(arg0, arg1) { + imports.wbg.__wbg_fetch_0fe04905cccfc2aa = function(arg0, arg1) { const ret = getObject(arg0).fetch(getObject(arg1)); return addHeapObject(ret); }; - imports.wbg.__wbg_instanceof_Response_e928c54c1025470c = function(arg0) { - const ret = getObject(arg0) instanceof Response; + imports.wbg.__wbg_instanceof_Response_eaa426220848a39e = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; return ret; }; - imports.wbg.__wbg_url_0f82030e7245954c = function(arg0, arg1) { + imports.wbg.__wbg_url_74285ddf2747cb3d = function(arg0, arg1) { const ret = getObject(arg1).url; const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); const len0 = WASM_VECTOR_LEN; getInt32Memory0()[arg0 / 4 + 1] = len0; getInt32Memory0()[arg0 / 4 + 0] = ptr0; }; - imports.wbg.__wbg_text_5cb78830c1a11c5b = function() { return handleError(function (arg0) { + imports.wbg.__wbg_text_1169d752cc697903 = function() { return handleError(function (arg0) { const ret = getObject(arg0).text(); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_newwithstrandinit_41c86e821f771b24 = function() { return handleError(function (arg0, arg1, arg2) { + imports.wbg.__wbg_newwithstrandinit_05d7180788420c40 = function() { return handleError(function (arg0, arg1, arg2) { const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); return addHeapObject(ret); }, arguments) }; @@ -372,15 +388,15 @@ function getImports() { const ret = false; return ret; }; - imports.wbg.__wbg_newnoargs_fc5356289219b93b = function(arg0, arg1) { + imports.wbg.__wbg_newnoargs_b5b063fc6c2f0376 = function(arg0, arg1) { const ret = new Function(getStringFromWasm0(arg0, arg1)); return addHeapObject(ret); }; - imports.wbg.__wbg_call_4573f605ca4b5f10 = function() { return handleError(function (arg0, arg1) { + imports.wbg.__wbg_call_97ae9d8645dc388b = function() { return handleError(function (arg0, arg1) { const ret = getObject(arg0).call(getObject(arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_new_306ce8d57919e6ae = function() { + imports.wbg.__wbg_new_0b9bfdd97583284e = function() { const ret = new Object(); return addHeapObject(ret); }; @@ -388,34 +404,34 @@ function getImports() { const ret = typeof(getObject(arg0)) === 'string'; return ret; }; - imports.wbg.__wbg_self_ba1ddafe9ea7a3a2 = function() { return handleError(function () { + imports.wbg.__wbg_self_6d479506f72c6a71 = function() { return handleError(function () { const ret = self.self; return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_window_be3cc430364fd32c = function() { return handleError(function () { + imports.wbg.__wbg_window_f2557cc78490aceb = function() { return handleError(function () { const ret = window.window; return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_globalThis_56d9c9f814daeeee = function() { return handleError(function () { + imports.wbg.__wbg_globalThis_7f206bda628d5286 = function() { return handleError(function () { const ret = globalThis.globalThis; return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_global_8c35aeee4ac77f2b = function() { return handleError(function () { + imports.wbg.__wbg_global_ba75c50d1cf384f4 = function() { return handleError(function () { const ret = global.global; return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_newwithlength_51bd08aed34ec6a3 = function(arg0) { + imports.wbg.__wbg_newwithlength_7c42f7e738a9d5d3 = function(arg0) { const ret = new Array(arg0 >>> 0); return addHeapObject(ret); }; - imports.wbg.__wbg_set_c1d04f8b45a036e7 = function(arg0, arg1, arg2) { + imports.wbg.__wbg_set_a68214f35c417fa9 = function(arg0, arg1, arg2) { getObject(arg0)[arg1 >>> 0] = takeObject(arg2); }; - imports.wbg.__wbg_call_9855a4612eb496cb = function() { return handleError(function (arg0, arg1, arg2) { + imports.wbg.__wbg_call_168da88779e35f61 = function() { return handleError(function (arg0, arg1, arg2) { const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_new_78403b138428b684 = function(arg0, arg1) { + imports.wbg.__wbg_new_9962f939219f1820 = function(arg0, arg1) { try { var state0 = {a: arg0, b: arg1}; var cb0 = (arg0, arg1) => { @@ -433,35 +449,35 @@ function getImports() { state0.a = state0.b = 0; } }; - imports.wbg.__wbg_resolve_f269ce174f88b294 = function(arg0) { + imports.wbg.__wbg_resolve_99fe17964f31ffc0 = function(arg0) { const ret = Promise.resolve(getObject(arg0)); return addHeapObject(ret); }; - imports.wbg.__wbg_then_1c698eedca15eed6 = function(arg0, arg1) { + imports.wbg.__wbg_then_11f7a54d67b4bfad = function(arg0, arg1) { const ret = getObject(arg0).then(getObject(arg1)); return addHeapObject(ret); }; - imports.wbg.__wbg_then_4debc41d4fc92ce5 = function(arg0, arg1, arg2) { + imports.wbg.__wbg_then_cedad20fbbd9418a = function(arg0, arg1, arg2) { const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); return addHeapObject(ret); }; - imports.wbg.__wbg_parse_5b823b8686817eb8 = function() { return handleError(function (arg0, arg1) { + imports.wbg.__wbg_parse_e23be3fecd886e2a = function() { return handleError(function (arg0, arg1) { const ret = JSON.parse(getStringFromWasm0(arg0, arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_stringify_cf20dc96bee34a66 = function() { return handleError(function (arg0) { + imports.wbg.__wbg_stringify_d6471d300ded9b68 = function() { return handleError(function (arg0) { const ret = JSON.stringify(getObject(arg0)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_set_b12cd0ab82903c2f = function() { return handleError(function (arg0, arg1, arg2) { + imports.wbg.__wbg_set_bf3f89b92d5a34bf = function() { return handleError(function (arg0, arg1, arg2) { const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); return ret; }, arguments) }; imports.wbg.__wbindgen_throw = function(arg0, arg1) { throw new Error(getStringFromWasm0(arg0, arg1)); }; - imports.wbg.__wbindgen_closure_wrapper336 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 66, __wbg_adapter_26); + imports.wbg.__wbindgen_closure_wrapper330 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 65, __wbg_adapter_26); return addHeapObject(ret); }; @@ -475,21 +491,24 @@ function initMemory(imports, maybe_memory) { function finalizeInit(instance, module) { wasm = instance.exports; init.__wbindgen_wasm_module = module; - cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); - cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); - cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); - cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + cachedFloat64Memory0 = new Float64Array(); + cachedInt32Memory0 = new Int32Array(); + cachedUint32Memory0 = new Uint32Array(); + cachedUint8Memory0 = new Uint8Array(); return wasm; } -function initSync(bytes) { +function initSync(module) { const imports = getImports(); initMemory(imports); - const module = new WebAssembly.Module(bytes); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); return finalizeInit(instance, module); @@ -517,7 +536,7 @@ export default init; // USDPL customization -const encoded = "AGFzbQEAAAABmwEXYAJ/fwBgAn9/AX9gAX8AYAN/f38Bf2AEf39/fwBgA39/fwBgAX8Bf2AAAX9gBH9/f38Bf2AFf39/f38AYAAAYAF/AX5gBX9/f39/AX9gBn9/f39/fwF/YAZ/f39/f38AYAV/f31/fwBgBX9/fH9/AGAEf31/fwBgBH98f38AYAJ+fwBgB39/f39/f38Bf2ADfn9/AX9gAXwBfwLLCSQDd2JnGl9fd2JpbmRnZW5fb2JqZWN0X2Ryb3BfcmVmAAIDd2JnG19fd2JpbmRnZW5fb2JqZWN0X2Nsb25lX3JlZgAGA3diZxVfX3diaW5kZ2VuX3N0cmluZ19nZXQAAAN3YmcVX193YmluZGdlbl9zdHJpbmdfbmV3AAEDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX25ldwAWA3diZxZfX3diaW5kZ2VuX2Jvb2xlYW5fZ2V0AAYDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX2dldAAAA3diZxJfX3diaW5kZ2VuX2lzX251bGwABgN3YmcXX193YmluZGdlbl9pc191bmRlZmluZWQABgN3YmcoX193YmdfaW5zdGFuY2VvZl9XaW5kb3dfYTJhMDhkMzkxOGQ3ZDRkMAAGA3diZxxfX3diZ19mZXRjaF8yMzUwNzM2OGVlZDhkODM4AAEDd2JnKl9fd2JnX2luc3RhbmNlb2ZfUmVzcG9uc2VfZTkyOGM1NGMxMDI1NDcwYwAGA3diZxpfX3diZ191cmxfMGY4MjAzMGU3MjQ1OTU0YwAAA3diZxtfX3diZ190ZXh0XzVjYjc4ODMwYzFhMTFjNWIABgN3YmcoX193YmdfbmV3d2l0aHN0cmFuZGluaXRfNDFjODZlODIxZjc3MWIyNAADA3diZxJfX3diaW5kZ2VuX2NiX2Ryb3AABgN3YmcgX193YmdfbmV3bm9hcmdzX2ZjNTM1NjI4OTIxOWI5M2IAAQN3YmcbX193YmdfY2FsbF80NTczZjYwNWNhNGI1ZjEwAAEDd2JnGl9fd2JnX25ld18zMDZjZThkNTc5MTllNmFlAAcDd2JnFF9fd2JpbmRnZW5faXNfc3RyaW5nAAYDd2JnG19fd2JnX3NlbGZfYmExZGRhZmU5ZWE3YTNhMgAHA3diZx1fX3diZ193aW5kb3dfYmUzY2M0MzAzNjRm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wABBkO/AADYCAEGQ78AAQYjvwAA2AgBBpO/AAEGY78AANgIAQZjvwABBkO/AADYCAEGs78AAQaDvwAA2AgBBoO/AAEGY78AANgIAQbTvwABBqO/AADYCAEGo78AAQaDvwAA2AgBBvO/AAEGw78AANgIAQbDvwABBqO/AADYCAEHE78AAQbjvwAA2AgBBuO/AAEGw78AANgIAQczvwABBwO/AADYCAEHA78AAQbjvwAA2AgBB1O/AAEHI78AANgIAQcjvwABBwO/AADYCAEHc78AAQdDvwAA2AgBB0O/AAEHI78AANgIAQeTvwABB2O/AADYCAEHY78AAQdDvwAA2AgBB7O/AAEHg78AANgIAQeDvwABB2O/AADYCAEH078AAQejvwAA2AgBB6O/AAEHg78AANgIAQfzvwABB8O/AADYCAEHw78AAQejvwAA2AgBB+O/AAEHw78AANgIAQQhBCBDMAiEBQRRBCBDMAiECQRBBCBDMAiEGQYzxwAAgAyADEIoDIgBBCBDMAiAAayIDEIgDIgA2AgBBhPHAACAFQQhqIAYgASACamogA2prIgE2AgAgACABQQFyNgIEQQhBCBDMAiEDQRRBCBDMAiECQRBBCBDMAiEFIAAgARCIA0Go8cAAQYCAgAE2AgAgBSACIANBCGtqajYCBAtBACECQYTxwAAoAgAiACAETQ0AQYTxwAAgACAEayIBNgIAQYzxwABBjPHAACgCACIAIAQQiAMiAzYCACADIAFBAXI2AgQgACAEEOYCIAAQigMhAgsgCUEQaiQAIAILxBECD38CfiMAQaAIayIHJAAgB0EIakEAQYAIEIQDGiAALAAEQQJ0QcitwABqKAIAIQUgACgCACEOIABBBWotAAAhDwJAAkADQCAEIAJJIhAEQAJAAkACQAJAIAIgBGsiACAOIA4gAEsbIgggBGoiCyAITwRAIAsgAksNAUEAIQYgASAEaiEMIAhBG0kEQEEAIQAMBQtBACAIQWZqIgAgACAISxshDUEAIQADQCAGQRpqIAhLDQMgAEHhB08NBCAHQYgIaiAGIAxqIgkQqgIgBy0AiAgNCSAHQQhqIABqIgQgBSAHKQCJCCITQjiGIhRCOoinai0AADoAACAEQQFqIAUgFCATQiiGQoCAgICAgMD/AIOEIhRCNIinQT9xai0AADoAACAEQQJqIAUg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wABBI0GwnMAAEIQCAAtBISEGIARBJEkNASAEEAAMAQsgA0EQahCoASADKAIMIQYLIAFBgAFqELwCIAFBAToApAFBAQshASAAIAY2AgQgACABRTYCACADQTBqJAAL3QUBCX8CQCACBEAgACgCBCEIIAAoAgAhCSAAKAIIIQcDQAJAIActAABFDQAgCUH40MAAQQQgCCgCDBEDAEUNAEEBDwtBACEGIAIhAwJAA0ACQCABIAZqIQQCQAJAAkACQCADQQhPBEAgBEEDakF8cSAEayIARQRAIANBeGohCkEAIQUMAwsgAyAAIAAgA0sbIQVBACEAA0AgACAEai0AAEEKRg0FIABBAWoiACAFRw0ACwwBCyADRQ0EQQAhACAELQAAQQpGDQMgA0EBRg0EQQEhACAELQABQQpGDQMgA0ECRg0EQQIhACAELQACQQpGDQMgA0EDRg0EQQMhACAELQADQQpGDQMgA0EERg0EQQQhACAELQAEQQpGDQMgA0EFRg0EQQUhACAELQAFQQpGDQMgA0EGRg0EQQYhACAELQAGQQpHDQQMAwsgBSADQXhqIgpLDQELA0ACQCAEIAVqIgsoAgAiAEF/cyAAQYqUqNAAc0H//ft3anFBgIGChHhxDQAgC0EEaigCACIAQX9zIABBipSo0ABzQf/9+3dqcUGAgYKEeHENACAFQQhqIgUgCk0NAQsLIAUgA00NACAFIAMQ/AIACyADIAVGDQEgBSADayEDIAQgBWohBEEAIQADQCAAIARqLQAAQQpHBEAgAyAAQQFqIgBqDQEMAwsLIAAgBWohAAsCQCAAIAZqIgBBAWoiBiAASSACIAZJcg0AIAAgAWotAABBCkcNACAHQQE6AAACQCACIAZNBEAgBiACIgBGDQUMAQsgASAGaiwAAEG/f0wNACAGIQAMBAsgASACQQAgBhChAgALIAIgBmshAyACIAZPDQELCyAHQQA6AAAgAiEACyAJIAEgACAIKAIMEQMABEBBAQ8LAkAgAiAATQRAIAAgAkYNAQwECyAAIAFqLAAAQb9/TA0DCyAAIAFqIQEgAiAAayICDQALC0EADwsgASACIAAgAhChAgALnAYCBH8BfiMAQTBrIgQkACAEIAEtAAAiBkEBajoACCAEQSBqIAIgBEEIakEBIAMoAgwiBREEAAJAAkACQAJAAkACQAJAAkAC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QhCJIAqFIghCFYkgCCAJQiCJfCIJhSEKIAxCIIkhCCAJIAuFIQkgBEEIaiIEIAJJDQALIAAgBzcDICAAIAk3AxAgACAKNwMoIAAgCDcDGAsgA0EDSw0BQgAhB0EADAILIAIgBWohAwwCCyABIARqNQAAIQdBBAsiAkEBciADSQRAIAEgAiAEamozAAAgAkEDdK2GIAeEIQcgAkECciECCyACIANJBH4gASACIARqajEAACACQQN0rYYgB4QFIAcLNwMwCyAAIAM2AjwLngUCBn8BfiMAQdAAayIDJAAgA0H/AToAByADQSBqIAEgA0EHakEBIAIoAiARBAACQAJAAkACQAJAAkACQAJAIAMtACBBBEcEQCADKQMgIgmnQf8BcUEGRw0BC0ECIQQCQAJAAkACQAJAAkACQAJAIAMtAAdBf2oOCAcGDgAFAQIEAwtBAyEEDAwLQQUhBAwLCyAAQQU6AAQMCQsgAEEFOgAEDAgLIANBIGogASACEEcgAykCJCEJIAMoAiAEQCAAIAk3AgQMCAsgCUIgiKchBiADQTBqKAIAIQUgA0EsaigCACEHIAmnIQhBByEEDAkLIANBIGogASACEEQgAykCJCEJIAMoAiBFDQUgACAJNwIEDAYLIANBIGogASACEHwgAygCIEUNAyAAIAMpAiQ3AgQMBQsgA0EgaiABIAIQViADKAIgRQ0BIAAgAykCJDcCBAwECyAAQQE2AgAgACAJNwIEDAYLIANBEGogA0E4aikDADcDACADQRhqIANBQGspAwA3AwAgAyADQTBqKQMANwMIIANBLGooAgAhByADQShqKAIAIQYgA0HIAGooAgAhBUEAIQQMBAsgA0EQaiADQThqKQMANwMAIAMgA0EwaikDADcDCCADQSxqKAIAIQcgA0EoaigCACEGIANBQGsoAgAhBUEBIQQMAwsgCUIgiKchBiADQTBqKAIAIQUgA0EsaigCACEHIAmnIQhBBCEEDAILIABBATYCAAwCCwsgAEEANgIAIABBGGogAykDCDcCACAAQTBqIAVBAWo2AgAgAEEUaiAHNgIAIABBEGogBjYCACAAQQxqIAg2AgAgAEEIaiAENgIAIABBKGogA0EYaikDADcCACAAQSBqIANBEGopAwA3AgALIANB0ABqJAALgAUBCn8jAEEwayIDJAAgA0EkaiABNgIAIANBAzoAKCADQoCAgICABDcDCCADIAA2AiAgA0EANgIYIANBADYCEAJAAkACQCACKAIIIgpFBEAgAkEUaigCACIERQ0BIAIoAgAhASACKAIQIQAgBEF/akH/////AXFBAWoiByEEA0AgAUEEaigCACIFBEAgAygCICABKAIAIAUgAygCJCgCDBEDAA0ECyAAKAIAIANBCGogAEEEaigCABEBAA0DIABBCGohACABQQhqIQEgBEF/aiIEDQALDAELIAJBDGooAgAiAEUNACAAQQV0IQsgAEF/akH///8/cUEBaiEHIAIoAgAhAQNAIAFBBGooAgAiAARAIAMoAiAgASgCACAAIAMoAiQoAgwRAwANAwsgAyAEIApqIgVBHGotAAA6ACggAyAFQQRqKQIAQiCJNwMIIAVBGGooAgAhBiACKAIQIQhBACEJQQAhAAJAAkACQCAFQRRqKAIAQQFrDgIAAgELIAZBA3QgCGoiDCgCBEH6AEcNASAMKAIAKAIAIQYLQQEhAAsgAyAGNgIUIAMgADYCECAFQRBqKAIAIQACQAJAAkAgBUEMaigCAEEBaw4CAAIBCyAAQQN0IAhqIgYoAgRB+gBHDQEgBigCACgCACEAC0EBIQkLIAMgADYCHCADIAk2AhggCCAFKAIAQQN0aiIAKAIAIANBCGogACgCBBEBAA0CIAFBCGohASALIARBIGoiBEcNAAsLQQAhACAHIAIoAgRJIgFFDQEgAygCICACKAIAIAdBA3RqQQAgARsiASgCACABKAIEIAMoAiQoAgwRAwBFDQELQQEhAAsgA0EwaiQAIAAL2wQBBn8jAEFAaiIDJAAgA0EIaiABIAIQ3AIgAyADKAIIIAMoAgwQ3AIgAyADKQMANwMQIANBMGogA0EQahA7AkACQAJAAkACQCADKAIwIgYEQCADKAI0IQEgA0E8aigCAA0CIAAgBjYCBAwBCyAAQejNwAA2AgRBACEBCyAAQQA2AgAgAEEIaiABNgIADAELAkAgAkUEQEEBIQUMAQsgAkF/TA0DIAJBARDaAiIFRQ0CCyADQQA2AiAgAyAFNgIYIAMgAjYCHCABIAJLBEAgA0EYakEAIAEQdSADKAIYIQUgAygCICEECyAEIAVqIAYgARCDAxogAyABIARqIgI2AiAgAygCHCACa0ECTQRAIANBGGogAkEDEHUg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BCEGA0ACQCADQTBqIAEgAhAvIAMoAjANACADQShqIAdBCGooAgAiBDYCACADIAcpAgAiCzcDICADKAI4IQggAygCSCEJIANBOGoiCiAENgIAIAMgCzcDMCADKAIYIgQgAygCFEYEQCADQRBqIAQQ6gEgAygCGCEECyAGIAlqIQYgAygCECAEQQR0aiIEIAMpAzA3AgQgBCAINgIAIARBDGogCigCADYCACADIAMoAhhBAWo2AhggBUF/aiIFDQEMAwsLIAMpAjQhCyAAQQE2AgAgACALNwIEIAMoAhgiAARAIAMoAhAhBCAAQQR0IQUDQCAELQAAIgBBfmpBB0kgAEVyRQRAIARBBGoQiQILIARBEGohBCAFQXBqIgUNAAsLIANBEGoQkAIMAgsgAEEBNgIAIAAgCzcCBAwBCyAAIAMpAxA3AgQgAEEANgIAIABBEGogBjYCACAAQQxqIANBGGooAgA2AgALIANB0ABqJAAL3AMDA38BfgF8IwBB4ABrIgIkACACIAE2AiwCQAJAQQFBAiABEAUiA0EBRhtBACADGyIDQQJHBEAgAEEIOgAAIAAgAzoAAQwBCyACQRhqIAEQBiACKAIYBEAgAisDICEGIABBAzoAACAAQQhqIAY5AwAMAQsgAkEQaiABEAICQCACKAIQIgNFBEAgAkEANgIwDAELIAIgAigCFCIENgJYIAIgBDYCVCACIAM2AlAgAkEIaiACQdAAahCaAiACQTBqIAIoAgggAigCDBDLAiACKAIwRQ0AIABBAToAACAAQQRqIAIpAzA3AgAgAEEMaiACQThqKAIANgIADAELAkACQAJAAkAgARAHQQFGDQAgARAIQQFGDQAgAiACQSxqEP4BIAIoAgQhASACKAIARQ0BIABBADoAACABQSRPDQIMAwsgAEEAOgAADAILIAIgATYCPCACQdAAaiACQTxqELwBIAIoAlBFDQMgAkHIAGogAkHYAGooAgAiAzYCACACIAIpA1AiBTcDQCAAQQxqIAM2AgAgAEEEaiAFNwIAIABBCToAACABQSRJDQELIAEQAAsgAigCLCEBCyABQSRPBEAgARAACyACQeAAaiQADwtBlJXAAEErQYicwAAQhAIAC6sEAgV/AX5BASEDAkAgASgCGCIEQScgAUEcaigCACgCECIFEQEADQBBAiEBQTAhAgJAAn4C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IGooAgA2AgALIANBgAFqJAALtAMBBH8jAEEgayICJAACQAJAAkACQAJAAkAgAC0AuAVBAWsOAwMAAgELAAsgAEHYAmogAEHYAhCDAxoLIAJBEGogAEHYAmoiAyABEJkBQQMhAQJAIAIoAhAiBEECRiIFDQAgAigCFCEBAkACQAJAIAAtAKgFDgQBAgIAAgsgAEGABGohAwsgAxCGAgsCQCAERQRAIAIgATYCGCACQSA2AhwgAiAAQbAFaiACQRxqIAJBGGoQ5QEgAigCAA0EIAIoAgQiAUEkTwRAIAEQAAsgAigCHCIBQSRPBEAgARAACyACKAIYIgFBJEkNASABEAAMAQsgAiABNgIYIAJBIDYCHCACQQhqIABBtAVqIAJBHGogAkEYahDlASACKAIIDQQgAigCDCIBQSRPBEAgARAACyACKAIcIgFBJE8EQCABEAALIAIoAhgiAUEkSQ0AIAEQAAsgACgCsAUiAUEkTwRAIAEQAAtBASEBIAAoArQFIgNBJEkNACADEAALIAAgAToAuAUgAkEgaiQAIAUPC0Ggj8AAQSNBiI/AABCEAgALQYCAwABBFRD2AgALQYCAwABBFRD2AgALsQMBAX8jAEFAaiICJAACQAJAAkACQAJAAkAgAC0AAEEBaw4DAQIDAAsgAiAAQQRqKAIANgIEQRRBARDaAiIARQ0EIABBEGpByMjAACgAADYAACAAQQhqQcDIwAApAAA3AAAgAEG4yMAAKQAANwAAIAJClICAgMACNwIMIAIgADYCCCACQTxqQQI2AgAgAkEkakHiADYCACACQgM3AiwgAkHAxsAANgIoIAJB4wA2AhwgAiACQRhqNgI4IAIgAkEEajYCICACIAJBCGo2AhggASACQShqELsBIQAgAigCDEEBSA0DIAIoAggQKwwDCyAALQABIQAgAkE8akEBNgIAIAJCATcCLCACQbzAwAA2AiggAkHkADYCDCACIABBIHNBP3FBAnQiAEHMyMAAaigCADYCHCACIABBzMrAAGooAgA2AhggAiACQQhqNgI4IAIgAkEYajYCCCABIAJBKGoQuwEhAAwCCyAAQQRqKAIAIgAoAgAgACgCBCABEP8CIQAMAQsgAEEEaigCACIAKAIAIAEgACgCBCgCEBEBACEACyACQUBrJAAgAA8LQRRBARD7AgAL+gIBBX8gAEEL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CSACQQRqQejlwAAQTBoCfyACLQAMIgEgAi0ADUUNABogAUH/AXEhAEEBIAANABogAigCCCIALQAAQQRxRQRAIAAoAhhBh9HAAEECIABBHGooAgAoAgwRAwAMAQsgACgCGEGG0cAAQQEgAEEcaigCACgCDBEDAAsgAkEQaiQAQf8BcUEARwvrAQECfyMAQTBrIgIkAAJ/AkACQAJAIAAtAABBfGoiA0ECIANB/wFxQQJJG0H/AXFBAWsOAgECAAsgAkEkakEANgIAIAJB0JzAADYCICACQgE3AhQgAkGsncAANgIQIAEgAkEQahC7AQwCCyACQSRqQQA2AgAgAkHQnMAANgIgIAJCATcCFCACQYidwAA2AhAgASACQRBqELsBDAELIAIgADYCDCACQSRqQQE2AgAgAkICNwIUIAJB4JzAADYCECACQTk2AiwgAiACQShqNgIgIAIgAkEMajYCKCABIAJBEGoQuwELIAJBMGokAAvrAQECfyMAQTBrIgIkAAJ/AkACQAJAIAAtAABBfGoiA0ECIANB/wFxQQJJG0H/AXFBAWsOAgECAAsgAkEkakEANgIAIAJB0JzAADYCICACQgE3AhQgAkGQnsAANgIQIAEgAkEQahC7AQwCCyACQSRqQQA2AgAgAkHQnMAANgIgIAJCATcCFCACQeydwAA2AhAgASACQRBqELsBDAELIAIgADYCDCACQSRqQQE2AgAgAkICNwIUIAJBxJ3AADYCECACQTk2AiwgAiACQShqNgIgIAIgAkEMajYCKCABIAJBEGoQuwELIAJBMGokAAvfAQICfwF+IwBBIGsiAyQAIAAoAgBFBEAgAEF/NgIAIANBGGogAEEkaikCADcDACADQRBqIABBHGopAgA3AwAgAEEUaikCACEFIABBGGpBADYCACADIAU3AwggA0EIahC9AgJAIAAoAgRBAkYNACAAQQRqKAIEIgRBJEkNACAEEAALIAAgAjYCCCAAIAE2AgQgACgCECEBIABBADYCECAAIAAoAgBBAWo2AgAgAQRAIAAoAgwgASgCBBECAAsgA0EgaiQADwtBzLnAAEEQIANBCGpB3LnAAEGku8AAEK4BAAu7AQECfyMAQSBrIgQkACAAAn9BACACIANqIgMgAkkNABogASgCBCICQQF0IgUgAyAFIANLGyIDQQggA0EISxsiBUF/c0EfdiEDIAQgAgR/IAQgASgCADYCECAEIAI2AhQgAkF/c0EfdgVBAAs2AhggBCAFIAMgBEEQahCQASAEKAIEIQMgBCgCAARAIARBCGooAgAMAQsgASAFNgIEIAEgAzYCAEGBgICAeAs2AgQgACADNgIAIARBIGokAAu8AQIBfwJ+IwBBIGsiAyQAIANCfzcDGCADIAEgA0EYakEIIAIoAiARBAAgAAJ/AkAgAy0AAEEERwRAIAMpAwAiBKdB/wFxQQZHDQELIAMpAxghBSADIAEgAhBAIAMpAgQhBCADKAIADQAgA0EMaigCACEBIABBIGogA0EQaigCAEEIajYCACAAQRhqIAE2AgAgAEEQaiAENwMAIABBCGogBTcDAEEADAELIAAgBDcCBEEBCzYCACADQSBqJAALtAEBAX8jAEFAaiIDJAAgA0EIakGACBDMASADQQA2AhggAyADKQMINwMQIANBIGogASACIANBEGoQJAJAIAMtACBBA0YEQCADQTBqIANBGGooAgA2AgAgAyADKQMQNwMoIANCADcDICAAIANBIGpB5I3AABA3IANBKGoQvAIMAQsgA0IFNwMgIANBOGogA0EgahDzAiAAIAMpAzg3AgQgAEEBNgIAIANBEGoQvAILIANBQGskAAvTAQECfyMAQTBrIgMkACADIAE2AgggAyABKAIIIgQ2AgwgA0EQaiACIAEQPSABKAIIIgIgBE8EQCADQSBqIAEoAgAgBGogAiAEaxAxAkAgAygCIEUEQCAAIAMpAxA3AgAgAEEIaiADQRhqKAIANgIAIAMgASgCCDYCDAwBCwJAIAMoAhBFBEAgAEECNgIEIABBCGpBnIvAADYCAAwBCyAAIAMpAhQ3AgQLIABBATYCAAsgA0EIaiIAKAIAIAAoAgQ2AgggA0EwaiQADwsgBCACEPwCAAu1AQECfyMAQTBrIgMkACADQYAIEMwBIANBADYCECADIAMpAwA3AwggA0EYaiABIANBCGpB4IzAABBhAkACQCADKAIYRQRAIAMoAhAiBCADKAIcIgFJDQIgAygCCCABIAIQ3AEgAEEANgIAIAAgATYCBAwBCyADIAMpAhw3AxggA0EoaiADQRhqEPMCIAAgAykDKDcCBCAAQQE2AgALIANBCGoQvAIgA0EwaiQADwsgASAEEP0CAAvVAQEFfyMAQRBr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IAJBGGogAEEIaigCADYCACACIAApAgA3AxAgAkEIaiACQRBqIAEQTSACKAIIIQAgAigCDCACQSBqJABBISAAGwtyAQF/IwBBMGsiAiQAIAIgATYCBCACIAA2AgAgAkEcakECNgIAIAJBLGpB5QA2AgAgAkICNwIMIAJBvNPAADYCCCACQeUANgIkIAIgAkEgajYCGCACIAJBBGo2AiggAiACNgIgIAJBCGpB7NPAABCPAgALcgEBfyMAQTBrIgIkACACIAE2AgQgAiAANgIAIAJBHGpBAjYCACACQSxqQeUANgIAIAJCAjcCDCACQdDUwAA2AgggAkHlADYCJCACIAJBIGo2AhggAiACQQRqNgIoIAIgAjYCICACQQhqQeDUwAAQjwIAC3IBAX8jAEEwayICJAAgAiABNgIEIAIgADYCACACQRxqQQI2AgAgAkEsakHlADYCACACQgI3AgwgAkGM1MAANgIIIAJB5QA2AiQgAiACQSBqNgIYIAIgAkEEajYCKCACIAI2AiAgAkEIakGc1MAAEI8CAAtvAQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EcakECNgIAIANBLGpB5QA2AgAgA0ICNwIMIANBpNDAADYCCCADQeUANgIkIAMgA0EgajYCGCADIAM2AiggAyADQQRqNgIgIANBCGogAhCPAgALVgECfyMAQSBrIgIkACAAQRxqKAIAIQMgACgCGCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCADIAJBCGoQOCACQSBqJAALaQECfyMAQSBrIgIkACACQQhqIAEoAgAQAgJAIAIoAggiAQRAIAIgAigCDCIDNgIYIAIgAzYCFCACIAE2AhAgAiACQRBqEJoCIAAgAigCACACKAIEEMsCDAELIABBADYCAAsgAkEgaiQAC2cBAX8jAEEgayIDJAAgACgCACADQQhqIAEgAhAxIAMoAggEQCADIAMpAgw3AxhB4K7AAEErIANBGGpBjK/AAEGAsMAAEK4BAAsgAygCDCIAIAAgA0EQaigCAGoQ+QEgA0EgaiQAQQALbQEEfyMAQRBrIgEkAAJAQQBByLzAACgCABEGACICBEAgACgCACgCACIAIAAoAgAiA0EBaiIENgIAIAQgA0kNASACIAAQoQEgAUEQaiQADwtBlLjAAEHGACABQQhqQdy4wABBvLnAABCuAQALAAtwAQF/AkACQAJAAkAgAC0AuAUOBAECAgACCyAAQdgCahC3AiAAKAKwBSIBQSRPBEAgARAACyAAKAK0BSIAQSNNDQEMAgsgABC3AiAAKAKwBSIBQSRPBEAgARAACyAAKAK0BSIAQSNLDQELDwsgABAAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBrIvAACACQQhqEDggAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB/JTAACACQQhqEDggAkEgaiQAC2EBA38gACABELACIAAoAgAiBCAAKAIIIgJqIQMCQAJAIAFBAk8EQCADQQAgAUF/aiIBEIQDGiAEIAEgAmoiAmohAwwBCyABRQ0BCyADQQA6AAAgAkEBaiECCyAAIAI2AggLWQEBfyMAQSBrIgIkACACIAAoAgA2AgQgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAkEEakHsv8AAIAJBCGoQOCACQSBqJAALaQAjAEEwayIBJABBgO3AAC0AAARAIAFBHGpBATYCACABQgI3AgwgAUH8xsAANgIIIAFB5QA2AiQgASAANgIsIAEgAUEgajYCGCABIAFBLGo2AiAgAUEIakGkx8AAEI8CAAsgAUEwaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0M3AACACQQhqEDggAkEgaiQAC2gBAn8gASgCACEDAkACQAJAIAFBCGooAgAiAUUEQEEBIQIMAQsgAUF/TA0BIAFBARDaAiICRQ0CCyACIAMgARCDAyECIAAgATYCCCAAIAE2AgQgACACNgIADwsQjgIACyABQQEQ+wIAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB7NLAACACQQhqEDggAkEgaiQAC44BAgF/An4jAEEQayIBJABB2OzAACAAOwEAQdDswABCATcDACABENQBIAEpAwghAiABKQMAIQNB9OzAACgCAARAQfDswAAoAgAEQBCFARDRAQsLQfjswABCADcDAEH07MAAQYiawAA2AgBB4OzAACADNwMAQejswAAgAjcDAEHw7MAAQQA2AgAgAUEQaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBrIvAACACQQhqEDggAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB/JTAACACQQhqEDggAkEgaiQAC2AAAkACQAJAAkACQCAAKAIADgcBAgMDBAMDAAsgAEEEaiIAEKcBIAAQkQIPCyAAQRBqELwCIABBHGoiABDdASAAEJACDwsgAEEQaiIAEN0BIAAQkAILDwsgAEEEahC8AgtIAQJ/AkAgAUUEQEEBIQIMAQsgAUEATgRAIAEgAUF/c0EfdiIDENoCIgINASABIAMQ+wIACxCOAgALIAAgATYCBCAAIAI2AgALXQECfyAAQQxqKAIAIgIgAkF/aiIDIAAoAgQiAiAAKAIAa3FrQQFGBEAgABCMASAAKAIMQX9qIQMgACgCBCECCyAAIAJBAWogA3E2AgQgACgCCCACQQJ0aiABNgIAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB7NLAACACQQhqEDggAkEgaiQAC2IBAX8jAEFAaiIBJAAgAUEBOgAPIABBADYCCCAAQgE3AgAgAUEQaiAAQYCEwAAQogIgAUEPaiABQRBqEI8BBEBBmITAAEE3IAFBOGpB0ITAAEGshcAAEK4BAAsgAUFAayQAC10BAX8jAEEQayIEJAAgASgCACACKAIAIAMoAgAQISECIARBCGoQpwIgAAJ/IAQoAghFBEAgACACQQBHOgABQQAMAQsgAEEEaiAEKAIMNgIAQQELOgAAIARBEGokAAtVAQN/AkACQAJAQfDswAAoAgAiAUEBaiIAQf////8AcSAARgRA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/AIACyAAIAIgA2s2AgQgACABKAIIIANqNgIAC0ABAX8jAEEgayIAJAAgAEEcakEANgIAIABBzMzAADYCGCAAQgE3AgwgAEHozMAANgIIIABBCGpBwM3AABCPAgALQwEDfwJAIAJFDQADQCAALQAAIgQgAS0AACIFRgRAIABBAWohACABQQFqIQEgAkF/aiICDQEMAgsLIAQgBWshAwsgAwtIAQJ/IAAtAABBA0YEQCAAQQRqKAIAIgEoAgAgASgCBCgCABECACABKAIEIgIoAgQEQCACKAIIGiABKAIAECsLIAAoAgQQKwsLSAEBfyMAQRBrIgIkACACQQhqIAAgARBrAkAgAigCDCIAQYGAgIB4RwRAIABFDQEgAigCCCAAEPsCAAsgAkEQaiQADwsQjgIAC0gBAX8jAEEQayICJAAgAkEIaiAAIAEQagJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABD7AgALIAJBEGokAA8LEI4CAAtKAQF/IwBBEGsiAiQAIAJBCGogACABQQEQewJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABD7AgALIAJBEGokAA8LEI4CAAtKAQF/IwBBEGsiAyQAIANBCGogACABIAIQewJAIAMoAgwiAEGBgICAeEcEQCAARQ0BIAMoAgggABD7AgALIANBEGokAA8LEI4CAAtQAQF/QSBBBBDaAiIBRQRAQSBBBBD7AgALIAFCgYCAgBA3AgAgASAAKQIANwIIIAFBEGogAEEIaikCADcCACABQRhqIABBEGopAgA3AgAgAQtLAQF/IAAoAgAiAQRAIAEgACgCBCgCABECACAAKAIEIgEoAgQEQCABKAIIGiAAKAIAECsLIABBCGooAgAgAEEMaigCACgCDBECAAsLTQECfyMAQRBrIgIkACAAKAIAIQMgAEEANgIAIANFBEBBlLrAAEEcEPYCAAsgAiADNgIMIANBCGpBASABEHogAkEMahCXASACQRBqJAALTQECfyMAQRBrIgIkACAAKAIAIQMgAEEANgIAIANFBEBBlLrAAEEcEPYCAAsgAiADNgIMIANBCGpBACABEHogAkEMahCXASACQRBqJAALSgEBfyAAKAIAIgBBBGooAgAgACgCCCIDayACSQRAIAAgAyACEHMgACgCCCEDCyAAKAIAIANqIAEg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MgEBfyAAAn9BACABKAIEIgJFDQAaIAAgAjYCBCAAIAEoAgA2AgAgAkF/c0Efdgs2AggLQAEBfyMAQSBrIgAkACAAQRxqQQA2AgAgAEHozcAANgIYIABCATcCDCAAQZjOwAA2AgggAEEIakGgzsAAEI8CAAs/AQF/IwBBIGsiAiQAIAJBAToAGCACIAE2AhQgAiAANgIQIAJBvNDAADYCDCACQaDPwAA2AgggAkEIahDfAQALKQEBfwJAIAAoAgQiAUUNACAAKAIAIAFBBHRFIAFB////P0tyDQAQKwsLKQEBfwJAIAAoAgQiAUUNACAAKAIAIAFBKGxFIAFBs+bMGUtyDQAQKwsLKgEBfwJAIAAoAgQiAUUNACAAKAIAIAFBAnRFIAFB/////wFLcg0AECsLCzMAAkAgAEH8////B0sNACAARQRAQQQPCyAAIABB/f///wdJQQJ0ENoCIgBFDQAgAA8LAAs0AQJ/IAFBeGoiAiACKAIAIgJBAWoiAzYCACADIAJJBEAACyAAQcy8wAA2AgQgACABNgIACzMBAX9BNEEEENoCIgFFBEBBNEEEEPsCAAsgAUKBgICAEDcCACABQQhqIABBLBCDAxogAQsvAQF/IwBBEGsiAiQAIAIgACgCADYCDCACQQxqIAEQYiACQQxqEPoBIAJBEGokAAsiAQF/AkAgACgCBCIBRQ0AIABBCGooAgBBAUgNACABECsLCyQAIwBBEGsiACQAIABBCGogARCjAiAAQQhqELABIABBEGokAAsyAQF/IAAgASgCBCABKAIIIgJLBH8gASACEPUBIAEoAggFIAILNgIEIAAgASgCADYCAAsyAQF/IAAgASgCBCABKAIIIgJLBH8gASACEPYBIAEoAggFIAILNgIEIAAgASgCADYCAAsjACAAKAIAIgBBcGoQvAIgAEF8aigCACIAQSRPBEAgABAACwsjAQF/An9BASABEAlFDQAaQQALIQIgACABNgIEIAAgAjYCAAsxAQF/QQRBBBDaAiICRQRAQQRBBBD7AgALIAIgATYCACAAQey5wAA2AgQgACACNgIACzEBAX9BBEEEENoCIgJFBEBBBEEEEPsCAAsgAiABNgIAIABBgLrAADYCBCAAIAI2AgALKgEBfyAAKAIABEAgABD6ASAAKAIEIgFBJE8EQCABEAALIABBCGoQxAIL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YTg4OWEvbGlicmFyeS9zdGQvc3JjL2lvL2ltcGxzLnJzAOgAEABLAAAA8gAAAA0AAAAvcnVzdGMvMjBmZmVhNjkzOGI1ODM5YzM5MDI1MmUwNzk0MGI5OWUzYjZhODg5YS9saWJyYXJ5L3N0ZC9zcmMvaW8vY3Vyc29yLnJzRAEQAEwAAADrAAAACgAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvc3RkL3NyYy9pby9yZWFkYnVmLnJzAAAAoAEQAE0AAADkAAAAKwAAAAcAAAAMAAAABAAAAAgAAAAJAAAACgAAAGEgRGlzcGxheSBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB1bmV4cGVjdGVkbHkAAwAAAAAAAAABAAAACwAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvYWxsb2Mvc3JjL3N0cmluZy5ycwBgAhAASwAAALkJAAAJAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZWNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAAAMAAAAAAAAAAQAAAAwAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvY2h1bmtlZF9lbmNvZGVyLnJzAAAAJAMQAGEAAAAtAAAAGgAAACQDEABhAAAANwAAAEQAAAAkAxAAYQAAADoAAAAnAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2VuY29kZS5yc7gDEABYAAAAtgAAACAAAAC4AxAAWAAAALcAAAAlAAAAuAMQAFgAAAD8AAAAHAAAALgDEABYAAAA/QAAACEAAAC4AxAAWAAAABMBAAAuAAAAuAMQAFgAAAATAQAACQAAALgDEABYAAAAFAEAAAkAAAC4AxAAWAAAAAsBAAAuAAAAuAMQAFgAAAALAQAACQAAALgDEABYAAAADQEAAA8AAAC4AxAAWAAAAAwBAAAJAAAAuAMQAFgAAAAPAQAACQAAALgDEABYAAAAoAAAACoAAAAwLjYuMnVzZHBsLWZyb250L3NyYy9saWIucnMA5QQQABYAAABgAAAAGAAAAOUEEAAWAAAAaAAAABgAAAAvcnVzdGMvMjBmZmVhNjkzOGI1ODM5YzM5MDI1MmUwNzk0MGI5OWUzYjZhODg5YS9saWJyYXJ5L3N0ZC9zcmMvaW8vbW9kLnJzAAAAHAUQAEkAAABQAQAAGAAAAHN0cmVhbSBkaWQgbm90IGNvbnRhaW4gdmFsaWQgVVRGLTgAAHgFEAAiAAAAFQAAACgpAAANAAAABAAAAAQAAAAOAAAADwAAABAAAAANAAAAAAAAAAEAAAARAAAAV3JpdGluZyB0byBhIFN0cmluZyBzaG91bGRuJ3QgZmFpbC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9lbmNvZGUucnMAAPYFEABYAAAAUwAAAA4AAAAVAAAADAAAAAQAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAL2hvbWUvbmduaXVzL0RvY3VtZW50cy9naXQtcmVwb3MvdXNkcGwtcnMvdXNkcGwtY29yZS9zcmMvc2VyZGVzL3RyYWl0cy5ycwAAAIgGEABJAAAAdgAAABwAAAAdAAAAGAAAAAgAAAAeAAAAHwAAACAAAAAhAAAAIgAAACMAAAAkAAAAJQAAAGB1bndyYXBfdGhyb3dgIGZhaWxlZC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93YXNtLWJpbmRnZW4tZnV0dXJlcy0wLjQuMzEvc3JjL2xpYi5ycyUHEABjAAAA2gAAACAAQaCPwAAL0EZgYXN5bmMgZm5gIHJlc3VtZWQgYWZ0ZXIgY29tcGxldGlvbmZhaWxlZCB0byB3cml0ZSB3aG9sZSBidWZmZXIAwwcQABwAAAAXAAAAJgAAAAwAAAAEAAAAJwAAACgAAAApAAAAZm9ybWF0dGVyIGVycm9yAAQIEAAPAAAAKAAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvc3RkL3NyYy9pby9tb2QucnMAAAAgCBAASQAAABoFAAAWAAAAIAgQAEkAAAAeBQAADQAAAGFkdmFuY2luZyBpbyBzbGljZXMgYmV5b25kIHRoZWlyIGxlbmd0aACMCBAAJwAAACAIEABJAAAAHAUAAA0AAAAqAAAADAAAAAQAAAArAAAAKgAAAAwAAAAEAAAALAAAACsAAADMCBAALQAAAC4AAAAvAAAAMAAAADEAAABjYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAAAyAAAAAAAAAAEAAAAzAAAAL3J1c3RjLzIwZmZlYTY5MzhiNTgzOWMzOTAyNTJlMDc5NDBiOTllM2I2YTg4OWEvbGlicmFyeS9zdGQvc3JjL3RocmVhZC9sb2NhbC5ycwBgCRAATwAAAKUBAAAJAAAAKgAAAAwAAAAEAAAANAAAADUAAAAKAAAAYSBEaXNwbGF5IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yIHVuZXhwZWN0ZWRseQAyAAAAAAAAAAEAAAALAAAAL3J1c3RjLzIwZmZlYTY5MzhiNTgzOWMzOTAyNTJlMDc5NDBiOTllM2I2YTg4OWEvbGlicmFyeS9hbGxvYy9zcmMvc3RyaW5nLnJzACAKEABLAAAAuQkAAAkAAAAyAAAABAAAAAQAAAA2AAAANwAAADgAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlaW50ZXJuYWwgZXJyb3I6IGVudGVyZWQgdW5yZWFjaGFibGUgY29kZTogAAAAvwoQACoAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJz9AoQAFgAAADSAQAAHwAAAPQKEABYAAAA2AEAAB8AAAD0ChAAWAAAAOEBAAAfAAAA9AoQAFgAAADqAQAAHwAAAPQKEABYAAAA8wEAAB8AAAD0ChAAWAAAAPwBAAAfAAAA9AoQAFgAAAAFAgAAHwAAAPQKEABYAAAADgIAAB8AAAD0ChAAWAAAAAMBAAAkAAAA9AoQAFgAAAAEAQAAKQAAAPQKEABYAAAAKgEAABYAAAD0ChAAWAAAAC0BAAAaAAAA9AoQAFgAAABBAQAADgAAAPQKEABYAAAARAEAABIAAAD0ChAAWAAAAFgBAAATAAAASW1wb3NzaWJsZTogbXVzdCBvbmx5IGhhdmUgMCB0byA4IGlucHV0IGJ5dGVzIGluIGxhc3QgY2h1bmssIHdpdGggbm8gaW52YWxpZCBsZW5ndGhzPAwQAFQAAAD0ChAAWAAAAJ0BAAAOAAAA9AoQAFgAAACxAQAACQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgb3V0cHV0IGJ1ZmZlciBsZW5ndGgAAPQKEABYAAAAlgAAAAoAAAD0ChAAWAAAAJsAAAAhAAAA//////////91c2RwbC1mcm9udC9zcmMvY29ubmVjdGlvbi5ycwAAABANEAAdAAAAGAAAACYAAABQT1NUaHR0cDovLzovdXNkcGwvY2FsbABEDRAABwAAAEsNEAABAAAATA0QAAsAAABsb2NhbGhvc3QAAABwDRAACQAAABANEAAdAAAAKwAAACQAAAAQDRAAHQAAADIAAAAnAAAARXhwZWN0ZWQgY2FsbCByZXNwb25zZSBtZXNzYWdlIGZyb20gLCBnb3Qgc29tZXRoaW5nIGVsc2WkDRAAJAAAAMgNEAAUAAAAdXNkcGwtZnJvbnQvc3JjL2NvbnZlcnQucnMAAOwNEAAaAAAAIAAAACcAAAB1c2RwbC1mcm9udC9zcmMvbGliLnJzAAAYDhAAFgAAAG8AAABOAAAAGA4QABYAAABuAAAAAQAAAExvYWRFcnJvcjogSW8oKQBQDhAADgAAAF4OEAABAAAATG9hZEVycm9yOiBJbnZhbGlkRGF0YQAAcA4QABYAAABMb2FkRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAkA4QABkAAABEdW1wRXJyb3I6IElvKAAAtA4QAA4AAABeDhAAAQAAAER1bXBFcnJvcjogVW5zdXBwb3J0ZWQAANQOEAAWAAAARHVtcEVycm9yOiBUb29TbWFsbEJ1ZmZlcgAAAPQOEAAZAAAAY3JhbmtzaGFmdAAAGA8QAAoAAABkZWNreQAAACwPEAAFAAAAYW55ADwPEAADAAAAISIjJCUmJygpKissLTAxMjM0NTY3ODlAQUJDREVGR0hJSktMTU5QUVJTVFVWWFlaW2BhYmNkZWhpamtsbXBxckFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5KywuL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Li8wMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5LV9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsv////////////////////////////////////////////AAECAwQFBgcICQoLDP//DQ4PEBESExQVFv///////xcYGRobHB0eHyAhIiMkJf8mJygpKiss/y0uLzD/////MTIzNDU2//83ODk6Ozz//z0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+P////zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn///////8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAE2Nzg5Ojs8PT4//////////wIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob////////HB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDX//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABAgMEBQYHCAkKC/////////8MDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJf///////yYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7//zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn/////P/8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pv///z80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////iBAQAEgQEAAIEBAAyA8QAIgPEABIDxAAyBUQAMgUEADIExAAyBIQAMgREADIEBAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2VuY29kZS5yc/gWEABYAAAAOwEAAAkAAABjYWxsZWQgYFJlc3VsdDo6dW53cmFwKClgIG9uIGFuIGBFcnJgIHZhbHVlADoAAAAIAAAABAAAADsAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvY2h1bmtlZF9lbmNvZGVyLnJzAAAAnBcQAGEAAABoAAAAMAAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgbnVtYmVyIG9mIGNodW5rcyBpbiBpbnB1dC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9kZWNvZGUucnMAQxgQAFgAAAC8AAAACgAAADwAAAAIAAAABAAAAD0AAAA+AAAAPAAAAAgAAAAEAAAAPwAAAGJvZHltZXRob2Rtb2Rlc2FtZS1vcmlnaW5uby1jb3JzY29yc25hdmlnYXRlYXR0ZW1wdGVkIHRvIGNvbnZlcnQgaW52YWxpZCBSZXF1ZXN0TW9kZSBpbnRvIEpTVmFsdWUvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2ViLXN5cy0wLjMuNTgvc3JjL2ZlYXR1cmVzL2dlbl9SZXF1ZXN0TW9kZS5yczEZEABrAAAAAwAAAAEAAABhbHJlYWR5IGJvcnJvd2VkQwAAAAAAAAABAAAARAAAAGFscmVhZHkgbXV0YWJseSBib3Jyb3dlZEMAAAAAAAAAAQAAAEUAAABhc3NlcnRpb24gZmFpbGVkOiBtaWQgPD0gc2VsZi5sZW4oKS9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvYWxsb2Mvc3JjL2NvbGxlY3Rpb25zL3ZlY19kZXF1ZS9tb2QucnNhc3NlcnRpb24gZmFpbGVkOiBzZWxmLmNhcCgpID09IG9sZF9jYXAgKiAyFxoQAF4AAADdCAAACQAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvYWxsb2Mvc3JjL2NvbGxlY3Rpb25zL3ZlY19kZXF1ZS9yaW5nX3NsaWNlcy5ycwAAsBoQAGYAAAAgAAAADgAAALAaEABmAAAAIwAAABEAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMxL3NyYy9xdWV1ZS5ycwAAADgbEABlAAAAGgAAAC4AAAA4GxAAZQAAAB0AAAApAAAAOBsQAGUAAAAyAAAAGgAAAEYAAAAEAAAABAAAAEcAAABIAAAAY2xvc3VyZSBpbnZva2VkIHJlY3Vyc2l2ZWx5IG9yIGRlc3Ryb3llZCBhbHJlYWR5Y2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAASgAAAAAAAAABAAAAMwAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMAbBwQAE8AAAClAQAACQAAAGFscmVhZHkgYm9ycm93ZWRKAAAAAAAAAAEAAABEAAAASwAAAAQAAAAEAAAATAAAAE0AAABLAAAABAAAAAQAAABOAAAATwAAAEZuT25jZSBjYWxsZWQgbW9yZSB0aGFuIG9uY2UvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMxL3NyYy9saWIucnMAMB0QAGMAAAClAAAADwAAADAdEABjAAAAhQAAACcAAAAwHRAAYwAAAK8AAAAkAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMS9zcmMvdGFzay9zaW5nbGV0aHJlYWQucnMAAADEHRAAcQAAACEAAAAVAAAAUAAAAFEAAABSAAAAUwAAAFQAAADEHRAAcQAAAFUAAAAlAAAAVQAAAHJldHVybiB0aGlzY2xvc3VyZSBpbnZva2VkIHJlY3Vyc2l2ZWx5IG9yIGRlc3Ryb3llZCBhbHJlYWR5Y2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAAGEAAAAAAAAAAQAAADMAAAAvcnVzdGMvMjBmZmVhNjkzOGI1ODM5YzM5MDI1MmUwNzk0MGI5OWUzYjZhODg5YS9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAAQfEABPAAAApQEAAAkAAABUcmllZCB0byBzaHJpbmsgdG8gYSBsYXJnZXIgY2FwYWNpdHlkHxAAJAAAAC9ydXN0Yy8yMGZmZWE2OTM4YjU4MzljMzkwMjUyZTA3OTQwYjk5ZTNiNmE4ODlhL2xpYnJhcnkvYWxsb2Mvc3JjL3Jhd192ZWMucnOQHxAATAAAAKoBAAAJAAAAZwAAAAQAAAAEAAAAaAAAAGkAAABqAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZUFjY2Vzc0Vycm9yAAAEIBAAAAAAAHVuY2F0ZWdvcml6ZWQgZXJyb3JvdGhlciBlcnJvcm91dCBvZiBtZW1vcnl1bmV4cGVjdGVkIGVuZCBvZiBmaWxldW5zdXBwb3J0ZWRvcGVyYXRpb24gaW50ZXJydXB0ZWRhcmd1bWVudCBsaXN0IHRvbyBsb25naW52YWxpZCBmaWxlbmFtZXRvbyBtYW55IGxpbmtzY3Jvc3MtZGV2aWNlIGxpbmsgb3IgcmVuYW1lZGVhZGxvY2tleGVjdXRhYmxlIGZpbGUgYnVzeXJlc291cmNlIGJ1c3lmaWxlIHRvbyBsYXJnZWZpbGVzeXN0ZW0gcXVvdGEgZXhjZWVkZWRzZWVrIG9uIHVuc2Vla2FibGUgZmlsZW5vIHN0b3JhZ2Ugc3BhY2V3cml0ZSB6ZXJvdGltZWQgb3V0aW52YWxpZCBkYXRhaW52YWxpZCBpbnB1dCBwYXJhbWV0ZXJzdGFsZSBuZXR3b3JrIGZpbGUgaGFuZGxlZmlsZXN5c3RlbSBsb29wIG9yIGluZGlyZWN0aW9uIGxpbWl0IChlLmcuIHN5bWxpbmsgbG9vcClyZWFkLW9ubHkgZmlsZXN5c3RlbSBvciBzdG9yYWdlIG1lZGl1bWRpcmVjdG9yeSBub3QgZW1wdHlpcyBhIGRpcmVjdG9yeW5vdCBhIGRpcmVjdG9yeW9wZXJhdGlvbiB3b3VsZCBibG9ja2VudGl0eSBhbHJlYWR5IGV4aXN0c2Jyb2tlbiBwaXBlbmV0d29yayBkb3duYWRkcmVzcyBub3QgYXZhaWxhYmxlYWRkcmVzcyBpbiB1c2Vub3QgY29ubmVjdGVkY29ubmVjdGlvbiBhYm9ydGVkbmV0d29yayB1bnJlYWNoYWJsZWhvc3QgdW5yZWFjaGFibGVjb25uZWN0aW9uIHJlc2V0Y29ubmVjdGlvbiByZWZ1c2VkcGVybWlzc2lvbiBkZW5pZWRlbnRpdHkgbm90IGZvdW5kIChvcyBlcnJvciApAAAABCAQAAAAAAAxIxAACwAAADwjEAABAAAAbWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAoAWCMQABUAAABtIxAADgAAAGxpYnJhcnkvc3RkL3NyYy9hbGxvYy5yc4wjEAAYAAAAUgEAAAkAAABsaWJyYXJ5L3N0ZC9zcmMvcGFuaWNraW5nLnJztCMQABwAAABHAgAADwAAALQjEAAcAAAARgIAAA8AAABrAAAADAAAAAQAAABsAAAAZwAAAAgAAAAEAAAAbQAAAG4AAAAQAAAABAAAAG8AAABwAAAAZwAAAAgAAAAEAAAAcQAAAHIAAABvcGVy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"; +const encoded = "AGFzbQEAAAABsAEaYAJ/fwF/YAJ/fwBgAX8AYAN/f38Bf2ADf39/AGAEf39/fwBgAX8Bf2AFf39/f38AYAABf2AEf39/fwF/YAAAYAV/f39/fwF/YAF/AX5gBn9/f39/fwF/YAZ/f39/f38AYAV/f35/fwBgBX9/fX9/AGAFf398f38AYAR/fn9/AGAEf31/fwBgBH98f38AYAJ+fwBgB39/f39/f38Bf2ADfn9/AX9gAXwBf2ACf38BfgLLCSQDd2JnGl9fd2JpbmRnZW5fb2JqZWN0X2Ryb3BfcmVmAAIDd2JnFV9fd2JpbmRnZW5fc3RyaW5nX25ldwAAA3diZxtfX3diaW5kZ2VuX29iamVjdF9jbG9uZV9yZWYABgN3YmcVX193YmluZGdlbl9zdHJpbmdfZ2V0AAEDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX25ldwAYA3diZxZfX3diaW5kZ2VuX2Jvb2xlYW5fZ2V0AAYDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX2dldAABA3diZxJfX3diaW5kZ2VuX2lzX251bGwABgN3YmcXX193YmluZGdlbl9pc191bmRlZmluZWQABgN3YmcoX193YmdfaW5zdGFuY2VvZl9XaW5kb3dfYWNjOTdmZjlmNWQyYzdiNAAGA3diZxxfX3diZ19mZXRjaF8wZmUwNDkwNWNjY2ZjMmFhAAADd2JnKl9fd2JnX2luc3RhbmNlb2ZfUmVzcG9uc2VfZWFhNDI2MjIwODQ4YTM5ZQAGA3diZxpfX3diZ191cmxfNzQyODVkZGYyNzQ3Y2IzZAABA3diZxtfX3diZ190ZXh0XzExNjlkNzUyY2M2OTc5MDMABgN3YmcoX193YmdfbmV3d2l0aHN0cmFuZGluaXRfMDVkNzE4MDc4ODQyMGM0MAADA3diZxJfX3diaW5kZ2VuX2NiX2Ryb3AABgN3YmcgX193YmdfbmV3bm9hcmdzX2I1YjA2M2ZjNmMyZjAzNzYAAAN3YmcbX193YmdfY2FsbF85N2FlOWQ4NjQ1ZGMzODhiAAADd2JnGl9fd2JnX25ld18wYjliZmRkOTc1ODMyODRlAAgDd2JnFF9fd2JpbmRnZW5faXNfc3RyaW5nAAYDd2JnG19fd2JnX3NlbGZfNmQ0Nzk1MDZmNzJjNmE3MQAIA3diZx1fX3di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AklyDQAgAEGBCEkEQCACIAdBCGogAGpBgAggAGsQ0AEgAGohAAwBCyAAQYAIQcCGwAAQ6QIACyAAQYEITw0CIAshBCADIAdBCGogABDOAUUNAQsLIAdBoAhqJAAgEA8LIABBgAhB0IbAABDqAgALQY+FwABBKyAHQZgIakG8hcAAQfiIwAAQrgEAC+sMAgV/AX4jAEGgAmsiAyQAIAACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAS0AYEEBaw4EAQADBgILAAtB4JDAAEEjQbiawAAQ/wEACyABIAEpAwA3AzAgA0HQAGogAUEIakEoEIUDGiABIAEvAVw7AV4gARASNgI4IAFBOGoiBRCrASAFEK0BIANBrAFqQR82AgAgA0GkAWpBHjYCACADIAFB3gBqNgKoASADQZSbwAA2AqABIANBIDYCnAEgAyABQTBqNgKYASADQQM2AtwBIANCBDcCzAEgA0HomsAANgLIASADIANBmAFqNgLYASADQZACaiADQcgBahA/IAFBxABqIANBmAJqKAIANgIAIAEgAykDkAI3AjwgA0HIAWogA0HQAGpBKBCFAxogA0GYAWogA0HIAWoQdCADKAKYASIERQ0BIAMoApwBIQYgAUHQAGogAygCoAEiBzYCACABQcwAaiAGNgIAIAEgBDYCSCADQZgBaiAEIAcQNSADQdABaiIEIANBoAFqKAIANgIAIAMgAykDmAE3A8gBIANB+ABqIANByAFqEKkBIAQgA0GAAWooAgA2AgAgAyADKQN4NwPIASADIANByAFqEPMBNgKYASAFIANBmAFqEJ0BIAMoApgBIgRBJE8EQCAEEAALIANByABqIAEoAjwgAUHEAGooAgAgBRDhASADKAJMIQUgAygCSA0KIAEgBTYCVCADQUBrENsBIAMoAkBFDQYgASADKAJENgJYIAEgAUHYAGooAgAgAUHUAGooAgAQChBDNgJoCyADQThqIAFB6ABqIgQgAhCBAUEDIQUgAygCOCIGQQJGDQYgAygCPCEFIAQQmAEgBg0IIANBMGogBRDfASADKAI0IQUgAygCMEUNAQwICyADKAKcASEFDAkLIAEgBTYCaCADQShqIAQQ5AEgAygCKCEEIAFB8ABqIAMoAiwiBTYCACABIAQ2AmwgBA0BIAEgBRBDNgJ0CyADQSBqIAFB9ABqIgQgAhCBAUEEIQUgAygCICICQQJGDQMgAygCJCEFIAQQmAEgAg0AIANBGGogBRDgASADKAIcIQQgAygCGEUNASAEIQULIAEoAmgiAkEkSQ0EIAIQAAwECyADQRBqIAQQAyADKAIQIgVFBEAgA0EANgLIAQwDCyADKAIUIQIgAyAFNgLIASADIAI2AtABIAMgAjYCzAEgA0EIaiADQcgBahCVAiADQcgBaiADKAIIIAMoAgwQywIgAygCyAFFDQIgA0GQAWogA0HQAWoiAigCACIFNgIAIAMgAykDyAEiCDcDiAEgA0HIAWogCKcgBRCMAQJ/AkAgAygCyAEiBkEIRwRAIAMoAswBIQUgA0GgAWogAkEoEIUDGiADIAU2ApwBIAMgBjYCmAEgBkEBRw0BIANBsAFqKAIAIQIgA0GoAWooAgAhByADQawBaigCAAwCCyADIAMpAswBNwOQAiADQZACahCeASEFIANBiAFqEK4CIARBJE8EQCAEEAALIAEoAmgiAkEkTwRAIAIQAAsgASgCWCICQSRPBEAgAhAACyABKAJUIgJBJE8EQCACEAALIAFByABqEK4CIAFBPGoQrgIgASgCOCICQSRJDQggAhAADAgLIANBkAJqIAFB6ABqENcBIANBITYCjAIgAyADQZACajYCiAIgA0EBNgLcASADQgI3AswBIANB9JvAADYCyAEgAyADQYgCajYC2AEgA0H4AWogA0HIAWoQPyADQZACahCuAkEAIQcgA0H4AWoQ8wELIQUgA0GIAWoQrgIgBEEkTwRAIAQQAAsgASgCaCIEQSRPBEAgBBAACyABKAJYIgRBJE8EQCAEEAALIAEoAlQiBEEkTwRAIAQQAAsgAUHIAGoQrgIgAUE8ahCuAiABKAI4IgRBJE8EQCAEEAALIAZBAUYNByADQZgBahDJAQwHC0H8k8AAQStBnJvAABD/AQALIAEgBToAYEEBDAYLQfyTwABBK0Gsm8AAEP8BAAsgASgCWCICQSRPBEAgAhAACyABKAJUIgJBJEkNACACEAALIAFByABqEK4CCyABQTxqEK4CIAEoAjgiAkEkSQ0AIAIQAAtBACEHCyAAIAc2AgQgAUEBOgBgIABBDGogAjYCACAAQQhqIAU2AgBBAAs2AgAgA0GgAmokAAviCgIPfwJ+IwBBIGsiBiQAAkBBlO7AACgCACIMQQFqIgEgDEkEQBDlASAGKAIEIQIgBigCACEBDAELAkACQAJAAkACQCABQYjuwAAoAgAiBCAEQQFqIglBA3ZBB2wgBEEISRsiDUEBdksEQCABIA1BAWoiAiABIAJLGyICQQhJDQEgAiACQf////8BcUYEQEF/IAJBA3RBB25Bf2pndkEBaiEBDAMLEOUBIAYoAgghASAGKAIMIgJBgYCAgHhHDQYMAgtBjO7AACgCACEDQQAhAQNAAkACfyACQQFxBEAgAUEHaiICIAFJIAIgCU9yDQIgAUEIagwBCyABIAlJIgVFDQEgASECIAEgBWoLIQEgAiADaiICIAIpAwAiEUJ/hUIHiEKBgoSIkKDAgAGDIBFC//79+/fv37//AIR8NwMAQQEhAgwBCwsCQAJAIAlBCE8EQCADIAlqIAMpAAA3AAAMAQsgA0EIaiADIAkQMyAJRQ0BCyADQXBqIQdBACEBIAMhCgNAAkAgAyABIgtqIg4tAABBgAFHDQAgByALQQR0ayEJIAMgC0F/c0EEdGohDwJAA0AgBEH47cAAIAkQQKciCHEiBSECIAMgBWopAABCgIGChIiQoMCAf4MiEFAEQEEIIQEgBSECA0AgASACaiECIAFBCGohASADIAIgBHEiAmopAABCgIGChIiQoMCAf4MiEFANAAsLIAMgEHqnQQN2IAJqIARxIgFqLAAAQX9KBEAgAykDAEKAgYKEiJCgwIB/g3qnQQN2IQELIAEgBWsgCyAFa3MgBHFBCEkNASABIANqIgItAAAgAiAIQRl2IgI6AAAgAUF4aiAEcSADakEIaiACOgAAQf8BRwRAIAMgAUEEdGshCEFwIQEDQCABIApqIgItAAAhBSACIAEgCGoiAi0AADoAACACIAU6AAAgAUEBaiIBDQALDAELCyAOQf8BOgAAIAtBeGogBHEgA2pBCGpB/wE6AAAgAyABQX9zQQR0aiICQQhqIA9BCGopAAA3AAAgAiAPKQAANwAADAELIA4gCEEZdiICOgAAIAtBeGogBHEgA2pBCGogAjoAAAsgC0EBaiEBIApBcGohCiAEIAtHDQALC0GQ7sAAIA0gDGs2AgAMAgtBBEEIIAJBBEkbIQELIAZBEGogARBjAkAgBigCFCIBBEAgBigCGCABQf8BIAYoAhAiCEEJahCEAyEHIAxrrSAMrUIghoQhESAJRQRAQZDuwAAgETcCAEGI7sAAIAg2AgBBjO7AACgCACEDQYzuwAAgBzYCAAwEC0GM7sAAKAIAIgNBcGohCwNAIAMgCmosAABBAE4EQCAHIAhB+O3AACALIApBBHRrEECnIgVxIgJqKQAAQoCBgoSIkKDAgH+DIhBQBEBBCCEBA0AgASACaiECIAFBCGohASAHIAIgCHEiAmopAABCgIGChIiQoMCAf4MiEFANAAsLIAcgEHqnQQN2IAJqIAhxIgFqLAAAQX9KBEAgBykDAEKAgYKEiJCgwIB/g3qnQQN2IQELIAEgB2ogBUEZdiICOgAAIAFBeGogCHEgB2pBCGogAjoAACAHIAFBf3NBBHRqIgFBCGogAyAKQX9zQQR0aiICQQhqKQAANwAAIAEgAikAADcAAAsgBCAKRiEBIApBAWohCiABRQ0ACwwBCyAGQRxqKAIAIQIgBigCGCEBDAQLQZDuwAAgETcCAEGM7sAAIAc2AgBBiO7AACAINgIAIAQNAQtBgYCAgHghAgwBC0GBgICAeCECIAQgCUEEdCIBakEJakUNACADIAFrECsLCyAAIAI2AgQgACABNgIAIAZBIGokAAu2CAEEfyMAQfAAayIFJAAgBSADNgIMIAUgAjYCCAJAAkACQAJAIAUCfwJAAkAgAUGBAk8EQANAIAAgBmogBkF/aiIHIQZBgAJqLAAAQb9/TA0ACyAHQYECaiIGIAFJDQIgAUH/fWogB0cNBCAFIAY2AhQMAQsgBSABNgIUCyAFIAA2AhBB/M/AACEHQQAMAQsgACAHakGBAmosAABBv39MDQEgBSAGNgIUIAUgADYCEEGU2MAAIQdBBQs2AhwgBSAHNgIYAkAgAiABSyIGIAMgAUtyRQRAAn8CQAJAIAIgA00EQAJAAkAgAkUNACACIAFPBEAgASACRg0BDAILIAAgAmosAABBQEgNAQsgAyECCyAFIAI2AiAgAiABIgZJBEAgAkEBaiIDQQAgAkF9aiIGIAYgAksbIgZJDQYgACADaiAAIAZqayEGA0AgBkF/aiEGIAAgAmogAkF/aiIHIQIsAABBQEgNAAsgB0EBaiEGCwJAIAZFDQAgBiABTwRAIAEgBkYNAQwKCyAAIAZqLAAAQb9/TA0JCyABIAZGDQcCQCAAIAZqIgEsAAAiAEF/TARAIAEtAAFBP3EhAyAAQR9xIQIgAEFfSw0BIAJBBnQgA3IhAAwECyAFIABB/wFxNgIkQQEMBAsgAS0AAkE/cSADQQZ0ciEDIABBcE8NASADIAJBDHRyIQAMAgsgBUHkAGpB+QA2AgAgBUHcAGpB+QA2AgAgBUHUAGpB5QA2AgAgBUHEAGpBBDYCACAFQgQ3AjQgBUH42MAANgIwIAVB5QA2AkwgBSAFQcgAajYCQCAFIAVBGGo2AmAgBSAFQRBqNgJYIAUgBUEMajYCUCAFIAVBCGo2AkgMCAsgAkESdEGAgPAAcSABLQADQT9xIANBBnRyciIAQYCAxABGDQULIAUgADYCJEEBIABBgAFJDQAaQQIgAEGAEEkNABpBA0EEIABBgIAESRsLIQcgBSAGNgIoIAUgBiAHajYCLCAFQcQAakEFNgIAIAVB7ABqQfkANgIAIAVB5ABqQfkANgIAIAVB3ABqQfsANgIAIAVB1ABqQfwANgIAIAVCBTcCNCAFQczZwAA2AjAgBUHlADYCTCAFIAVByABqNgJAIAUgBUEYajYCaCAFIAVBEGo2AmAgBSAFQShqNgJYIAUgBUEkajYCUCAFIAVBIGo2AkgMBQsgBSACIAMgBhs2AiggBUHEAGpBAzYCACAFQdwAakH5ADYCACAFQdQAakH5ADYCACAFQgM3AjQgBUG82MAANgIwIAVB5QA2AkwgBSAFQcgAajYCQCAFIAVBGGo2AlggBSAFQRBqNgJQIAUgBUEoajYCSAwECyAGIANBkNrAABDrAgALIAAgAUEAIAYgBBDXAgALQfzPwABBKyAEEP8BAAsgACABIAYgASAEENcCAAsgBUEwaiAEEI8CAAvwBwEIfwJAAkAgAEEDakF8cSICIABrIgUgAUsgBUEES3INACABIAVrIgdBBEkNACAHQQNxIQhBACEBAkAgACACRg0AIAVBA3EhAwJAIAIgAEF/c2pBA0kEQCAAIQIMAQsgBUF8cSEGIAAhAgNAIAEgAiwAAEG/f0pqIAIsAAFBv39KaiACLAACQb9/SmogAiwAA0G/f0pqIQEgAkEEaiECIAZBfGoiBg0ACwsgA0UNAANAIAEgAiwAAEG/f0pqIQEgAkEBaiECIANBf2oiAw0ACwsgACAFaiEAAkAgCEUNACAAIAdBfHFqIgIsAABBv39KIQQgCEEBRg0AIAQgAiwAAUG/f0pqIQQgCEECRg0AIAQgAiwAAkG/f0pqIQQLIAdBAnYhBSABIARqIQMDQCAAIQEgBUUNAiAFQcABIAVBwAFJGyIEQQNxIQYgBEECdCEIAkAgBEH8AXEiB0UEQEEAIQIMAQsgASAHQQJ0aiEJQQAhAgNAIABFDQEgAiAAKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIABBBGooAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWogAEEIaigCACICQX9zQQd2IAJBBnZyQYGChAhxaiAAQQxqKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIQIgAEEQaiIAIAlHDQALCyAFIARrIQUgASAIaiEAIAJBCHZB/4H8B3EgAkH/gfwHcWpBgYAEbEEQdiADaiEDIAZFDQALAkAgAUUEQEEAIQIMAQsgASAHQQJ0aiEAIAZBf2pB/////wNxIgJBAWoiBEEDcSEBAkAgAkEDSQRAQQAhAgwBCyAEQfz///8HcSEGQQAhAgNAIAIgACgCACICQX9zQQd2IAJBBnZyQYGChAhxaiAAQQRqKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIABBCGooAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWogAEEMaigCACICQX9zQQd2IAJBBnZyQYGChAhxaiECIABBEGohACAGQXxqIgYNAAsLIAFFDQADQCACIAAoAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWohAiAAQQRqIQAgAUF/aiIBDQALCyACQQh2Qf+B/AdxIAJB/4H8B3FqQYGABGxBEHYgA2oPCyABRQRAQQAPCyABQQNxIQICQCABQX9qQQNJBEAMAQsgAUF8cSEBA0AgAyAALAAAQb9/SmogACwAAUG/f0pqIAAsAAJBv39KaiAALAADQb9/SmohAyAAQQRqIQAgAUF8aiIBDQALCyACRQ0AA0AgAyAALAAAQb9/SmohAyAAQQFqIQAgAkF/aiICDQALCyADC5EHAQV/IAAQjAMiACAAEPoCIgIQiQMhAQJAAkACQCAAEPsCDQAgACgCACEDAkAgABDkAkUEQCACIANqIQIgACADEIoDIgBBoPLAACgCAEcNASABKAIEQQNxQQNHDQJBmPLAACACNgIAIAAgAiABEKsCDwsgAiADakEQaiEADAILIANBgAJPBEAgABBZDAELIABBDGooAgAiBCAAQQhqKAIAIgVHBEAgBSAENgIMIAQgBTYCCAwBC0GI78AAQYjvwAAoAgBBfiADQQN2d3E2AgALAkAgARDgAgRAIAAgAiABEKsCDAELAkACQAJAQaTywAAoAgAgAUcEQCABQaDywAAoAgBHDQFBoPLAACAANgIAQZjywABBmPLAACgCACACaiIBNgIAIAAgARDFAg8LQaTywAAgADYCAEGc8sAAQZzywAAoAgAgAmoiATYCACAAIAFBAXI2AgQgAEGg8sAAKAIARg0BDAILIAEQ+gIiAyACaiECAkAgA0GAAk8EQCABEFkMAQsgAUEMaigCACIEIAFBCGooAgAiAUcEQCABIAQ2AgwgBCABNgIIDAELQYjvwABBiO/AACgCAEF+IANBA3Z3cTYCAAsgACACEMUCIABBoPLAACgCAEcNAkGY8sAAIAI2AgAMAwtBmPLAAEEANgIAQaDywABBADYCAAtBwPLAACgCACABTw0BQQhBCBDMAiEAQRRBCBDMAiEBQRBBCBDMAiEDQQBBEEEIEMwCQQJ0ayICQYCAfCADIAAgAWpqa0F3cUF9aiIAIAIgAEkbRQ0BQaTywAAoAgBFDQFBCEEIEMwCIQBBFEEIEMwCIQFBEEEIEMwCIQJBAAJAQZzywAAoAgAiBCACIAEgAEEIa2pqIgJNDQBBpPLAACgCACEBQbDywAAhAAJAA0AgACgCACABTQRAIAAQ5gIgAUsNAgsgACgCCCIADQALQQAhAAsgABD8Ag0AIABBDGooAgAaDAALQQAQX2tHDQFBnPLAACgCAEHA8sAAKAIATQ0BQcDywABBfzYCAA8LIAJBgAJJDQEgACACEFhByPLAAEHI8sAAKAIAQX9qIgA2AgAgAA0AEF8aDwsPCyACQXhxQZDvwABqIQECf0GI78AAKAIAIgNBASACQQN2dCICcQRAIAEoAggMAQtBiO/AACACIANyNgIAIAELIQMgASAANgIIIAMgADYCDCAAIAE2AgwgACADNgIIC48HAQh/AkACQCAAKAIIIgpBAUdBACAAKAIQIgNBAUcbRQRAAkAgA0EBRw0AIAEgAmohCSAAQRRqKAIAQQFqIQcgASEEA0ACQCAEIQMgB0F/aiIHRQ0AIAMgCUYNAgJ/IAMsAAAiBUF/SgRAIAVB/wFxIQUgA0EBagwBCyADLQABQT9xIQggBUEfcSEEIAVBX00EQCAEQQZ0IAhyIQUgA0ECagwBCyADLQACQT9xIAhBBnRyIQggBUFwSQRAIAggBEEMdHIhBSADQQNqDAELIARBEnRBgIDwAHEgAy0AA0E/cSAIQQZ0cnIiBUGAgMQARg0DIANBBGoLIgQgBiADa2ohBiAFQYCAxABHDQEMAgsLIAMgCUYNACADLAAAIgRBf0ogBEFgSXIgBEFwSXJFBEAgBEH/AXFBEnRBgIDwAHEgAy0AA0E/cSADLQACQT9xQQZ0IAMtAAFBP3FBDHRycnJBgIDEAEYNAQsCQAJAIAZFDQAgBiACTwRAQQAhAyACIAZGDQEMAgtBACEDIAEgBmosAABBQEgNAQsgASEDCyAGIAIgAxshAiADIAEgAxshAQsgCkUNAiAAQQxqKAIAIQYCQCACQRBPBEAgASACECohBAwBCyACRQRAQQAhBAwBCyACQQNxIQUCQCACQX9qQQNJBEBBACEEIAEhAwwBCyACQXxxIQdBACEEIAEhAwNAIAQgAywAAEG/f0pqIAMsAAFBv39KaiADLAACQb9/SmogAywAA0G/f0pqIQQgA0EEaiEDIAdBfGoiBw0ACwsgBUUNAANAIAQgAywAAEG/f0pqIQQgA0EBaiEDIAVBf2oiBQ0ACwsgBiAESwRAIAYgBGsiBCEGAkACQAJAQQAgAC0AICIDIANBA0YbQQNxIgNBAWsOAgABAgtBACEGIAQhAwwBCyAEQQF2IQMgBEEBakEBdiEGCyADQQFqIQMgAEEcaigCACEEIABBGGooAgAhBSAAKAIEIQACQANAIANBf2oiA0UNASAFIAAgBCgCEBEAAEUNAAtBAQ8LQQEhAyAAQYCAxABGDQIgBSABIAIgBCgCDBEDAA0CQQAhAwNAIAMgBkYEQEEADwsgA0EBaiEDIAUgACAEKAIQEQAARQ0ACyADQX9qIAZJDwsMAgsgACgCGCABIAIgAEEcaigCACgCDBEDACEDCyADDwsgACgCGCABIAIgAEEcaigCACgCDBEDAAu0BwEOfwJAAkAgAigCGCILQSIgAkEcaigCACINKAIQIg4RAABFBEACQCABRQRADAELIAAgAWohDyAAIQcCQANAAkAgBywAACICQX9KBEAgB0EBaiEJIAJB/wFxIQQMAQsgBy0AAUE/cSEFIAJBH3EhBCACQV9NBEAgBEEGdCAFciEEIAdBAmohCQwBCyAHLQACQT9xIAVBBnRyIQUgB0EDaiEJIAJBcEkEQCAFIARBDHRyIQQMAQsgBEESdEGAgPAAcSAJLQAAQT9xIAVBBnRyciIEQYCAxABGDQIgB0EEaiEJC0EwIQVBgoDEACECAkACfwJAAkACQAJAAkACQAJAIAQOIwgBAQEBAQEBAQIEAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEFAAsgBEHcAEYNBAsgBBBKRQ0EIARBAXJnQQJ2QQdzDAULQfQAIQUMBQtB8gAhBQwEC0HuACEFDAMLIAQhBQwCC0GBgMQAIQIgBCEFIAQQbA0BIARBAXJnQQJ2QQdzCyEFIAQhAgsCQAJAIAJBgIC8f2oiCkEDIApBA0kbQQFGDQAgBiADSQ0BAkAgA0UNACADIAFPBEAgASADRg0BDAMLIAAgA2osAABBQEgNAgsCQCAGRQ0AIAYgAU8EQCABIAZHDQMMAQsgACAGaiwAAEG/f0wNAgsgCyAAIANqIAYgA2sgDSgCDBEDAARAQQEPC0EFIQgDQCAIIQwgAiEKQYGAxAAhAkHcACEDAkACQAJAAkACQAJAIApBgIC8f2oiEEEDIBBBA0kbQQFrDgMBBQACC0EAIQhB/QAhAyAKIQICQAJAAkAgDEH/AXFBAWsOBQcFAAECBAtBAiEIQfsAIQMMBQtBAyEIQfUAIQMMBAtBBCEIQdwAIQMMAwtBgIDEACECIAUiA0GAgMQARw0DCwJ/QQEgBEGAAUkNABpBAiAEQYAQSQ0AGkEDQQQgBEGAgARJGwsgBmohAwwECyAMQQEgBRshCEEwQdcAIAogBUECdHZBD3EiAkEKSRsgAmohAyAFQX9qQQAgBRshBQsgCiECCyALIAMgDhEAAEUNAAtBAQ8LIAYgB2sgCWohBiAJIgcgD0cNAQwCCwsgACABIAMgBkGo1MAAENcCAAsgA0UEQEEAIQMMAQsgAyABTwRAIAEgA0YNAQwECyAAIANqLAAAQb9/TA0DCyALIAAgA2ogASADayANKAIMEQMARQ0BC0EBDwsgC0EiIA4RAAAPCyAAIAEgAyABQbjUwAAQ1wIAC7UHAgZ/An4jAEEwayIDJAAgA0H/AToADyADQRBqIAEgA0EPakEBIAIoAiAiBhEFAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMtABBBBEcEQCADKQMQIglC/wGDQgZSDQELIAMtAA9Bf2oOChMQAgMEBQYHCQgBCyAAIAk3AgQMEwsgAEEFOgAEDBILIANBfzYCKCADQRBqIAEgA0EoakEEIAYRBQAgAy0AEEEERwRAIAMxABBCBlINDQsgAzUCKEKAgICAwACEIQlBBCEFQQIhBAwQCyADQn83AyggA0EQaiABIANBKGpBCCAGEQUAIAMtABBBBEcEQCADMQAQQgZSDQsLIAMpAygiCkIghiEJIApCIIinIQdBCCEFQQMhBAwPCyADQX82AiggA0EQaiABIANBKGpBBCAGEQUAIAMtABBBBEcEQCADKQMQIglC/wGDQgZSDQkLIAM1AighCUEEIQRBBCEFDA4LIANCfzcDICADQShqIAEgA0EgakEIIAYRBQAgAy0AKEEERwRAIAMpAygiCUL/AYNCBlINBwsgAyADKQMgIgk3AhQgCUIgiKchByADKQMQIQlBCCEFQQUhBAwNCyADQX82AiggA0EQaiABIANBKGpBBCAGEQUAIAMtABBBBEcEQCADKQMQIglC/wGDQgZSDQULIAM1AighCUEEIQVBBiEEDAwLIANCfzcDICADQShqIAEgA0EgakEIIAYRBQAgAy0AKEEERwRAIAMpAygiCUL/AYNCBlINAwsgAyADKQMgIgk3AhQgCUIgiKchByADKQMQIQlBCCEFQQchBAwLCyADQRBqIAEgAhBFIAMoAhBFDQggAygCGCEHIAMpAxAhCSADKAIcIQVBCSEEDAoLIANBEGogASACEKoBIAMoAhBFDQggACADKQIUNwIEDAoLIAAgCTcCBAwJCyAAIAk3AgQMCAsgACAJNwIEDAcLIAAgCTcCBAwGCyAAIAM1AhAgAzUCFEIghoQ3AgQMBQsgACADNQIQIAM1AhRCIIaENwIEDAQLIANBEGogASACEEUgAygCEARAIAMoAhghByADKQMQIQkgAygCHCEFQQEhBAwDCyAAIAMpAhQ3AgQMAwsgACADKQIUNwIEDAILQQghBCADQRhqKAIAIQUgAy0AFCEICyAAIAc2AAwgACAJNwAEIAAgCDoAASAAIAQ6AAAgACAFQQFqNgIQDAELIABBCjoAAAsgA0EwaiQAC48HAQZ/AkACQAJAIAJBCU8EQCADIAIQRiICDQFBAA8LQQhBCBDMAiEBQRRBCBDMAiEFQRBBCBDMAiEEQQAhAkEAQRBBCBDMAkECdGsiBkGAgHwgBCABIAVqamtBd3FBfWoiASAGIAFJGyADTQ0BQRAgA0EEakEQQQgQzAJBe2ogA0sbQQgQzAIhBSAAEIwDIgEgARD6AiIGEIkDIQQCQAJAAkACQAJAAkACQCABEOQCRQRAIAYgBU8NASAEQaTywAAoAgBGDQIgBEGg8sAAKAIARg0DIAQQ4AINByAEEPoCIgcgBmoiCCAFSQ0HIAggBWshBiAHQYACSQ0EIAQQWQwFCyABEPoCIQQgBUGAAkkNBiAEIAVBBGpPQQAgBCAFa0GBgAhJGw0FIAEoAgAiBiAEakEQaiEHIAVBH2pBgIAEEMwCIQRBACIFRQ0GIAUgBmoiASAEIAZrIgBBcGoiAjYCBCABIAIQiQNBBzYCBCABIABBdGoQiQNBADYCBEGo8sAAQajywAAoAgAgBCAHa2oiADYCAEHE8sAAQcTywAAoAgAiAiAFIAUgAksbNgIAQazywABBrPLAACgCACICIAAgAiAASxs2AgAMCQsgBiAFayIEQRBBCBDMAkkNBCABIAUQiQMhBiABIAUQogIgBiAEEKICIAYgBBA5DAQLQZzywAAoAgAgBmoiBiAFTQ0EIAEgBRCJAyEEIAEgBRCiAiAEIAYgBWsiBUEBcjYCBEGc8sAAIAU2AgBBpPLAACAENgIADAMLQZjywAAoAgAgBmoiBiAFSQ0DAkAgBiAFayIEQRBBCBDMAkkEQCABIAYQogJBACEEQQAhBgwBCyABIAUQiQMiBiAEEIkDIQcgASAFEKICIAYgBBDFAiAHIAcoAgRBfnE2AgQLQaDywAAgBjYCAEGY8sAAIAQ2AgAMAgsgBEEMaigCACIJIARBCGooAgAiBEcEQCAEIAk2AgwgCSAENgIIDAELQYjvwABBiO/AACgCAEF+IAdBA3Z3cTYCAAsgBkEQQQgQzAJPBEAgASAFEIkDIQQgASAFEKICIAQgBhCiAiAEIAYQOQwBCyABIAgQogILIAENAwsgAxAlIgVFDQEgBSAAIAEQ+gJBeEF8IAEQ5AIbaiIBIAMgASADSRsQhQMgABArDwsgAiAAIAEgAyABIANJGxCFAxogABArCyACDwsgARDkAhogARCLAwuHBgEIfwJAIAJFDQBBACACQXlqIgQgBCACSxshCSABQQNqQXxxIAFrIQpBACEEA0ACQAJAAkACQAJAAkACQAJAAkAgASAEai0AACIHQRh0QRh1IghBAE4EQCAKIARrQQNxIApBf0ZyDQEgBCAJSQ0CDAgLQQEhBkEBIQMCQAJAAkACQAJAAkACQAJAIAdBlNbAAGotAABBfmoOAwABAg4LIARBAWoiBSACSQ0GQQAhAwwNC0EAIQMgBEEBaiIFIAJPDQwgASAFaiwAACEFIAdBoH5qIgNFDQEgA0ENRg0CDAMLIARBAWoiAyACTwRAQQAhAwwMCyABIANqLAAAIQUCQAJAAkAgB0GQfmoOBQEAAAACAAsgCEEPakH/AXFBAksEQEEBIQMMDgsgBUF/TA0JQQEhAwwNCyAFQfAAakH/AXFBMEkNCQwLCyAFQY9/Sg0KDAgLIAVBYHFBoH9HDQkMAgsgBUGgf04NCAwBCwJAIAhBH2pB/wFxQQxPBEAgCEF+cUFuRwRAQQEhAwwLCyAFQX9MDQFBASEDDAoLIAVBv39KDQgMAQtBASEDIAVBQE8NCAtBACEDIARBAmoiBSACTw0HIAEgBWosAABBv39MDQVBASEDQQIhBgwHCyABIAVqLAAAQb9/Sg0FDAQLIARBAWohBAwHCwNAIAEgBGoiAygCAEGAgYKEeHENBiADQQRqKAIAQYCBgoR4cQ0GIARBCGoiBCAJSQ0ACwwFC0EBIQMgBUFATw0DCyAEQQJqIgMgAk8EQEEAIQMMAwsgASADaiwAAEG/f0oEQEECIQZBASEDDAMLQQAhAyAEQQNqIgUgAk8NAiABIAVqLAAAQb9/TA0AQQMhBkEBIQMMAgsgBUEBaiEEDAMLQQEhAwsgACAENgIEIABBCWogBjoAACAAQQhqIAM6AAAgAEEBNgIADwsgBCACTw0AA0AgASAEaiwAAEEASA0BIAIgBEEBaiIERw0ACwwCCyAEIAJJDQALCyAAIAE2AgQgAEEIaiACNgIAIABBADYCAAuABgEHfwJ/IAEEQEErQYCAxAAgACgCACIIQQFxIgEbIQogASAFagwBCyAAKAIAIQhBLSEKIAVBAWoLIQcCQCAIQQRxRQRAQQAhAgwBCwJAIANBEE8EQCACIAMQKiEGDAELIANFBEAMAQsgA0EDcSEJAkAgA0F/akEDSQRAIAIhAQwBCyADQXxxIQsgAiEBA0AgBiABLAAAQb9/SmogASwAAUG/f0pqIAEsAAJBv39KaiABLAADQb9/SmohBiABQQRqIQEgC0F8aiILDQALCyAJRQ0AA0AgBiABLAAAQb9/SmohBiABQQFqIQEgCUF/aiIJDQALCyAGIAdqIQcLAkACQCAAKAIIRQRAQQEhASAAQRhqKAIAIgcgAEEcaigCACIAIAogAiADEIwCDQEMAgsCQAJAAkACQCAAQQxqKAIAIgYgB0sEQCAIQQhxDQQgBiAHayIGIQdBASAALQAgIgEgAUEDRhtBA3EiAUEBaw4CAQIDC0EBIQEgAEEYaigCACIHIABBHGooAgAiACAKIAIgAxCMAg0EDAULQQAhByAGIQEMAQsgBkEBdiEBIAZBAWpBAXYhBwsgAUEBaiEBIABBHGooAgAhBiAAQRhqKAIAIQggACgCBCEAAkADQCABQX9qIgFFDQEgCCAAIAYoAhARAABFDQALQQEPC0EBIQEgAEGAgMQARg0BIAggBiAKIAIgAxCMAg0BIAggBCAFIAYoAgwRAwANAUEAIQECfwNAIAcgASAHRg0BGiABQQFqIQEgCCAAIAYoAhARAABFDQALIAFBf2oLIAdJIQEMAQsgACgCBCELIABBMDYCBCAALQAgIQxBASEBIABBAToAICAAQRhqKAIAIgggAEEcaigCACIJIAogAiADEIwCDQAgBiAHa0EBaiEBAkADQCABQX9qIgFFDQEgCEEwIAkoAhARAABFDQALQQEPC0EBIQEgCCAEIAUgCSgCDBEDAA0AIAAgDDoAICAAIAs2AgRBAA8LIAEPCyAHIAQgBSAAKAIMEQMAC8gGAgZ/AX4jAEEwayIDJAACfwJAAkACQAJAAkACQAJAAkAgAS0AtAFBAWsOAwMAAgELAAsgASABKQN4NwOQASABIAEpAoQBNwKcASABQZgBaiABQYABaigCADYCACABQaQBaiIFIAFBjAFqKAIAIgQ2AgBB6O3AAEHo7cAAKQMAIglCAXw3AwAgAyAEEJABIAMoAgAhBCABQbABakEANgIAIAFBrAFqIAMoAgQ2AgAgASAENgKoASABQaABaigCACEGIAMgASgCnAEiBCAFKAIAIgVBAnQiCGoiBzYCHCADIAQ2AhggAyAGNgIUIAMgBDYCECABQagBaiEGIAUEQANAIANBIGogBCgCABBBIAEoArABIgUgASgCrAFGBEAgBiAFEOcBIAEoArABIQULIARBBGohBCABKAKoASAFQQR0aiIFIAMpAyA3AwAgBUEIaiADQShqKQMANwMAIAEgASgCsAFBAWo2ArABIAhBfGoiCA0ACyADIAc2AhgLIANBEGoQsgFB8O3AAC8BACEEIANBEGogAUGQAWoQxAEgASAJNwMQIAFBADYCCCABIAk3AwAgAUEAOgBgIAEgBDsBXCABIAMpAxA3AxggAUEgaiADQRhqKAIANgIAIAEgBikCADcCJCABQSxqIAZBCGooAgA2AgALIANBIGogASACECcgAygCIEUEQCADQSxqKAIAIQIgA0EoaigCACEFIAMoAiQhBCABEJwBIARFDQIgAyACEBg2AgwgAyAEIAJBBHRqIgY2AhwgAyAENgIYIAMgBTYCFCADIAQ2AhAgAkUNBEEAIQUgA0EgakEBciICQQdqIQgDQCAELQAAIgdBCkYEQCAEQRBqIQYMBQsgAiAEKQABNwAAIAggBEEIaikAADcAACADIAc6ACAgA0EgahBVIQcgA0EMaigCACAFIAcQGSAFQQFqIQUgBEEQaiIEIAZHDQALDAMLIAFBAzoAtAFBAAwFC0HgkMAAQSNByJzAABD/AQALQSEhBCAFQSRJDQIgBRAADAILIAMgBjYCGAsgA0EQahCnASADKAIMIQQLIAFBkAFqEK4CIAFBAToAtAFBAQshASAAIAQ2AgQgACABRTYCACADQTBqJAALkgUBB38CQAJAAn8CQCAAIAFrIAJJBEAgASACaiEFIAAgAmohAyACQQ9LDQEgAAwCCyACQQ9NBEAgACEDDAMLIABBACAAa0EDcSIFaiEEIAUEQCAAIQMgASEAA0AgAyAALQAAOgAAIABBAWohACADQQFqIgMgBEkNAAsLIAQgAiAFayICQXxxIgZqIQMCQCABIAVqIgVBA3EiAARAIAZBAUgNASAFQXxxIgdBBGohAUEAIABBA3QiCGtBGHEhCSAHKAIAIQADQCAEIAAgCHYgASgCACIAIAl0cjYCACABQQRqIQEgBEEEaiIEIANJDQALDAELIAZBAUgNACAFIQEDQCAEIAEoAgA2AgAgAUEEaiEBIARBBGoiBCADSQ0ACwsgAkEDcSECIAUgBmohAQwCCyADQXxxIQBBACADQQNxIgZrIQcgBgRAIAEgAmpBf2ohBANAIANBf2oiAyAELQAAOgAAIARBf2ohBCAAIANJDQALCyAAIAIgBmsiBkF8cSICayEDQQAgAmshAgJAIAUgB2oiBUEDcSIEBEAgAkF/Sg0BIAVBfHEiB0F8aiEBQQAgBEEDdCIIa0EYcSEJIAcoAgAhBANAIABBfGoiACAEIAl0IAEoAgAiBCAIdnI2AgAgAUF8aiEBIAMgAEkNAAsMAQsgAkF/Sg0AIAEgBmpBfGohAQNAIABBfGoiACABKAIANgIAIAFBfGohASADIABJDQALCyAGQQNxIgBFDQIgAiAFaiEFIAMgAGsLIQAgBUF/aiEBA0AgA0F/aiIDIAEtAAA6AAAgAUF/aiEBIAAgA0kNAAsMAQsgAkUNACACIANqIQADQCADIAEtAAA6AAAgAUEBaiEBIANBAWoiAyAASQ0ACwsLhwYCBH8BfiMAQSBrIgQkACAEIAEtAAAiBkEBajoAECAEQRhqIAIgBEEQakEBIAMoAgwiBREFAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfyAELQAYQQRGBEAgBCgCHAwBCyAEKQMYIghC/wGDQgZSDQEgCEIgiKcLIQcgBkEBaw4JAQIDBAUGBwgJCwsgACAINwIADAwLIARBCGogAUEEaiACIAMQfQwICyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQUAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAgLIAQgBCkDGDcDCAwHCyAEIAErAwg5AxggBEEQaiACIARBGGpBCCAFEQUAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAcLIAQgBCkDEDcDCAwGCyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQUAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAYLIAQgBCkDGDcDCAwFCyAEIAEpAwg3AxggBEEQaiACIARBGGpBCCAFEQUAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAULIAQgBCkDEDcDCAwECyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQUAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAQLIAQgBCkDGDcDCAwDCyAEIAEpAwg3AxggBEEQaiACIARBGGpBCCAFEQUAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAMLIAQgBCkDEDcDCAwCCyAEIAEtAAE6ABAgBEEYaiACIARBEGpBASAFEQUAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAILIAQgBCkDGDcDCAwBCyAEQQhqIAFBBGogAiADEH0LIAQtAAhBBkYEQCAEKAIMIQYMAQsgBCkDCCIIQv8Bg0IGUg0BIAhCIIinIQYLIABBBjoAACAAIAYgB2o2AgQMAQsgACAINwIACyAEQSBqJAALyAUBBX8jAEHwAGsiAyQAIANBKGogASACEN0CIAMgAykDKDcDMCADQdAAaiADQTBqEDsCQCADKAJQBEAgA0HoAGogA0HYAGopAwA3AwAgAyADKQNQNwNgIANBIGogA0HgAGoQgAMgAygCJCEEIAMoAiAhBiADQRhqIANB4ABqEIEDIAMoAhxFBEAgACAGNgIEIABBADYCACAAQQhqIAQ2AgAMAgsCQAJAAkAgAkUEQEEBIQEMAQsgAkF/TA0CIAJBARDbAiIBRQ0BCyADQQA2AkAgAyABNgI4IAMgAjYCPCAEIAJLBH8gA0E4akEAIAQQeSADKAJAIQUgAygCOAUgAQsgBWogBiAEEIUDGiADIAQgBWoiAjYCQCADKAI8IAJrQQJNBEAgA0E4aiACQQMQeSADKAJAIQILIAMoAjgiASACaiIEQfjPwAAvAAAiBTsAACAEQQJqQfrPwAAtAAAiBjoAACADIAJBA2oiAjYCQCADIAMpAzA3A0ggA0HQAGogA0HIAGoQOyADKAJQBEADQCADQegAaiADQdgAaikDADcDACADIAMpA1A3A2AgA0EQaiADQeAAahCAAyADKAIQIQcgAygCPCACayADKAIUIgRJBEAgA0E4aiACIAQQeSADKAJAIQIgAygCOCEBCyABIAJqIAcgBBCFAxogAyACIARqIgI2AkAgA0EIaiADQeAAahCBAyADKAIMBEAgAygCPCACa0ECTQRAIANBOGogAkEDEHkgAygCQCECCyADKAI4IgEgAmoiBCAFOwAAIARBAmogBjoAACADIAJBA2oiAjYCQAsgA0HQAGogA0HIAGoQOyADKAJQDQALCyAAIAMpAzg3AgAgAEEIaiADQUBrKAIANgIADAMLIAJBARD+AgALEI4CAAsgAEHEzsAANgIEIABBADYCACAAQQhqQQA2AgALIANB8ABqJAAL6AQCBH8GfiAAIAAoAjggAmo2AjgCQCAAAn8CQAJAAkAgACgCPCIFRQRADAELAn4gAkEIIAVrIgQgAiAESRsiBkEDTQRAQgAMAQtBBCEDIAE1AAALIQcgACAAKQMwIANBAXIgBkkEQCABIANqMwAAIANBA3SthiAHhCEHIANBAnIhAwsgAyAGSQR+IAEgA2oxAAAgA0EDdK2GIAeEBSAHCyAFQQN0QThxrYaEIgc3AzAgBCACSw0BIABBIGoiAyAAQShqIgUpAwAgB4UiCCAAQRhqIgYpAwB8IgogAykDACIJQg2JIAkgACkDEHwiCYUiC3wiDCALQhGJhTcDACAGIAxCIIk3AwAgBSAKIAhCEImFIghCFYkgCCAJQiCJfCIIhTcDACAAIAcgCIU3AxALIAIgBGsiAkEHcSEDIAQgAkF4cSICSQRAIABBGGopAwAhCCAAQSBqKQMAIQcgAEEoaikDACEKIAApAxAhCQNAIAggASAEaikAACILIAqFIgh8IgogByAJfCIJIAdCDYmFIgd8IgwgB0IRiYUhByAIQhCJIAqFIghCFYkgCCAJQiCJfCIJhSEKIAxCIIkhCCAJIAuFIQkgBEEIaiIEIAJJDQALIAAgBzcDICAAIAk3AxAgACAKNwMoIAAgCDcDGAsgA0EDSw0BQgAhB0EADAILIAIgBWohAwwCCyABIARqNQAAIQdBBAsiAkEBciADSQRAIAEgAiAEamozAAAgAkEDdK2GIAeEIQcgAkECciECCyACIANJBH4gASACIARqajEAACACQQN0rYYgB4QFIAcLNwMwCyAAIAM2AjwL/wQBCn8jAEEwayIDJAAgA0EkaiABNgIAIANBAzoAKCADQoCAgICABDcDCCADIAA2AiAgA0EANgIYIANBADYCEAJ/AkACQCACKAIIIgpFBEAgAkEUaigCACIARQ0BIAIoAhAhASAAQQN0IQUgAEF/akH/////AXFBAWohByACKAIAIQADQCAAQQRqKAIAIgQEQCADKAIgIAAoAgAgBCADKAIkKAIMEQMADQQLIAEoAgAgA0EIaiABQQRqKAIAEQAADQMgAUEIaiEBIABBCGohACAFQXhqIgUNAAsMAQsgAkEMaigCACIARQ0AIABBBXQhCyAAQX9qQf///z9xQQFqIQcgAigCACEAA0AgAEEEaigCACIBBEAgAygCICAAKAIAIAEgAygCJCgCDBEDAA0DCyADIAUgCmoiBEEcai0AADoAKCADIARBBGopAgBCIIk3AwggBEEYaigCACEGIAIoAhAhCEEAIQlBACEBAkACQAJAIARBFGooAgBBAWsOAgACAQsgBkEDdCAIaiIMQQRqKAIAQfgARw0BIAwoAgAoAgAhBgtBASEBCyADIAY2AhQgAyABNgIQIARBEGooAgAhAQJAAkACQCAEQQxqKAIAQQFrDgIAAgELIAFBA3QgCGoiBkEEaigCAEH4AEcNASAGKAIAKAIAIQELQQEhCQsgAyABNgIcIAMgCTYCGCAIIAQoAgBBA3RqIgEoAgAgA0EIaiABKAIEEQAADQIgAEEIaiEAIAsgBUEgaiIFRw0ACwsgByACKAIESQRAIAMoAiAgAigCACAHQQN0aiIAKAIAIAAoAgQgAygCJCgCDBEDAA0BC0EADAELQQELIANBMGokAAvRBAEKfyMAQUBqIgMkACACKAIEIQkgAigCCCEIIANBOGohCiADQTBqIQsgA0EoaiEMA0AgAigCCCIFIAIoAgQiBEYEQCACQSAQrwIgAigCBCEEIAIoAgghBQsgAyAGNgIUIANBADYCECADIAQgBWs2AgwgAyACKAIAIAVqNgIIIANBGGogASADQQhqQQAQlgECQAJAAkACQAJAAkACQAJAIAMtABgiBUEERgRAIAMoAhAiBQ0BIABBBDoAACAAIAIoAgggCGs2AgQMCAsCfwJAAkACQAJAIAVBAWsOAwECAwALIAMoAhwaQSgMAwsgAy0AGQwCCyADKAIcLQAIDAELIAMoAhwtAAgLQf8BcUEjRg0BIAAgAykDGDcCAAwHCyADKAIUIgYgBUkNASAGIAMoAgwiBEsNAiAFIARLDQMgAiACKAIIIAVqIgQ2AgggBCACKAIEIgdHIAcgCUdyDQUgCkIANwMAIAtCADcDACAMQgA3AwAgA0IANwMgIAMgARDjASADKAIAIQcgAygCBCIEQSAgBEEgSRsiBEEBRgRAIActAAAhByABIAEpAwAgBK18NwMAIAMgBzoAIAwFCyADQSBqIAcgBBCFAxogASABKQMAIAStfDcDACAEDQQgAEEEOgAAIAAgAigCCCAIazYCBAwGCyADIAMpAxg3AyAgA0EgahDyAQwGCyAFIAZB6ILAABDrAgALIAYgBEHogsAAEOoCAAsgBSAEQYiCwAAQ6gIACyACIANBIGogBBCCAgsgBiAFayEGDAELCyADQUBrJAAL1QQBBH8gACABEIkDIQICQAJAAkAgABD7Ag0AIAAoAgAhAwJAIAAQ5AJFBEAgASADaiEBIAAgAxCKAyIAQaDywAAoAgBHDQEgAigCBEEDcUEDRw0CQZjywAAgATYCACAAIAEgAhCrAg8LIAEgA2pBEGohAAwCCyADQYACTwRAIAAQWQwBCyAAQQxqKAIAIgQgAEEIaigCACIFRwRAIAUgBDYCDCAEIAU2AggMAQtBiO/AAEGI78AAKAIAQX4gA0EDdndxNgIACyACEOACBEAgACABIAIQqwIMAgsCQEGk8sAAKAIAIAJHBEAgAkGg8sAAKAIARw0BQaDywAAgADYCAEGY8sAAQZjywAAoAgAgAWoiATYCACAAIAEQxQIPC0Gk8sAAIAA2AgBBnPLAAEGc8sAAKAIAIAFqIgE2AgAgACABQQFyNgIEIABBoPLAACgCAEcNAUGY8sAAQQA2AgBBoPLAAEEANgIADwsgAhD6AiIDIAFqIQECQCADQYACTwRAIAIQWQwBCyACQQxqKAIAIgQgAkEIaigCACICRwRAIAIgBDYCDCAEIAI2AggMAQtBiO/AAEGI78AAKAIAQX4gA0EDdndxNgIACyAAIAEQxQIgAEGg8sAAKAIARw0BQZjywAAgATYCAAsPCyABQYACTwRAIAAgARBYDwsgAUF4cUGQ78AAaiECAn9BiO/AACgCACIDQQEgAUEDdnQiAXEEQCACKAIIDAELQYjvwAAgASADcjYCACACCyEBIAIgADYCCCABIAA2AgwgACACNgIMIAAgATYCCAuWBAEIfyMAQSBrIgkkAAJAAkACQAJAIANFDQAgAkEEaiEEIANBA3QhBiADQX9qQf////8BcUEBaiEHAkADQCAEKAIADQEgBEEIaiEEIAVBAWohBSAGQXhqIgYNAAsgByEFCyAFIANLBEAgBSADQeSMwAAQ6QIACyADIAVrIghFDQAgAiAFQQN0aiEDA0AgAyICIAhBA3QiCmohB0EAIQUgCiEGIANBBGoiAyEEA0AgBCgCACAFaiEFIARBCGohBCAGQXhqIgYNAAsgASAFEK8CIAIhBANAIAEgBCgCACAEQQRqKAIAEIICIARBCGoiBCAHRw0ACyAFRQRAIABCgoCAgICfgQg3AgAMAwsgCEF/akH/////AXFBAWohC0EAIQRBACEGAkADQCADKAIAIAZqIgcgBUsNASADQQhqIQMgBEEBaiEEIAchBiAKQXhqIgoNAAsgCyEECyAIIARJDQMgAiAEQQN0IgdqIQMCQCAEIAhGBEAgBSAGRg0BIAlBHGpBADYCACAJQZiMwAA2AhggCUIBNwIMIAlBrI3AADYCCCAJQQhqQbSNwAAQjwIACyACIAdqIgooAgQiByAFIAZrIgJJDQUgCkEEaiAHIAJrNgIAIAMgAygCACACajYCAAsgCCAEayIIDQALCyAAQQQ6AAALIAlBIGokAA8LIAQgCEHkjMAAEOkCAAsgAiAHQfSMwAAQ6QIAC5gEAQd/IAEoAgQiBgRAIAEoAgAhBANAAkAgA0EBaiECAn8gAiADIARqLQAAIgdBGHRBGHUiCEEATg0AGgJAAkACQAJAAkACQAJAIAdBlNbAAGotAABBfmoOAwABAggLIAIgBGpBzdDAACACIAZJGy0AAEHAAXFBgAFHDQcgA0ECagwGCyACIARqQc3QwAAgAiAGSRssAAAhBSAHQaB+aiIHRQ0BIAdBDUYNAgwDCyACIARqQc3QwAAgAiAGSRssAAAhBQJAAkACQAJAIAdBkH5qDgUBAAAAAgALIAVBf0ogCEEPakH/AXFBAktyIAVBQE9yDQgMAgsgBUHwAGpB/wFxQTBPDQcMAQsgBUGPf0oNBgsgBCADQQJqIgJqQc3QwAAgAiAGSRstAABBwAFxQYABRw0FIAQgA0EDaiICakHN0MAAIAIgBkkbLQAAQcABcUGAAUcNBSADQQRqDAQLIAVBYHFBoH9HDQQMAgsgBUGgf04NAwwBCyAIQR9qQf8BcUEMTwRAIAhBfnFBbkcgBUF/SnIgBUFAT3INAwwBCyAFQb9/Sg0CCyAEIANBAmoiAmpBzdDAACACIAZJGy0AAEHAAXFBgAFHDQEgA0EDagsiAyICIAZJDQELCyAAIAM2AgQgACAENgIAIAEgBiACazYCBCABIAIgBGo2AgAgACACIANrNgIMIAAgAyAEajYCCA8LIABBADYCAAuEBAIKfwR+IwBB8ABrIgMkACADQX82AgwgA0FAayABIANBDGpBBCACKAIgEQUAAkACQAJAIAMtAEBBBEcEQCADKQNAIg1C/wGDQgZSDQELIAMgAygCDCIHEJEBIANBADYCGCADIAMpAwA3AxAgB0UEQEEEIQUMAgsgA0HMAGohBkEEIQUDQAJAIANBQGsgASACED4gAykCRCENIAMoAkAiCEEIRg0AIANBOGogBkEYaigCACIENgIAIANBMGogBkEQaikCACIONwMAIANBKGogBkEIaikCACIPNwMAIAMgBikCACIQNwMgIAMoAmghCSADQdgAaiIKIAQ2AgAgA0HQAGoiCyAONwMAIANByABqIgwgDzcDACADIBA3A0AgAygCGCIEIAMoAhRGBEAgA0EQaiAEEOkBIAMoAhghBAsgBSAJaiEFIAMoAhAgBEEobGoiBCANNwIEIAQgCDYCACAEIAMpA0A3AgwgBEEUaiAMKQMANwIAIARBHGogCykDADcCACAEQSRqIAooAgA2AgAgAyADKAIYQQFqNgIYIAdBf2oiBw0BDAMLCyAAQQA2AgAgACANNwIEIANBEGoQqAEgA0EQahCuAgwCCyAAQQA2AgAgACANNwIEDAELIAAgAykDEDcCACAAIAU2AgwgAEEIaiADQRhqKAIANgIACyADQfAAaiQAC4MEAgp/AX4jAEFAaiIDJAAgA0F/NgIUIANBKGogASADQRRqQQQgAigCIBEFAAJAAkACQCADLQAoQQRHBEAgAykDKCINQv8Bg0IGUg0BCyADQQhqIAMoAhQiBRCQASADQQA2AiAgAyADKQMINwMYIAVFBEBBBCEGDAILIANBKGpBAXIhB0EEIQYDQAJAIANBKGogASACEC4gAy0AKCIIQQpGDQAgA0EmaiAHQQJqLQAAIgQ6AAAgAyAHLwAAIgk7ASQgAykCLCENIAMoAjQhCiADKAI4IQsgA0EqaiIMIAQ6AAAgAyAJOwEoIAMoAiAiBCADKAIcRgRAIANBGGogBBDnASADKAIgIQQLIAYgC2ohBiADKAIYIARBBHRqIgQgAy8BKDsAASAEIAg6AAAgBCAKNgIMIAQgDTcCBCAEQQNqIAwtAAA6AAAgAyADKAIgQQFqNgIgIAVBf2oiBQ0BDAMLCyADKQIsIQ0gAEEANgIAIAAgDTcCBCADKAIgIgAEQCADKAIYIQQgAEEEdCEFA0AgBC0AACIAQX5qQQdJIABFckUEQCAEQQRqEIUCCyAEQRBqIQQgBUFwaiIFDQALCyADQRhqEK4CDAILIABBADYCACAAIA03AgQMAQsgACADKQMYNwIAIAAgBjYCDCAAQQhqIANBIGooAgA2AgALIANBQGskAAumBAIFfwF+IwBB0ABrIgMkACADQf8BOgAPIANBKGogASADQQ9qQQEgAigCIBEFAAJAAkACQAJAAkACQAJAIAMtAChBBEcEQCADKQMoIghC/wGDQgZSDQELQQIhBAJAAkACQAJAAkACQAJAAkAgAy0AD0F/ag4IBwYMAAUBAgQDC0EDIQQMCwtBBSEEDAoLIABBBToABAwKCyAAQQU6AAQMCQsgA0EoaiABIAIQPCADKAIoIgZFDQQgAygCNCEFIAMpAiwhCEEHIQQMBwsgA0EoaiABIAIQRSADKAIoIgYEQCADKAI0IQUgAykCLCEIQQQhBAwHCyAAIAMpAiw3AgQMBwsgA0EoaiABIAIQhgEgAykDKCEIIAMoAjAiBw0EDAMLIANBKGogASACEGIgAykDKCEIIAMoAjAiB0UNAiADQSBqIANBxABqKAIANgIAIANBGGogA0E8aikCADcDACADIAMpAjQ3AxAgAygCSCEFQQAhBAwECyAAQQg2AgAgACAINwIEDAULIAAgAykCLDcCBAwDCyAAIAg3AgQMAgsgA0EYaiADQTxqKAIANgIAIAMgAykCNDcDECADKAJAIQVBASEECyAAIAMpAxA3AhQgACAHNgIQIAAgCDcCCCAAIAY2AgQgACAENgIAIAAgBUEBajYCKCAAQSRqIANBIGooAgA2AgAgAEEcaiADQRhqKQMANwIADAELIABBCDYCAAsgA0HQAGokAAvpAwEGfyMAQTBrIgUkAAJAAkACQAJAAkAgASgCBCIDBEAgASgCACEHIANBf2pB/////wFxIgNBAWoiBkEHcSEEAn8gA0EHSQRAQQAhAyAHDAELIAdBPGohAiAGQfj///8DcSEGQQAhAwNAIAIoAgAgAkF4aigCACACQXBqKAIAIAJBaGooAgAgAkFgaigCACACQVhqKAIAIAJBUGooAgAgAkFIaigCACADampqampqamohAyACQUBrIQIgBkF4aiIGDQALIAJBRGoLIQIgBARAIAJBBGohAgNAIAIoAgAgA2ohAyACQQhqIQIgBEF/aiIEDQALCyABQRRq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QQBHC+cBAQJ/IwBBMGsiAiQAAn8CQAJAAkAgAC0AAEF8akH/AXEiA0ECIANBAkkbQQFrDgIBAgALIAJBJGpBADYCACACQeicwAA2AiAgAkIBNwIUIAJB9J3AADYCECABIAJBEGoQuQEMAgsgAkEkakEANgIAIAJB6JzAADYCICACQgE3AhQgAkHQncAANgIQIAEgAkEQahC5AQwBCyACIAA2AgwgAkEkakEBNgIAIAJCAjcCFCACQaidwAA2AhAgAkE4NgIsIAIgAkEoajYCICACIAJBDGo2AiggASACQRBqELkBCyACQTBqJAAL5wEBAn8jAEEwayICJAACfwJAAkACQCAALQAAQXxqQf8BcSIDQQIgA0ECSRtBAWsOAgECAAsgAkEkakEANgIAIAJB6JzAADYCICACQgE3AhQgAkHYnsAANgIQIAEgAkEQahC5AQwCCyACQSRqQQA2AgAgAkHonMAANgIgIAJCATcCFCACQbSewAA2AhAgASACQRBqELkBDAELIAIgADYCDCACQSRqQQE2AgAgAkICNwIUIAJBjJ7AADYCECACQTg2AiwgAiACQShqNgIgIAIgAkEMajYCKCABIAJBEGoQuQELIAJBMGokAAvPAQECfyMAQSBrIgMkAAJAAkAgASACaiICIAFJDQAgAEEEaigCACIBQQF0IgQgAiAEIAJLGyICQQggAkEISxsiAkF/c0EfdiEEAkAgAQRAIANBATYCGCADIAE2AhQgAyAAKAIANgIQDAELIANBADYCGAsgAyACIAQgA0EQahCJASADKAIEIQEgAygCAEUEQCAAIAE2AgAgAEEEaiACNgIADAILIANBCGooAgAiAEGBgICAeEYNASAARQ0AIAEgABD+AgALEI4CAAsgA0EgaiQAC88BAQJ/IwBBIGsiAyQAAkACQCABIAJqIgIgAUkNACAAQQRqKAIAIgFBAXQiBCACIAQgAksbIgJBCCACQQhLGyICQX9zQR92IQQCQCABBEAgA0EBNgIYIAMgATYCFCADIAAoAgA2AhAMAQsgA0EANgIYCyADIAIgBCADQRBqEIMBIAMoAgQhASADKAIARQRAIAAgATYCACAAQQRqIAI2AgAMAgsgA0EIaigCACIAQYGAgIB4Rg0BIABFDQAgASAAEP4CAAsQjgIACyADQSBqJAALzQEBA38jAEEgayIC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CyABRQ0CCyABIAIQ2wIMAgsgACABNgIEIABBCGpBADYCAAwCCyACCyIDBEAgACADNgIEIABBCGogATYCAEEADAILIAAgATYCBCAAQQhqIAI2AgALQQELNgIAC8oBAQJ/IwBB0AFrIgMkACAAKAIAIgAtAMgBIQQgAEEEOgDIAQJAIARBBEcEQCADQQhqIABByAEQhQMaIAMgAEHMAWooAAA2AAMgAyAAKADJATYCAEGwA0EIENsCIgBFDQEgACADQQhqQcgBEIUDIgAgBDoAyAEgAEEAOgCoAyAAIAI2AqQDIAAgATYCoAMgACADKAIANgDJASAAQcwBaiADKAADNgAAIAAQlQEgA0HQAWokAA8LQdSPwABBFRD5AgALQbADQQgQ/gIAC60BAQF/AkAgAgRAAn8CQAJAAkAgAUEATgRAIAMoAghFDQIgAygCBCIEDQEgAQ0DIAIMBAsgAEEIakEANgIADAULIAMoAgAgBCACIAEQzQIMAgsgAQ0AIAIMAQsgASACENsCCyIDBEAgACADNgIEIABBCGogATYCACAAQQA2AgAPCyAAIAE2AgQgAEEIaiACNgIADAELIAAgATYCBCAAQQhqQQA2AgALIABBATYCAAunAQEFfyAAQQhqIABBDGoiASgCACICIAIQ0wEgASgCACIFIAJBAXRGBEAgACgCACIDIAAoAgQiAUsEQCABIAIgA2siBE8EQCAAKAIIIgIgBSAEayIBQQJ0aiACIANBAnRqIARBAnQQhQMaIAAgATYCAA8LIAAoAggiAyACQQJ0aiADIAFBAnQQhQMaIAAgASACajYCBAsPC0GutcAAQStB3LXAABD/AQALrAEBA38jAEEwayICJAAgAUEEaiEDIAEoAgRFBEAgASgCACEBIAJBEGoiBEEANgIAIAJCATcDCCACIAJBCGo2AhQgAkEoaiABQRBqKQIANwMAIAJBIGogAUEIaikCADcDACACIAEpAgA3AxggAkEUakG4wMAAIAJBGGoQNxogA0EIaiAEKAIANgIAIAMgAikDCDcCAAsgAEG8yMAANgIEIAAgAzYCACACQTBqJAALmgEBAX8jAEEwayIDJAAgA0GACBDNASADQQA2AhAgAyADKQMANwMIIANBGGogASACIANBCGoQJAJAIAMtABhBA0YEQCADQShqIANBEGooAgA2AgAgAyAD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ABCkASAAQQRqIQAgAkF8aiICDQALCyABQRBqJAALkQEBAX8gACgCACIAIAAoAgBBf2oiATYCAAJAIAENAAJAIABBDGooAgBBAkYNACAAQRBqKAIAIgFBJEkNACABEAALIABBGGooAgAiAQRAIABBFGooAgAgASgCDBECAAsgAEEgaigCAARAIABBHGoQwwIgAEEoahDDAgsgACAAKAIEQX9qIgE2AgQgAQ0AIAAQKwsLlAEBBH8jAEEgayIBJAAgARCSASABQQA6ABwgAUEANgIQIAFCADcDCCABIAEpAwA3AhQgAUEIahDxASECIAFBIDYCCCABQQhqKAIAEBwhAyACIAIoAgBBAWoiBDYCACAEBEAgAEEIaiACEIYCIAAgAzYCBCAAIAI2AgAgASgCCCIAQSRPBEAgABAACyABQSBqJAAPCwALsAEBA38jAEEQayIBJAAgACgCACICQRRqKAIAIQMCQAJ/AkACQCACKAIEDgIAAQMLIAMNAkEAIQJB0MDAAAwBCyADDQEgAigCACIDKAIEIQIgAygCAAshAyABIAI2AgQgASADNgIAIAFB8MjAACAAKAIEIgEoAgggACgCCCABLQAQEH8ACyABQQA2AgQgASACNgIAIAFB3MjAACAAKAIEIgEoAgggACgCCCABLQAQEH8AC5cBAQJ/IwBBEGsiASQAIAAoAgBFBEAgAEF/NgIAIAACf0EAIAAoAgQiAkUNABogAEEAOgAUIAEgAEEMajYCBCACIAFBBGogAEEIaigCACgCDBEAAEUEQCAAQQRqIgIQ9gEgAkEANgIACyAAKAIAQQFqCzYCACABQRBqJAAPC0HsuMAAQRAgAUEIakH8uMAAQai9wAAQrgEAC5ABAQF/AkACQAJAAkACQCAALQBgDgUDBAQAAQQLIABB6ABqEJgBDAELIABB9ABqEJgBIAAoAmgiAUEkSQ0AIAEQAAsgACgCWCIBQSRPBEAgARAACyAAKAJUIgFBJE8EQCABEAALIABByABqEK4CIABBPGoQrgIgACgCOCIAQSRJDQEgABAADwsgAEEIahDJAQsLhAEBAX8jAEEQayICJAAgAkHoscAAQQQQATYCCCACIAEEfyABKAIAEAIFQSALNgIMIAIgACACQQhqIAJBDGoQ0QEgAigCDCIAQSRPBEAgABAACyACKAIIIgBBJE8EQCAAEAALAkAgAi0AAEUNACACKAIEIgBBJEkNACAAEAALIAJBEGokAAuOAQECfyMAQUBqIgEkACABQQA2AgggAUIBNwMAIAFBEGogAUHAksAAEJ0CIAAgAUEQahB2RQRAIAFBGGogAUEIaigCADYCACABIAEpAwA3AxAgAUEQahC+AiAALQAAQQZxQQRHBEAgABDyAQsgAUFAayQADwtB2JLAAEE3IAFBOGpBkJPAAEHsk8AAEK4BAAuOAQECfyMAQUBqIgEkACABQQA2AgggAUIBNwMAIAFBEGogAUHAksAAEJ0CIAAgAUEQahB3RQRAIAFBGGogAUEIaigCADYCACABIAEpAwA3AxAgAUEQahC+AiAALQAAQQZxQQRHBEAgABDyAQsgAUFAayQADwtB2JLAAEE3IAFBOGpBkJPAAEHsk8AAEK4BAAuAAQEEfwJAIAMEQCACIANBA3QiBmohByACQQRqIQUDQCAFKAIAIARqIQQgBUEIaiEFIAZBeGoiBg0ACyABIAQQrwIgA0UNAQNAIAEgAigCACACQQRqKAIAEIICIAJBCGoiAiAHRw0ACwwBCyABQQAQrwILIABBBDoAACAAIAQ2AgQLmAEBAn8jAEEQayIDJAAgACgCACICKAIIRQRAIAJBfzYCCCACQQxqIAEQygEgAiACKAIIQQFqNgIIIAAoAgBBHGoiAS0AACECIAFBAToAAAJAIAJBAXENACAAQQRqKAIAIABBCGooAgAQHSIAQSRJDQAgABAACyADQRBqJAAPC0GItMAAQRAgA0EIakGYtMAAQfS2wAAQrgEAC4wBAQF/IwBBEGsiBSQAAkACfyAEIANLBEAgAiAESQ0CIAIgBGshAiABIARBAnRqDAELIAVBCGogASACIAQgAxD3AUEAIQMgBSgCDCECIAUoAggLIQQgACABNgIIIAAgAjYCBCAAIAQ2AgAgAEEMaiADNgIAIAVBEGokAA8LQYy5wABBI0HsusAAEP8BAAuNAQECfyMAQRBrIgQkACAEQQhqIAEQ4wECQCAEKAIMIANPBEAgBCgCCCEFAkAgA0EBRwRAIAIgBSADEIUDGgwBCyACIAUtAAA6AAALIABBBDoAACABIAEpAwAgA618NwMADAELIABBADsAASAAQdSKwAA2AAQgAEECOgAAIABBA2pBADoAAAsgBEEQaiQAC4UBAQF/IAAoAgAiACAAKAIAQX9qIgE2AgACQCABDQAgAEEMaigCACIBBEAgASAAQRBqIgEoAgAoAgARAgAgASgCACIBKAIEBEAgASgCCBogACgCDBArCyAAQRRqKAIAIABBGGooAgAoAgwRAgALIAAgACgCBEF/aiIBNgIEIAENACAAECsLC4cBAQN/IwBBEGsiBSQAIAVBCGogARDjASAFKAIIIQYCQAJAIAMgBSgCDCIEIAMgBEkbIgRBAUcEQCACIAYgBBCFAxoMAQsgA0UNASACIAYtAAA6AAALIAAgBDYCBCAAQQQ6AAAgASABKQMAIAStfDcDACAFQRBqJAAPC0EAQQBBrIvAABC4AQALhAEBAX8jAEEgayIGJAAgAQRAIAYgASADIAQgBSACKAIQEQcAIAZBGGogBkEIaigCACIBNgIAIAYgBikDADcDECAGKAIUIAFLBEAgBkEQaiABEIgCIAYoAhghAQsgBigCECECIAAgATYCBCAAIAI2AgAgBkEgaiQADwtBx73AAEEwEPkCAAt1AQR/IwBBEGsiAyQAIAAoAgwiAiAAKAIIIgFHBEAgAiABa0EEdkEEdCECA0AgAS0AACIEQX5qQQdJIARFckUEQCABQQRqEK4CCyABQRBqIQEgAkFwaiICDQALCyADIAApAgA3AwggA0EIahCuAiADQRBqJAALkAEBAn8gACgCCCICBEAgACgCACEAIAJBKGwhAgNAAkACQAJAAkACQCAAKAIADgcBAgQEAwQEAAsgAEEEaiIBEKgBIAEQrgIMAwsgAEEQahCFAiAAQRxqIgEQ2QEgARCuAgwCCyAAQRBqIgEQ2QEgARCuAgwBCyAAQQRqEIUCCyAAQShqIQAgAkFYaiICDQALCwt/AQJ/IAEoAgghAiABKAIEIQMCQAJAAkAgASgCACIBRQRAAkAgAkUEQEEBIQEMAQsgAkF/TA0CIAJBARDbAiIBRQ0DCyABIAMgAhCFAyEBIAAgAjYCBAwDCyAAIAM2AgQMAgsQjgIACyACQQEQ/gIACyAAIAE2AgAgACACNgIIC4MBAgF/AX4jAEEQayIDJAAgA0H/AToAByADQQhqIAEgA0EHakEBIAIoAiARBQACQAJAIAMtAAhBBEcEQCADKQMIIgRC/wGDQgZSDQELIABBADYCACAAQQhqQQE2AgAgACADLQAHQQBHOgAEDAELIABBATYCACAAIAQ3AgQLIANBEGokAAt+AQF/IwBBEGsiASQAIAFB7LHAAEEGEAE2AgggAUHImsAAQQQQATYCDCABIAAgAUEIaiABQQxqENEBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALhwECAX8BfiMAQRBrIgEkAEHw7sAAKQMAUARAQYDvwAACfgJAIABFDQAgACkDACAAQgA3AwBCAVINACAAKQMIIQIgACkDEAwBCyABQgI3AwggAUIBNwMAIAEpAwAhAiABKQMICzcDAEH47sAAIAI3AwBB8O7AAEIBNwMACyABQRBqJABB+O7AAAt+AQF/IwBBEGsiASQAIAFB8rHAAEEEEAE2AgggAUGIssAAQQQQATYCDCABIAAgAUEIaiABQQxqENEBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALgAEBAX8jAEFAaiIFJAAgBSABNgIMIAUgADYCCCAFIAM2AhQgBSACNgIQIAVBLGpBAjYCACAFQTxqQfoANgIAIAVCAjcCHCAFQazRwAA2AhggBUH5ADYCNCAFIAVBMGo2AiggBSAFQRBqNgI4IAUgBUEIajYCMCAFQRhqIAQQjwIAC2wBAX8jAEEwayIDJAAgAyABNgIoIAMgATYCJCADIAA2AiAgA0EIaiADQSBqEJUCIANBEGogAygCCCADKAIMEMsCIANBKGogA0EYaigCADYCACADIAMpAxA3AyAgA0EgaiACELUBIANBMGokAAt8AQF/IAAtAAQhASAALQAFBEAgAUH/AXEhASAAAn9BASABDQAaIAAoAgAiAS0AAEEEcUUEQCABKAIYQePRwABBAiABQRxqKAIAKAIMEQMADAELIAEoAhhB4tHAAEEBIAFBHGooAgAoAgwRAwALIgE6AAQLIAFB/wFxQQBHC2kBAX8jAEEwayICJAAgAiABNgIoIAIgATYCJCACIAA2AiAgAkEIaiACQSBqEJUCIAJBEGogAigCCCACKAIMEMsCIAJBKGogAkEYaigCADYCACACIAIpAxA3AyAgAkEgahBbIAJBMGokAAtpAQR/IwBBEGsiAyQAIAAoAgwiASAAKAIIIgJHBEAgASACa0ECdkECdCEBA0AgAigCACIEQSRPBEAgBBAACyACQQRqIQIgAUF8aiIBDQALCyADIAApAgA3AwggA0EIahCEAiADQRBqJAALdwEBfwJAAkAgAEUNACAAKAIAIQEgAEEANgIAIAAoAgQhAAJAIAEOAgECAAsgAEEkSQ0AIAAQAAsQTyEAC0G07sAAKAIAIQFBtO7AACAANgIAQbDuwAAoAgBBsO7AAEEBNgIARSABQSRJckUEQCABEAALQbTuwAALfAEDfyAAIAAQiwMiAEEIEMwCIABrIgIQiQMhAEGc8sAAIAEgAmsiATYCAEGk8sAAIAA2AgAgACABQQFyNgIEQQhBCBDMAiECQRRBCBDMAiEDQRBBCBDMAiEEIAAgARCJAyAEIAMgAkEIa2pqNgIEQcDywABBgICAATYCAAtpAQF/IwBBIGsiAiQAQYzuwAAoAgBFBEBB5ITAAEErQaSJwAAQ/wEACyACQRhqIABBCGooAgA2AgAgAiAAKQIANwMQIAJBCGogAkEQaiABEE0gAigCCCEAIAIoAgwgAkEgaiQAQSEgABsLbAEEfyMAQSBrIgIkAEEBIQMCQCAAIAEQUw0AIAFBHGooAgAhBCABKAIYIAJBADYCHCACQfzPwAA2AhggAkIBNwIMIAJBrNDAADYCCCAEIAJBCGoQNw0AIABBBGogARBTIQMLIAJBIGokACADC2sBAn8jAEEgayICJAAgAkEIaiABKAIAEAMCQCACKAIIIgMEQCACKAIMIQEgAiADNgIQIAIgATYCGCACIAE2AhQgAiACQRBqEJUCIAAgAigCACACKAIEEMsCDAELIABBADYCAAsgAkEgaiQAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHlADYCACADQgI3AgwgA0GA0cAANgIIIANB5QA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACEI8CAAtWAQJ/IwBBIGsiAiQAIABBHGooAgAhAyAAKAIYIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAMgAkEIahA3IAJBIGokAAtvAQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EcakECNgIAIANBLGpB5QA2AgAgA0ICNwIMIANBsNXAADYCCCADQeUANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANBCGogAhCPAgALbwEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBHGpBAjYCACADQSxqQeUANgIAIANCAjcCDCADQdDVwAA2AgggA0HlADYCJCADIANBIGo2AhggAyADQQRqNgIoIAMgAzYCICADQQhqIAIQjwIAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHlADYCACADQgI3AgwgA0GE1sAANgIIIANB5QA2AiQgAyADQSBqNgIYIAMgA0EEajYCKCADIAM2AiAgA0EIaiACEI8CAAtuAQF/AkACQAJAAkAgAC0AqAMOBAECAgACCyAAQdABahBeIAAoAqADIgFBJE8EQCABEAALIAAoAqQDIgBBI00NAQwCCyAAEF4gACgCoAMiAUEkTwRAIAEQAAsgACgCpAMiAEEjSw0BCw8LIAAQAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQcyEwAAgAkEIahA3IAJBIGokAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQbSEwAAgAkEIahA3IAJBIGokAAthAQN/IAAgARCvAiAAKAIAIgQgACgCCCICaiEDAkACQCABQQJPBEAgA0EAIAFBf2oiARCEAxogBCABIAJqIgJqIQMMAQsgAUUNAQsgA0EAOgAAIAJBAWohAgsgACACNgIIC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBuMDAACACQQhqEDcgAkEgaiQAC2kAIwBBMGsiASQAQZjuwAAtAAAEQCABQRxqQQE2AgAgAUICNwIMIAFByMfAADYCCCABQeUANgIkIAEgADYCLCABIAFBIGo2AhggASABQSxqNgIgIAFBCGpB8MfAABCPAgALIAFBMGokAAtZAQF/IwBBIGsiAiQAIAIgACgC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IAEgAhCIAiABKAIIBSACCzYCBCAAIAEoAgA2AgALLgEBfyABKAIEIgIEQCAAQQE2AgggACACNgIEIAAgASgCADYCAA8LIABBADYCCAsjAQF/An9BASABEAlFDQAaQQALIQIgACABNgIEIAAgAjYCAAsqAQF/IAAoAgAEQCAAEPUBIAAoAgQiAUEkTwRAIAEQAAsgAEEIahDDAgsLLgEBfyAAKAIAIAAoAgQoAgARAgAgACgCBCIBKAIEBEAgASgCCBogACgCABArCwswAQF/IAFBeGoiAiACKAIAQQFqIgI2AgAgAkUEQAALIABBmL3AADYCBCAAIAE2AgALLQEBfyMAQRBrIgEkACABQQhqIABBCGooAgA2AgAgASAAKQIANwMAIAEQmgEACzQAIABBAzoAICAAQoCAgICABDcCACAAIAE2AhggAEEANgIQIABBADYCCCAAQRxqIAI2AgALNQEBfyABKAIYQfvAwABBCyABQRxqKAIAKAIMEQMAIQIgAEEAOgAFIAAgAjoABCAAIAE2AgALIwAgACgCAEFwaiIAEK4CIABBDGooAgAiAEEkTwRAIAAQAAsLMQEBf0EEQQQQ2wIiAkUEQEEEQQQQ/gIACyACIAE2AgAgAEHEucAANgIEIAAgAjYCAAsxAQF/QQRBBBDbAiICRQRAQQRBBBD+AgALIAIgATYCACAAQbC5wAA2AgQgACACNgIACycAIAAgACgCBEEBcSABckECcjYCBCAAIAFqIgAgACgCBEEBcjYCBAsmAAJAIABFDQAgACABKAIAEQIAIAEoAgRFDQAgASgCCBogABArCwsmAQF/IwBBEGsiASQAIAEgAEF4ajYCDCABQQxqEKQBIAFBEGokAAs6AQJ/QdDuwAAtAAAhAUHQ7sAAQQA6AABB1O7AACgCACECQdTuwABBADYCACAAIAI2AgQgACABNgIACyABAX8CQCAAKAIEIgFFDQAgAEEIaigCAEUNACABECsLCyYBAX8jAEEQayIDJAAgAyABNgIMIAMgADYCCCADQQhqIAIQgAIACxMAIAAgASkAADcAASAAQQA6AAALJgEBfyAAQQdqIgEgAEkEQEGosMAAQTNBtLHAABDtAgALIAFBA3YLIwACQCABQfz///8HTQRAIAAgAUEEIAIQzQIiAA0BCwALIAALIwAgAiACKAIEQX5xNgIEIAAgAUEBcjYCBCAAIAFqIAE2AgALHgAgACgCACIArUIAIACsfSAAQX9KIgAbIAAgARBSCyUAIABFBEBBx73AAEEwEPkCAAsgACACIAMgBCAFIAEoAhARCwALEQAgACgCBARAIAAoAgAQKwsLIAEBfyAAKAIEIAAoAggiAmsgAUkEQCAAIAIgARDqAQsLIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARBQALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARCQALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhAREwALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhAREgALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARFAALFwAgASADRgR/IAAgAiABEOYBRQVBAAsLHgAgACABQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIECyEAIABFBEBBx73AAEEwEPkCAAsgACACIAMgASgCEBEEAAsUACAAQQRqKAIABEAgACgCABArCwsdACABKAIARQRAAAsgAEHYscAANgIEIAAgATYCAAsfACAARQRAQcSzwABBMBD5AgALIAAgAiABKAIQEQEACx8AIABFBEBBhLfAAEEwEPkCAAsgACACIAEoAhARAQALHwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgASgCEBEAAAsXACAAKAIEBEAgABDDAiAAQQxqEMMCCwsVAQF/IAAoAgAgACgCCBABIAAQrgILHgEBf0G07sAAIQFBsO7AACgCAAR/IAEFIAAQswELCxkBAX8gACgCECIBBH8gAQUgAEEUaigCAAsLFQAgAC0ABEEERwRAIABBBGoQ8gELCxkAIAEgAiADEIICIABBBDoAACAAIAM2AgQLFAAgACgCABAPBEAgAEEEahCaAgsLEgBBAEEZIABBAXZrIABBH0YbCxYAIAAgAUEBcjYCBCAAIAFqIAE2AgALGQAgACABQQhqKAIANgIEIAAgASgCADYCAAscACABKAIYQbTQwABBCyABQRxqKAIAKAIMEQMACxwAIAEoAhhBv9DAAEEOIAFBHGooAgAoAgwRAwALHAAgASgCGEHI5sAAQQUgAUEcaigCACgCDBEDAAsXAEGc7sAAKAIARQRAIAAQaQtBnO7AAAsXACAAIAI2AgggACACNgIEIAAgATYCAAsQACAAIAFqQX9qQQAgAWtxCwwAIAAgASACIAMQLwsLACABBEAgABArCwsUACAAKAIAIABBCGooAgAgARD/AgsPACAAQQF0IgBBACAAa3ILEwAgACgCACAAQQhqKAIAIAEQLQsTACAAKAIAKAIAIAEgAhCCAkEACxIAIAEgAiADEIICIABBBDoAAAsKACAAQQhqEK4CCw8AIAAoAgAEQCAAEJgBCwsUACAAKAIAIAEgACgCBCgCDBEAAAsPACAAIAEgAiADIAQQKQALDgAgACgCACABEGoaQQALEAAgACgCACABIAIQggJBAAsRACAAKAIAIAAoAgggARD/AgsIACAAIAEQRgsRACAAKAIAIAAoAgQgARD/AgsQACAAIAI2AgQgACABNgIACxYAQdTuwAAgADYCAEHQ7sAAQQE6AAALEwAgAEHMyMAANgIEIAAgATYCAAsNACAALQAEQQJxQQF2CxAAIAEgACgCACAAKAIEECwLDQAgACABIAIQggJBAAsKAEEAIABrIABxCwsAIAAtAARBA3FFCwwAIAAgAUEDcjYCBAsNACAAKAIAIAAoAgRqCw0AIAAoAgAgARBQQQALDgAgACgCABoDQAwACwALDAAgACABIAIQugEACwwAIAAgASACELsBAAsMACAAIAEgAhC8AQALDQAgADUCAEEBIAEQUgsMACAAIAEgAhCnAgALDQAgACgCACABIAIQQgsNACAAKQMAQQEgARBSCw0AIAAzAQBBASABEFILDgAgACgCAC0AACABEFYLCwAgACMAaiQAIwALBwAgABCuAgsKACAAIAEgAhA4CwsAIAAgAiABEJMBCw0AIAFBvJLAAEECECwLCwAgACgCACABEEsLCwAgACABQcgAECMLCQAgACABECIACwoAIAAoAgRBeHELCgAgACgCBEEBcQsKACAAKAIMQQFxCwoAIAAoAgxBAXYLGgAgACABQdjuwAAoAgAiAEHmACAAGxEBAAALCgAgAiAAIAEQLAsMACAAIAEpAgA3AwALDAAgACABKQIINwMACw0AIAFByNTAAEECECwLCwAgACgCACABEFMLCwAgACABIAIQhQELCgAgACABIAIQUQsHACAAEKwBCwkAIABBBDoAAAsJACAAQQA2AgALBwAgACAB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aW8gc2xpY2VzIGJleW9uZCB0aGVpciBsZW5ndGgAhAYQACcAAAAYBhAASQAAACYFAAANAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9zdGQvc3JjL2lvL3JlYWRidWYucnMAAADEBhAATQAAACEBAAArAAAAIgAAAAwAAAAEAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAAC9ob21lL25nbml1cy9Eb2N1bWVudHMvZ2l0LXJlcG9zL3VzZHBsLXJzL3VzZHBsLWNvcmUvc3JjL3NlcmRlcy90cmFpdHMucnMAAABMBxAASQAAAHYAAAAcAAAAKgAAABgAAAAIAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAAMQAAADIAAABgdW53cmFwX3Rocm93YCBmYWlsZWQvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnPpBxAAYwAAANoAAAAgAAAAAAAAAGBhc3luYyBmbmAgcmVzdW1lZCBhZnRlciBjb21wbGV0aW9uY2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAADMAAAAAAAAAAQAAADQAAAAvcnVzdGMvZWRmMDE4MjIxM2E5ZTMwOTgyZWIzNGYzOTI1ZGRjNGNmNWVkMzQ3MS9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzANwIEABPAAAApgEAAAkAAAAoKQAAIgAAAAwAAAAEAAAANQAAADYAAAARAAAAYSBEaXNwbGF5IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yIHVuZXhwZWN0ZWRseQAzAAAAAAAAAAEAAAASAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9hbGxvYy9zcmMvc3RyaW5nLnJzAKAJEABLAAAA6AkAAAkAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlADMAAAAAAAAAAQAAADcAAABpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlOiAAADgKEAAqAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5yc2wKEABYAAAA0gEAAB8AAABsChAAWAAAANgBAAAfAAAAbAoQAFgAAADhAQAAHwAAAGwKEABYAAAA6gEAAB8AAABsChAAWAAAAPMBAAAfAAAAbAoQAFgAAAD8AQAAHwAAAGwKEABYAAAABQIAAB8AAABsChAAWAAAAA4CAAAfAAAAbAoQAFgAAAADAQAAJAAAAGwKEABYAAAABAEAACkAAABsChAAWAAAACoBAAAWAAAAbAoQAFgAAAAtAQAAGgAAAGwKEABYAAAAQQEAAA4AAABsChAAWAAAAEQBAAASAAAAbAoQAFgAAABYAQAAEwAAAEltcG9zc2libGU6IG11c3Qgb25seSBoYXZlIDAgdG8gOCBpbnB1dCBieXRlcyBpbiBsYXN0IGNodW5rLCB3aXRoIG5vIGludmFsaWQgbGVuZ3Roc7QLEABUAAAAbAoQAFgAAACdAQAADgAAAGwKEABYAAAAsQEAAAkAAABPdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIG91dHB1dCBidWZmZXIgbGVuZ3RoAABsChAAWAAAAJYAAAAKAAAAbAoQAFgAAACbAAAAIQAAAFdyaXRpbmcgdG8gYSBTdHJpbmcgc2hvdWxkbid0IGZhaWwvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzAACiDBAAWAAAAFMAAAAOAAAAAAAAAP//////////dXNkcGwtZnJvbnQvc3JjL2Nvbm5lY3Rpb24ucnMAAAAYDRAAHQAAABkAAAAmAAAAUE9TVGh0dHA6Ly91c2RwbC46L3VzZHBsL2NhbGwAAABMDRAADAAAAFgNEAABAAAAWQ0QAAEAAABaDRAACwAAAGxvY2FsaG9zdAAAAIgNEAAJAAAAGA0QAB0AAAAsAAAAJAAAABgNEAAdAAAAMwAAACcAAABFeHBlY3RlZCBjYWxsIHJlc3BvbnNlIG1lc3NhZ2UgZnJvbSAsIGdvdCBzb21ldGhpbmcgZWxzZbwNEAAkAAAA4A0QABQAAAB1c2RwbC1mcm9udC9zcmMvY29udmVydC5ycwAABA4QABoAAAAgAAAAJwAAAHVzZHBsLWZyb250L3NyYy9saWIucnMAADAOEAAWAAAAbwAAAE4AAAAwDhAAFgAAAG4AAAABAAAAY3JhbmtzaGFmdAAAaA4QAAoAAABkZWNreQAAAHwOEAAFAAAAYW55AIwOEAADAAAATG9hZEVycm9yOiBJbygpAJgOEAAOAAAApg4QAAEAAABMb2FkRXJyb3I6IEludmFsaWREYXRhAAC4DhAAFgAAAExvYWRFcnJvcjogVG9vU21hbGxCdWZmZXIAAADYDhAAGQAAAER1bXBFcnJvcjogSW8oAAD8DhAADgAAAKYOEAABAAAARHVtcEVycm9yOiBVbnN1cHBvcnRlZAAAHA8QABYAAABEdW1wRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAPA8QABkAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzYA8QAFgAAAA7AQAACQAAACEiIyQlJicoKSorLC0wMTIzNDU2Nzg5QEFCQ0RFRkdISUpLTE1OUFFSU1RVVlhZWltgYWJjZGVoaWprbG1wcXJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSssLi9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL////////////////////////////////////////////wABAgMEBQYHCAkKCwz//w0ODxAREhMUFRb///////8XGBkaGxwdHh8gISIjJCX/JicoKSorLP8tLi8w/////zEyMzQ1Nv//Nzg5Ojs8//89Pj//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pj////80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABNjc4OTo7PD0+P/////////8CAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG////////xwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wgREADIEBAAiBAQAEgQEAAIEBAAyA8QAEgWEABIFRAASBQQAEgTEABIEhAASBEQAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAOQAAAAgAAAAEAAAAOgAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAAC0FxAAYQAAAGgAAAAwAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBudW1iZXIgb2YgY2h1bmtzIGluIGlucHV0L2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5ycwBbGBAAWAAAALwAAAAKAAAAOwAAAAgAAAAEAAAAPAAAAD0AAAA7AAAACAAAAAQAAAA+AAAAYm9keW1ldGhvZG1vZGVzYW1lLW9yaWdpbm5vLWNvcnNjb3JzbmF2aWdhdGVhdHRlbXB0ZWQgdG8gY29udmVydCBpbnZhbGlkIFJlcXVlc3RNb2RlIGludG8gSlNWYWx1ZS9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93ZWItc3lzLTAuMy42MC9zcmMvZmVhdHVyZXMvZ2VuX1JlcXVlc3RNb2RlLnJzSRkQAGsAAAADAAAAAQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeUIAAAAEAAAABAAAAEMAAABEAAAAYWxyZWFkeSBib3Jyb3dlZEUAAAAAAAAAAQAAAEYAAABhbHJlYWR5IG11dGFibHkgYm9ycm93ZWRFAAAAAAAAAAEAAABHAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9hbGxvYy9zcmMvY29sbGVjdGlvbnMvdmVjX2RlcXVlL21vZC5yc2Fzc2VydGlvbiBmYWlsZWQ6IHNlbGYuY2FwKCkgPT0gb2xkX2NhcCAqIDIAAABQGhAAXgAAAOMIAAAJAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvcXVldWUucnMAAADsGhAAZQAAABoAAAAuAAAA7BoQAGUAAAAdAAAAKQAAAOwaEABlAAAAMgAAABoAAABjbG9zdXJlIGludm9rZWQgcmVjdXJzaXZlbHkgb3IgZGVzdHJveWVkIGFscmVhZHljYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAABJAAAAAAAAAAEAAAA0AAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9zdGQvc3JjL3RocmVhZC9sb2NhbC5ycwAMHBAATwAAAKYBAAAJAAAAYWxyZWFkeSBib3Jyb3dlZEkAAAAAAAAAAQAAAEYAAABhc3NlcnRpb24gZmFpbGVkOiBtaWQgPD0gc2VsZi5sZW4oKQBKAAAABAAAAAQAAABLAAAATAAAAEoAAAAEAAAABAAAAE0AAABOAAAARm5PbmNlIGNhbGxlZCBtb3JlIHRoYW4gb25jZS9ydXN0Yy9lZGYwMTgyMjEzYTllMzA5ODJlYjM0ZjM5MjVkZGM0Y2Y1ZWQzNDcxL2xpYnJhcnkvYWxsb2Mvc3JjL2NvbGxlY3Rpb25zL3ZlY19kZXF1ZS9yaW5nX3NsaWNlcy5ycwAA9BwQAGYAAAAgAAAADgAAAPQcEABmAAAAIwAAABEAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnMAfB0QAGMAAAClAAAADwAAAHwdEABjAAAAhQAAACcAAAB8HRAAYwAAAK8AAAAkAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvdGFzay9zaW5nbGV0aHJlYWQucnMAAAAQHhAAcQAAACEAAAAVAAAATwAAAFAAAABRAAAAUgAAAFMAAAAQHhAAcQAAAFUAAAAlAAAAVAAAAHJldHVybiB0aGlzY2xvc3VyZSBpbnZva2VkIHJlY3Vyc2l2ZWx5IG9yIGRlc3Ryb3llZCBhbHJlYWR5Y2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAAGEAAAAAAAAAAQAAADQAAAAvcnVzdGMvZWRmMDE4MjIxM2E5ZTMwOTgyZWIzNGYzOTI1ZGRjNGNmNWVkMzQ3MS9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAFAfEABPAAAApgEAAAkAAABUcmllZCB0byBzaHJpbmsgdG8gYSBsYXJnZXIgY2FwYWNpdHmwHxAAJAAAAC9ydXN0Yy9lZGYwMTgyMjEzYTllMzA5ODJlYjM0ZjM5MjVkZGM0Y2Y1ZWQzNDcxL2xpYnJhcnkvYWxsb2Mvc3JjL3Jhd192ZWMucnPcHxAATAAAAKoBAAAJAAAAZwAAAAQAAAAEAAAAaAAAAGkAAABqAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZUFjY2Vzc0Vycm9yAABQIBAAAAAAAHVuY2F0ZWdvcml6ZWQgZXJyb3JvdGhlciBlcnJvcm91dCBvZiBtZW1vcnl1bmV4cGVjdGVkIGVuZCBvZiBmaWxldW5zdXBwb3J0ZWRvcGVyYXRpb24gaW50ZXJydXB0ZWRhcmd1bWVudCBsaXN0IHRvbyBsb25naW52YWxpZCBmaWxlbmFtZXRvbyBtYW55IGxpbmtzY3Jvc3MtZGV2aWNlIGxpbmsgb3IgcmVuYW1lZGVhZGxvY2tleGVjdXRhYmxlIGZpbGUgYnVzeXJlc291cmNlIGJ1c3lmaWxlIHRvbyBsYXJnZWZpbGVzeXN0ZW0gcXVvdGEgZXhjZWVkZWRzZWVrIG9uIHVuc2Vla2FibGUgZmlsZW5vIHN0b3JhZ2Ugc3BhY2V3cml0ZSB6ZXJvdGltZWQgb3V0aW52YWxpZCBkYXRhaW52YWxpZCBpbnB1dCBwYXJhbWV0ZXJzdGFsZSBuZXR3b3JrIGZpbGUgaGFuZGxlZmlsZXN5c3RlbSBsb29wIG9yIGluZGlyZWN0aW9uIGxpbWl0IChlLmcuIHN5bWxpbmsgbG9vcClyZWFkLW9ubHkgZmlsZXN5c3RlbSBvciBzdG9yYWdlIG1lZGl1bWRpcmVjdG9yeSBub3QgZW1wdHlpcyBhIGRpcmVjdG9yeW5vdCBhIGRpcmVjdG9yeW9wZXJhdGlvbiB3b3VsZCBibG9ja2VudGl0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HgE7AQEBDAEJASgBAwE3AQEDBQMBBAcCCwIdAToBAgECAQMBBQIHAgsCHAI5AgEBAgQIAQkBCgIdAUgBBAECAwEBCAFRAQIHDAhiAQIJCwdJAhsBAQEBATcOAQUBAgULASQJAWYEAQYBAgICGQIEAxAEDQECAgYBDwEAAwADHQIeAh4CQAIBBwgBAgsJAS0DAQF1AiIBdgMEAgkBBgPbAgIBOgEBBwEBAQECCAYKAgEwHzEEMAcBAQUBKAkMAiAEAgIBAzgBAQIDAQEDOggCApgDAQ0BBwQBBgEDAsZAAAHDIQADjQFgIAAGaQIABAEKIAJQAgABAwEEARkCBQGXAhoSDQEmCBkLLgMwAQIEAgInAUMGAgICAgwBCAEvATMBAQMCAgUCAQEqAggB7gECAQQBAAEAEBAQAAIAAeIBlQUAAwECBQQoAwQBpQIABAACUANGCzEEewE2DykBAgIKAzEEAgIHAT0DJAUBCD4BDAI0CQoEAgFfAwIBAQIGAQIBnQEDCBUCOQIBAQEBFgEOBwMFwwgCAwEBFwFRAQIGAQECAQECAQLrAQIEBgIBAhsCVQgCAQECagEBAQIGAQFlAwIEAQUACQEC9QEKAgEBBAGQBAICBAEgCigGAgQIAQkGAgMuDQECAAcBBgEBUhYCBwECAQJ6BgMBAQIBBwEBSAIDAQEBAAILAjQFBQEBAQABBg8ABTsHAAE/BFEBAAIALgIXAAEBAwQFCAgCBx4ElAMANwQyCAEOARYFAQ8ABwERAgcBAgEFZAGgBwABPQQABAAHbQcAYIDwAADkMhAAKAAAAD8BAAAJAEHo7cAACwoBAAAAAAAAAGl6ADsJcHJvZHVjZXJzAQxwcm9jZXNzZWQtYnkCBndhbHJ1cwYwLjE5LjAMd2FzbS1iaW5kZ2VuBjAuMi44Mw=="; function asciiToBinary(str) { if (typeof atob === 'function') { diff --git a/src/usdpl_front/usdpl_front_bg.wasm b/src/usdpl_front/usdpl_front_bg.wasm index d63284bc6c5d1ea35396faf816309c6783758983..781ff6cdb9ae9b3d59fe69ed63fcc546a8a1b111 100644 GIT binary patch literal 84394 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 WF5|(tzO_1BRJeQ{*XpWU>i-)X6=6F7 literal 84752 zcmeFa3z%iqS?9g?+WTCpPF44AXrQ1;*yp6@Ng<%s_iDsgyS{K~Itcps%!e~RU(=W3 za;k0UrfAS1bYlZ)5==;f5fx+43{Im4MMFkR7*mdnVnQNnG{m5iNHoq6?HK%mO48r& z|E{&q*{7wri+rF7ABc}?h7FXE0 z``SG-R->*OCsk@(Kez9iJy&hJYGy8qUZQNz%#BgJux!r_Kd@tF-!_$wUawHtlzn2V(o_Ynj}jrdimRPFY~Fo4xrd#0_FTJt z-&NOdyK?7-bsILWo!q>3&E_4O*X{5_3;^xizI*q!^&2*=yK>{ihMn8j@7QqVnh9Sc zjERP}t((}mb7peahE1E-Y@XS;eI{xMgq7+kkRQ|K$;Sf`TEBi~_m$grY+ti$*Y+!C zHqUI|w0+(7wf^JRc`$GEGqq!8-Oios*G;V3xc(=h{b=tnpRlBdXVUQHhx zHtyQIbMuvxYu4}DKEwY8+Vb_bP3~N`L51tL@7%QM%C$Ruoz*?G2)(;!_FOf0^|lRb zcI=v%+&;5w-TIlG8@I0;n9S>E=CnGOjShH?&{o2VL8z>gHjhlDQ ztl30glRMUKUO#}vxvN>C#N%@gZ(uD#NCm1#_Y9_FszckPXy^lhfYYq-z#H|(3)cH_S7*IhTW zZ{50$eEJplWtY~QHJ2tXPDX3ZS}jRy{HaAzT8mn>D6ZE|jB9aRUpZ21)Onqp#A7XL zxVRoiE{(Xaaa*g!QN8J6zT%@euBn+?Z75CB;hI`Yor~f$t#RdlwKR?D_4-gm*Xc5f zxVoW4P1a+H0h&vkA#Mty2<3phMS!->79>p5vgQN31kLya134O1_2 zk$n&ib9MEo9yxl@7i!Bct_GrO@n|%(d?agXST!03z`DS$+koOGmwLjBI8HRe8qL(> zq)v-^OhA=h0kb}&-AL7vgj+tW(_V}JG4w`!U3{2-d=jmw4!J-ec7Pppv2%uUx_yKipWMD$*_#OpQD2bOxhHjb94ye|5% zJEPL{_FcQS&0Py;qTg-TU3<-*xtV>@UoF+%`skBOz1|T0$x^R3Mvu6m!%RvMw=Vi< ze9?Q8JK{Uy+mkQ5KXd=j$KsE$A9BK>%QbZ1BL&0_cQT3leZ+$pM zy~&O5O+Fj{s=GV+u=}w48D9Lhd))m<@;(OP-9oW_#34RsZEK`+3(Hd2qUZOK0VDe)#BUl&?J68O}$$on}6~Wi)bAc{3lq zB%R8Wyt&aeN8*<5^3mDszsJ7KW=qdoM(r_buPB~*a6TG$QM*3aRngenX)R;DxFn5h zt)kg(jijyVxVK$gU0sjG@%TbLJviOGBXuIe<4E4rO5Z*EPeC~l3^ zTlr|dqT4<}Pl7d>${WQM7mU`pGi8h&`b#>u@Ju2LhZv~fzWMpCJfR%(p(YNVAK zwMvasdo^m68iv;}g4236>XjOeN*k-F@jc9Nqi9g0mDg-08vU8bTlopy&hq@E>GgNy zE2q!B2KxlDbwTp9h>g(_tfdr`Fq;*$^2b4o!xO8xSLe<@jIpu+W+Q{M~80X z#aMXp%y%B*sp+4NopIG%G4)9_vwYLMS_- zQs%K96(@$W6DwsN>rt^Xl&!3kd8|jpNulhdN}0!cRGb{jPOg-BtVhKuq3o1Ona6qr z)<^!uVSOyXJ63_$>q6P< zDrF_5zdn?`zEW0F`Wd0@j7nLb(ogu8hVy)+xVhUNK|qXk+pT=K)5x=}qeF1|R-PJz zM3C$&c_d^a;-+q=hMdcX^V+5R&PN8BoEz%PVhanl8Gkl~`)?MOb3CNy*7*3pzp(*&Ma zV4M$kI}HiDW`%jilt`@g-2S2m0El2K9YNU=z@8Xcjy zcFE|d6))1OMwd}szhrc|6)#e%Mo~A5#wDXGtazbD_1&W<8j*Ec^!wVy_)98DX!73? zMW|%2R#$oxwZ%1D;#yaF&c@T`y<77T&N{jL>EII z%#3j#FSKe1U{vZXKPj(q)2S6dw7YoI-UrbnA@_Ww?eZb0??jcMmR>mOMow$-joW)Z z3@^@?=R>R7G3aTk28)3z8l-EFjGUrjczBBF;#E+i*3$IBzmK$%##B1^iVv`#FiTQK z!YE314?aMe@$CMMICZ^SE;m%SWwzXkh<{JK4_^P_IBFF!|DNtWxxy9Cl}}6$I8H}e zts>#yi*aE`bHpHV$(Ww%O*HPvy3^;e9k zt6VnRIE@z*t+p#-EDSdV5~Aq?SbK-_m4~LI?^z`|*5E%_hW^{CIW*Riik6DWb_04s zUR{7BgMhpFN+@`8?}LZWgSs1{?gm_tVQ9f4^qM&=Me{Dpm=>{l<4b8j$zu%NRvs0} zxly!S^H}S$6pX1d*T>^SVyx3n6ahlwd|B~;1hpnF$AI3%5TDH5@&oZLZ-|O)wllOk zs-lIK|5iQW*txj?lT>>wRm|Cmd zPK)QiWG46dqpUG8UFQzyrZ}h}o>rW}?eXKs8(Vqcw$6Xe{a1CO+5JVlmxkiG+2T#z zR;NKP#ld6qQ5XBY6OU@;LYwVG6O{QL133Son@3w$h5p0nZ1Rg^9u_o^v`F@M;{6>k zxmU9XJYP0A#cd;64`6qq^YtQo)?GaaK=xG=AuQVL*Ig${rSL zx^S<<9_V(`8ydP#UZ3mKJwt(fpkfDT#ewUEP`C<1p6k%^UzNCo;)GKm_U(3@_#2NK z-H1j4$!P%yd2qE`^619B8>QMYBAUwnt8no41V)ROkhKArXYB37bJ_3O*yr{Nd5d~Y zLa*^)uRQu*Md)R(<=`rPvyOx%T@EMAryzm4I%ySY%!&&3Guj@`q8`p-2(cuHI$%4n zvR7XSY2|obUf;)H^N7{2nFK0O!evCm_ZJ{;wyfE_MqQh;Jk?i;#|z#dLmrx`H5Rwp zQYVC1 zQ98>EY63Tq)TP|V?L@q9RI7)fv?C~lIa_H&Ao{BTTfKPQ{vzGWs`u;dLRNNOTh+#w z#F7;FM#l_MO1#z~7;I?H%ayZNOD6%&1xu$bPIUfg+|q(!+*&jpMAxPC3Xsghmc1Q% z0wau;8}Qy=ILZ0I9hPc`rE+N@oNzOH=_=ndL*Kbm`fPSulhDdSe3_XsyL< zet~OPThS1P0#k+x7V>3Sb_%=B?xL10XJe60a<}9X%)Ozwz&{B0$4#;%OX`^~*^#thtPZ*nsBn5z-29n$YImG^_g*tw{F(2{Td?_ozet zG1jhL#lR^MZi>5n0l?nNT{{xpWPbs+Wg}{_8c&rN_&{hPI$w0PW#4Fmc0uL8gV?$J zJ&PH2Do1>%BUiTEXo&F`s9K}Qel^!`lO}1@z~TlKB@XZiNMMQuOC-)2 zV2S~0LGKqp_GPba*ZW>0;#;rC+SsspwZ_ZAvA$R}nuxz}o#kQXJIiK^YrvowL2S}4 zk7sk?G%qDHTJM%sorb25)rm^S%E0sJMdNU2r;YsdZ$=C@4ODIVYI$?EGb$d7i#;-O zL8 z-7X&+lz;9~bEZQnhch+1#SuQ>5%mQ;XIzT=c_U^S75C}R7_aEVNYUzxqeen)QF4T$ zp&pj!aYqUY8i#P&xB%;nOYUYn#!CP&dk|a){vfP>--uVbP#G$cq{1J>{o=V!yhwh) z15ViuuC2u(2CgfMd~aAwkJdYA=0AwOs^n(ZRL z!#IO%gxd2O@3k<~?ktv5RMH+)S~7(^x&X~WU7-mT#4_X|HJ)5DNEoScFFcD{Hj=eo zVW^AP=|l1h1KD#qlXRtAMPQ4o27N)YOHcs6=unEb*0#-)QC7+AsAr5p1M@UhN>Ypk zaYWjXsL<@Ig>qO7RVe6`+$elI$dGV3Xkirrv8A8>| zFPYoW2TlJotm;7;q8@bZmE5C;!=XgiUbXx5aCa!twO8$aJ=_~gbnR99fF6#75?y=M z9@fJHp+whSwMX^vP$<#0SM4!9JQ7ND?NytvmOP;cz0u$vuReTA4|=1LC#w%n>p^c+ z@>KQVSv}~DN}j1cJf{b}QOOsp56|mCZ&Y%u`tYJ2^hPBwR3C2pYfAJ+C3orJAb<3r zYp>)UJsb`ty7sEwr-!>kiLSkB_v_)_P@-$E+6VM-B$VjdtM;%S9tb76_NqOqhlfIm zuDxoH>EV%3qHC|(6MC2rCA#*ieM%3HhZ0?T)t=VFlc7Y{UbScS@Kh+#wO8#qJv@|;Oif(!613=VkddO-VH~W6 zo3|cYfk(l~qi_Ump~1U`gf^tt%x+6g%cHX+oI`WP;}3e1Q&z8J-LgC?%x&3T?xswM zN@X=?DG&Z1gMiUTxK*gDIJr13-Z61hg!fj{afLJ_i@c$$q%)%|Nw&yuc%^AW#2Z$% zNA(_cpstvCQ(oSv_*~;sgkPgLj6x$vUS}x#IaGmjqQgymvKoZ+DTHv|I5WDl**TGz zaEB1`;iHN#;DUj@$6bn7<|i(Q6jN>e;iJWO?(NrfWzDL0^u&P>GGBe`g0B+$YI=OZ zYcy55o$f4njpMEcEd4n2iIq4sForlZ10fFGIgx~l;^h4UP&U-UaFGqZty#NxF{e)- z=+WbDNUp;Q=H#iRm6t}^kcwXw(r}jfny(3IL`Q_3g-9bdx)jou>Gd~+wB>4H5zu(5Yr>KQRNIS{eeQBhf zumEXes{hiIcB+bB71Ce}{|Kb5vac2)?R5WoA<|y2*RKU>LkpMZ8EOH}JGeYwXYDRV zT2$oSwtO~Y-Abvs+3?^MR%vmo>pH_Ykm0z- zRTD8v_^K?YufbQ79{(H#V&krLg-=!#Zhy%WM+@U_^^kgWLWL2Hdd9k{(o%2^FzH>_3^>plYM-5?~$PuM|w|&Sd&>6h?M9=J~KDaSibyx z33L24yew{QDq4#a_EP}_C`;MrVv+qhJ}zc`bVoUqNwS+$~N-sh3q>d@{oLzgMrRe2=a#((p!iw{Aa0P5FiMWIEYIIwr54 zveJ2OdAK{~<0tj{Zk9+=%*WmAO*Fb*5BECR^7@(zXC`;MP3~-8hrd7^;I&r5w?Cj@ z)IG6KJq`ruM{4_C5%HNx)M;#T=kW%&_av|BTwZDAZDyO*B-L0jRNRzkZ0a-KlnB(~ z7zpy<{j99!qn1d0aeZH`#FZe{FP^Yg#8X zt52aFDo}F}w~%jn0w(3;QK6OfysBkChBKXzSi(#L-RG>Qvwh`p-WwQ~Q%uTCE&C%Y z&MCH=)g7EGSEx=AUAWPGf1Zv474?8(m!LrS#l^EgQTI@!zTq*Pn?M1c$DL(E2?{wu z6I6CSf5uu@ZW!>n5w>b^WY2770txO+5S52#yxHc5P(}8 ziq@;AqU&8f_g;7doQ>|V0MjxzOE8&ck=inU`X|K%0)`K(rY-Xq42^!7`vK8C ztBK)!m57s8)=Ld-!B{WCxoATx2mj{57fTJT`US|BQxzcS`{S`f{P+B*_-=6xY<-}=M19lra>{K5E8zGC|L*T41;U;XPp{pj)NwwvMG!X~ZR zXcYty@hcL-LW-hIkqKwx7re|i}^b$IrEW0I2qGz82WW{t_|HE`{MLy=Em1kjhQ9KAG3lWSeeM@s1 zeV0)yDWnVrS`$%?EKL}moR%ad$naH>67^mkDWR5+h(?^BTWBOLX~bUjDN9@ejs^67 zeIQJFQwq)dDOILm^8)I?E?Dnqq%Vu9yskAWq%zTBKG9w+M`Ajls6&i-NIcIn2&7dP z;CHrda=+2d&T19662rTx<(aFA?IH9cIOzw6;@Sb+fyZ!jrs&|v9tDY@X@W#i5t>SB9t8lqdxLIDikVq{JBO+IF zK`v$x&ynAegd8hE(nQTD;G+lL!Y8O?16AMgXz+2FIrc$<)9 zXmGP3NQ=?(vA{baUC}qMtdpsWq)a6eJ2u)}RXd59G-CNmf^tfqLdqNOPskmmTln4u zw95+a@<$A0R$fwC?KDNcUL16>eEj;jIfR0L(xO zB#wtJtc6LS)NA2~h(1NFIm_UUz(@(s#&F~SR{ zIY^}m7hh%Op}6Ad%KfLf|3Y|=CSMq>rqk&rx1O2@pArd7aHl$NVd7FL{u=>aw`1I0 zVRspKm)qS4cbC~+le>$kH9?S?cCvR#qj1FuB&!`f79q>eiIN`R`&hIG4?af7wHD}u z;Zge_)NC}*ZDzMg0r^lDmMT$g3uv5+gv&+@n^YD_p{O^v&sB!H5Ct!UVG9L+=kKR$ ze%#N$^0=?2%M<}sVqly*kAch+M%KXquqzM$9Tp6ZQiL|kXXdV4c3)YE< z5qH{=U}C99`%bj4Io<|iVc?$jRnwI<2MFF3*NKUc$YlhtiiuTB`?QAAQKdB~+h|R` zloX9`w3r|(+L3|D@CN_o>9RLyH?aNBrE#2;57jF>tLgq}WejkWT`U7E&GwAK9f*VM zy9)1C(YXG>Y3-MLlC0$ASjDI^ z-U4@Z;y{QkNvXhr&`AQ;k%x!f6=P!-m+^*q9gTRttp`K~Jt*|6u!VT)-E7EJ_%6n{%kvYrQv z^RoCKR1AVNdHM3Akdm8IGHfxi4}Hji^X1bAZnj>RAL3rvzV1-?T6}P@-K;DD*S!)y zHO1HHN{B+uf~-L*W@#j?$&nOPMTn;sSuL~6k~od(AThif#7ZrRVh8*0^<>};jtz1d zEFQ!RlwhYNkHX8L2Le=%P0di;@27$fQPN=l zB?bpDWqWk%=q*xKd;FW*KL6JG6aPkK6q?EYoF!eVjUT>4E*9E-_^%rag8U&- z%|AfEmnssrvI?Zg^ywQ0)}wC|_#K-}yq-hyeCB-y_qGOFSsrEYP?n@myHp}hU@!r zDSR%>f{Y^6HdI+z12q{$usE+QBHenaFO`gJR@%QBNEw_Ijd z0oteXND}%)$1;@%<;?snG({@U@{pTk^%N;Dqvvq@UcEBEsBAsxf=(H&%pO<+!XymZ z`7|o@6&tEpzaO-RupG2BWJa+tjjBIrjn&dD%U%a?FAl2_$w%j>%I;d08~}=;DfIYP z&hDpykhRAuBNqYu5`UKspkxNK-1HEV9@yu)An8HLvpt;Q`js8dER&AVVZRf)j&k)n zt{u54*o_*@V+lgbevFsMeng1-L{8EPJPJ=ky+@`;*}t2G7R&i52YLywEY0u$h!7z% z4Kf*oz3=l`QA&-XW2w-l7$MiQe|OsQmen521+M0bCk3emc^=3;NkLCK|Y(wdn zEuvgtE+gvIUo^d~Iz1eFX%$QHS zgwz`>DZ}c4>$`izPgi%KODy>rP=aBsZH# zJE{3eWK0gWX4Rl^=Z%o2Rg<9BoaPNlXk;{?^vw(Ob`&9*CFt#EV+E*hdx;qpUYY^O zOZX+~1S}mTpJ1DagdQ0@SjHP{fAFZ`UnA;;ye9qKyaUCH@m{nxCMfc})KCIG*~De6 zKW=LvAY4R@?7zNf;QcA;#0_yOHTQOzl+>2!OB9AxyY!cSaWC~Hh#I2l3}Q1M3Ik)e z5(pznQ*xbcFU9d&Uu^8<)~;R5>vT7fUM05>JOQKPry85StDC`&rI`2|JPtB2Nh#b5 z{_!26E^5G{2v@v_j?&mm&a$V9|1HDU-~l`qRoV6d)_Y<;1We92dD%$;dm)yKr!9Q` z3OLg;HWKjb8B5dfa=nw7z_7xj&p-u7SbU ztQw>j0jn%^TO?`gZ|ZT~7=V}nP(h1Lh&H~kVA06RK%KtOc9rRdI1Wovd&J3AP1S*(I`9xRoI&h0<@%#H zug*CUTOAnejgg6F!gwGks1Tjzq*5|Kbiyv9g0GfH#m(-CuGbnps67o{xUU)R@kRT? zWgrIS)TQMaI3l@oq8y(Wy!3)qjKOT5C^m%EvCm8!g%HJ!xe$-qZw?{fN1!`VI@%!E z6h*cpH^mT{WcZU|5&Wi5wl_1dBT%qF41IbV6+DA>M2@Flgg29?7V^4n>tzjxF-cBT zTCzU!`j+K#gy#wMmR=F9|J=};BdP*noMpYLCLU-^t4?E8dzf|`W>M=kobnvKVvH@D zdc51(C%VOP?hsylJ z$a^ISI>3;C9@6{|*~A9PTxrd!G5?Yk;NMGTtPePdX~!COQ)7v#66M1p{OozQRI*0I zj`Xi2djiW1MXVqZ)VIB(DF`5-jVaTqqmuBwXvfll`m_@}w9o~O+lF48BzfJVg6P1{{Z9e6a0cD=|i=MP&zPX5=)Lx&S`UA5z;POVCrYcLHXn%a%%vj>wB^w-1bzxr#mhx%6H*mh ztq(Vn8a}xAtppDU!X~SuTtea8h{zz?LmqQk4hA$Id8fW2jXV}#?O(~PtVm^M65q=@ zP4CaagCyp0PP81jmkqDXI0vj&Zwxhgiw}L1OGj36SJcjp(vcIzim)oi`yh?uQqBcU zwSDzO!)zZ;zQv8BeZm~^zNI58cr$%qQ!>~9TS1p@03QLcj<>P3Xn;JEk?gfWfIFrK z0eNM(-Na2_4FrQIVvSY+Az@@>*=qv?rM?FUj(i#ra$Y+iP=5uG2JMi^7wE%fZ&nIO zMuv~lV+i6xqKS_-BAn=dB~vlPH^Qr@DVO~mgvCealhwo=p6S>qZxzDi`|!pFVoS*e z$7ytT+@^Bd4{5}q-C-&kEZ5${#c%O`E%8>UDS`0=@KUpc1#e;>FpdAE$0o%P2SU@- zfHCQd8uvNTN}Y}d3z8o`D#(y-U|T5c7%Anj@$Gh}Y+9DJufu|4c&b3+^w6Z;h2XWM zS!9VRg2jSJU%dZt<-Q#?z%deFVG6hP!KMQM7p(Bo>@blBoG(Dp~JMPLr{$(gMR^aiMzCWX@Qzcb*vlmKFI8ZL6X0UB_|uG zL7g+Y;6fXAIU)ha*ZF*ku8d{FcXhTr5Wnu=EI?TVhldltbuk9#b6q_$i>d9REw|G0 zSwoxs(1!Ga8kQAPg)NeUa(8_O#Q5ddtSoPc4GKy$i01UK*;G}bi z2z+^c%Y!GZ3QCFX9+d3GL!in#c?&T_K(+mQwq4ZRl-4uW6TuWSsD`-ncD>04@)P8) z;qB7iI7D^1sj(jLm>U(ns$I@8n8JaqvEFGW+T&8 zq61jc)>WjnLD^@)ur*sUP0H8!!3e=~mWN323l43CU7@YF)y=h(%M^tMUGalTyhKE^ z1BQ%Elu68xJXTT#m`tVy*NClMD9|#W8%n1hy8*k@awmqd8c=L=lBX}&r}d+ZYDd5T zWd|*;)Mxq)vQUnFYCck11fiEHFo3*}0fDWdwE_eQ5q|M*2$V?Wg=;m6BZRNb zfJll_7OKJ~)&iU*Sa{<7;KYC7d*{2m>5;Q|qe$V{rgR3GmQE&+>@fhrHX=}MPe`Gf z(on6=#1_s;LpIckcVQwAD^agjT(P$}a^OM=n7tae-(|;IL8eVDWHmh^0wCJHx7dSr zVa-}2N;@7Gg_>v$b!`yt7hD_;evk&H zBXm&8G;JM(SX3xE>ZZMxb83#P{tFQ~+)}iyq{O&a&a1yzdY*w8|+JVL-BpB2p@# zew+4Gt}{&nweV7a;YglUHAzG8OEn}O*!p1IHG0W>=#h(#{~<7cKQlu-D~Vi8*o#rb zXC_x$!l`cE+$MJyH?VV+;7EeAmPck`wlukE19V=sw1q*Ki zjZ6zN0x`JJ9Z{2{dF!Rv5Z!Vi%Nr4KH%m#2e4LJ%ry8Gi2nf$1k55-ysjji-g z+8s{@wpNOTGBqnHm8qqCV$5W8P&Ic%&2hai#+ruXq}l(p4v(NLFz|8puPq0n4pggL zu!~q|XIwgzp2G*G9WV&MA5(2?DDTgd{*rx=q-b#PZL!AdHJaieS)jkk*ZJ_KL}_B0 zA6=A&Nw?n~zl96EW}6ZX2o*%y4X}Ic)NJGb>6EONa$;;+GwjC*X=HB{6qo~rKe)z& zjP=gj)k1ql?tER2<9t{lToUfb#NNRc?UCrD6xs@Yhu_r4FB}?St62e|NHL}ZJ6gws z3D-Dtk!E8#ZmFmtDub{X9+G@WmXKP?E;aO+@G-G^s#(JHqdaV9 z!e5lGMX0l$pj4$}_x2auH}4Y|iZ-95%Gd^xWEIPb(KI|@^D`nh4S^4z&lGlc!cEOsi{+}C~PoTqzgWX7oLRVQ`zAPu1n&` zts`uid26-7JS@ubq5jd4rHzVtNDygrC!Ppia|V_~l2QafZNxvMANEevjzBilXmSJ$ zBQC*j2RD%M0*#owebuvR&?LwSNtl6o@Gs-?C1D1(;P{tBjeSiLm;lGWOv;zI3}q@= zn`!xy6s@$V`IoiwWnC}p{$;%wzHn4Wl(ED#q|PvjO)zISB~oMOsur}4Vqy$$zvqD` zqw9;~U;Bp}yL(F(jj_xEe&t$P1~A`YlwwI4X~*)5C4OHFZZ+BGJS(!Go=s^QK%|+# z0hL``KZ)^DYDV~ga?|My&-h=IPh9uAb8_2=rBOx*S*3_lnNo%BnDve_o4lsePsN}u z!oOlO5H=4!(#=N}_Q>lf*HOtMn}GD~r45Mp~;dO-UN|2KfclslAMg zLHsor^>SS;&z7Xgkarz4hlZid^h^p^Lnhlaq+nL2({R+LbZ%p^a_Z4=6OS?ZjCQJsT5ERCN}|mPjH=Qa=FDqsO?f`w zJlL?EJZvUkzERkqhi@WmkkdC2Hq%$2G}g-)JV~N95E_%pIyD+wYD&HDuQ#a%l($G0 z5e{YEtE=k>eMDZ)vMTWW!t0GZ&ZKAoJ@TQq-``V<8$Ku{5x{q|=vYuUOG+9Bi%1~_ z4*gcLrsZ>RZz~doTI-L+9mzx>xgQ}`(^}<&*cdo0os||8J;lS|&{8)Q-)8kA^JFI~ zM$%E5DF8^PwD4{xq9xXr)WDi5D4VT~K%_@bvTM#3V{)ov?M2p=q*`;ol$r=BF*N66 z^7aiwMM*|6QLjRXH4Eo7hdeXRH(oh0FMGANf~dIlWlaO1<@_c9)7GdH4H|X^3kdka zjcBnq9{@4Iq_Goq6KeRPR9?jf;Xg_NfF05n7su!oi}0gQX_A1_#r@GMT1riX)`HQe z2`E=&fI}wkP4s;P2f?8ip;n?+C02&2k5(;E{p<|Gx zHm}#`VMbfv#obcKMZ^5c=5}NU04@YNE!K!Ir>_lBL^wyyotaFC2KOP^Y|fJIx(L*O zQx0ow+(sqLE)wpfjZozlu$1Va*M1eING2V7bU4YA9}Hlt8hNW&+RRkM0*AUIRMAci z{+2gx$BPu9*4l2#n>#3{vJ-};NAFZx0Lt&pouS)1t(!X|d24#bowrNlX8-SWey8pb z^?7qTyOUO?Pr4Jea)^SPJ58%b>$&c53o~%7A|m~g`#2P!D~(S*)1R&V-0na^Pfu3& z?IC8vc122E?Xb6lz656@9|AP?a*on_L+~{O9|#gaR;>!s(CsMR0-L@#rTTVOrevHZ zMN-{xX_x9qG=noi-0HeTz=m2KT?4$S> zw1muGLMM=eHSYx$^3G5tuz<$dQ-Ix+|EKyo#CTb=QC}9-_=zBFWcl_-I1bl4r$e|w zUS=P7Ks5-kxa>mc2i;=GEFVoU_=Lw(12ug=ZZkDcdewbhrotPM3T`?sMy7CHe;<zyA7*4$n|$Rare@WcTq~xlzaqv`>OoC@G~DUd ze4^?+=hzI6n~SK*kmY&g4mY}v(c?~TbbmK4gxKozu68i0AqgSg$bB-> zmYRdLcvxF%dQmZqVar!!&72z%O0q=TgQ-kx7|%wR(+n560=Q&>>>%G}XIM%r2m6|# zk;(_j>!@v)tnI~A*o!DB4Z*-0f==3zT$j0R(nU4~%5R9MYQ|}Z9vL2%q1sovycnVO z`kN+7Hxh%ES0)i$CPbP|38l}qg3A#@G3w^CFlb|k9{DFW9yJ*#HalN zgkc9pooXYn@l&J(7}t<}V3$RKjmv*gz*5cQM*6&qa1KfC&E;@0^2pQT?@8c_l~S(3 zVq!x_@}fexm;mSwItY)po)xZPO_)dG+dXRaSM}H@@27A* zKqtj{nhi#Q%nPb2r)+&{tOU_JCoq zpQ2aAKV`1<`%|o1<8H=r#Or+Ai;;r@WkrgAEe?5+1KDR;#!|R2{OhfXaG0PWRGB8H<0~eQI zS~VXM173CcazIH+BqWw{=s9>cmm$2y`>;b81!2y9bgX#8x7V)FxR_pEM=&I0hh~}w z$j(cY*54)22U0Dc?KFuJP5FQLlzlFrW1Lv*mdU4mUQ8`iQ+HFaWgIR1Qh=E^RKayG zWy!qKd0h$YNEEq$C4M+h!qhD4Aa?ENAkfCS*WREyA`Wweo;p|np>+~NUL`XS0Khb@?2jQH>LY<{m%e4hGE5l11`nA&^DaqL^TiGY4J!;tu6IdV zIIovCkh2B#Wz0&Q!=9|;{2&OdL7IAz4@+2L-Vyl})^w|JB4n`J;6I{#MMD@RLzAKd z+aY3zg{lM$=Eb|Ko9Jm?ymMmI-2xG9XFA4<33WgGZoN=~Ax_yxdGPx?>x@T2)Ml2T z3tFmqfXqc8?LZVY2C^MC*$u%MNv1ya!-Pn{{kj_+Z;3P-`qzXAv5d|9>L|u~g;L)4C2VPwM zlWm9|QRoM4Bl}b7d z$uHwUw3rECdWb;a`|L06xFRS{jisyt*43kzJE+_#eGEhCv7R8*57X<;9!3*e(jp!NpwJ7p^x|W>LdR zWr|sLzNfz2)-Ng;5Hn!g#)I9#CLjQ3YoiDWM;J_48+Pe}#;GSyqAdnfzLl^6>6v0j zkyrDIxSfc@1kT&klzH~;cZTOIbI3~*M532$HBpte-}6iiH9SKly2~gT=@w67BXCE= za}rcP^vU_CSjRK@n9u6|F66SE?Z!LHQTwyR)$k`W$@22VHp^4+BT=hnd_wd0#pmYn zh@rYqf8}Gp`|+c9edd>+kId0#r?tUdr@!e1C#_26+EWBp6kr#47 z@yi%0h>PDLMJ497+rV-nPvp#G5{3n#;~?Y@d@9ui(*+&8EzQb&2bhix4z9&RDfb~h zJ5J%3?+~vZKOu{c&wPpS>f0%)%Oi>JuYR*~-{k4jt$)ugs~!JiOW$(3+nxO4(Ct)| zpD@(b=c+|FbSEdFIVx}N)cJv=T$6m1bMrjOtC6Le=hqrH85doXk2-hmcvjUbk=~NJNP1D zRrt6yp&Wc=qGwV+LTAcNlFM1Cl8|$;(qsdK?^8KcAh`p6w85B1Es$P5$Ak?nA4+%x32d||jtpDJ9(dj<$mAQ5ezLLVj32fie zh3E0>F1DLTYDsn{>s{-U$~9#*)XYkRm2|Va?a+>a4#Xw_O4cyFMP4ab;6Rhq^w5iO zd*|5GNs=gS{AL#RGc0V!!p0@SK^fv|1?D$$sMbjkII9XeSjDa7il7t98t2uyk?qiM z#&0r{%x^trFcYBFux1vgtvlOZ^>n&UG=?2fKP!iKiYF*|j0k+PUc_6KqykUU@p*uAw!AvLw7f}s$IPLX zkw6kof;)U4%v+~){Co=2wu3n=E@*3@cq1Q&4R0AydL7DvpB)Zv-h*2_PRhT=R6EhK z@n#(U=h8S%%7;Z)9dr?u2VF!QbU|JZv$5!e3+2#pu7%T;b1igojn1|3DCHtym+dhh z6-W;+mS~5V6wZIE(gKZ2sEjmS?Wi09L`JL<{VsKpBy;&sT)1*5MU*Z%w%&`m&9aiCstF2nGj%8@*ln7tW(CusnjFY4I zzjS5=XEQ{0HiM3CCDRCHu~9j?qG8SG=n5OX=rCnoHJL<|Y0uh@eGq&QG>&AjZ=~fT z{P=74x(D?~;BKYjSC5a{2M>O>KX*`7uFu@oE2Y16?p3!CgUM_cc=wj$a(_~CwA ztOI-Qwe|fp3Fo++e#~djwRbS7Uy9l5X`^x)C0Z0Jnt>HKy^cua1#Oovq$OOw$*tz? zu?W3K>o}-EoWN?IS9AZ)OfK4#TrK=Gje{Uj(cxHw*?+@ttJdv%Tk*suOg!pA-CVs1 z$EhJgdxrEOC|tP!WYW}N+b{t9-%o&Avi+3|SUj!!dp-hwbV~2XrNP-DjZ?tP2euc7 zd`PBMXaYk)ws#sKPAAzu-jnU)1Dk$WXHvAt;b_Qv3MmO_nzb^%UM@7B$p0}ve2*vpVLJP#vC zeAFa%F8Y*1mjx3-DfYQ<%rpV?n{16Z zK&`AM#%y;C#^Mjq`n_I45lrK_hgb|Qc3qXX-pu42)krR24xzYvRX{_sG$5$o`0 zKeFqYFKp9g2XeZYNl?zs66Zfs2~7t}mf#4-44ki%8aUdsn~j%e6b=CYO@(|(copuTE#L`u z&Ir;4B~PPcXHYzw^P{8U&*T$8+-050&w%PEL;q!$L>D$*_#_l|3`xTBC5s4xwqF88 z@Ot%)3{@JP-K$#Ydj5cu1g`y6=~Wcbe>97a&vt7_>r_Hx<0H5dQ z@>Ei;)hNB_3+$8Pf^)v?jd>!$lUlaHMLpX78{u3#xP8N^-&>-c&)NZE4V~8dsiaJQ zmmnPAlTzUZ7-cV=LCor+9;3XdGdy4fRhZatB@Nf$9&TrQKXQy?oE#cCgG8+SLE;Uf@L(tn?K%=&;qsx_Eln*A@&AZ7M& zT)!nF!6xB|yFy-|>gxe<4+D~YkG;oXlK4sFq~->QXviJ3NHV>i*@E%(V8Q^k+&WH zC2lI2(zJ2Jwqsj8kx)1;zn}5K7d)6$?%;5ihnwTuaO|0z8a-bCa852UAdYT^viX`I zD$58lAvLlTZ-T^1)C`toT2>tTJd7pH!a4DsH4NWc|bzaeO%;~8h~27@N8M1+Iw4{ zc7)anQdtZQCUOmD1i*%wl7nC8sFCLWHVq1=;k<9qq@VJ_y9xCvI@ZkT3h3xuSj=1c z=`KZRU=TSQ5zMoXhtT%lp%5^BjySR4b}}XZwEAS|V3t;F9PouvjRa&2X|M}g!wzPn zrkx(jo`CTCIC98X>MtT5e?R{F*zl;JUz>bXP^3Txl;n3!rtF&3F*fw?>IJ`e6%Fm4^bq6aD&#TE*I?jd6(wvL7%E(gDRfEdbX(q*X z{aEZ-OG!$FAB8I5gDZ~v!E(P|1qs6wu>!M_B*}@9Q&Waa9<~0+x#0sfMHVn-EPRxG zXM0)CDvk3Gur zXl2sc@@$2*iY@6|9f8DXwW;4ij~JuH83>fJz-Sx-^g4|-#tuNSKmGVkk@KDXP`gaiRO%9I}U}xc-wId2BK^@VETBcYT zKVVMrKgcA~8pnE7jNktjUASS{JE_~?(yQBe6_}fYb}X)w4|hb5nNKFMbKwrg`_7F< zkz6qcI+BRR(@5dXHsKT54J;amrgctFP1!*_A;!(2siDEh;PDm?q5XrY)|Q$?zqJmQ zmmQQZmf4FD{U)EU;XycoVFC@Jy|jtXTV4AB~KBTA`Gurh2#utc;QtZ94Pu+M2+TeGx_3GXB= z5#Q4$INL6!e0IWJ5&e^2HDsIM&?(1t{62 zEv2=;WlpJ6wh4|?a43VcY-Qknb$rS&!|-G*@M#!cc~V1b-j%+4B)Rm~H`*Yh>AOD} zeXn6k=}ELy(}_e0W)P|Zlx!6alDj~?Ti$vUgh&A|o{jdf7cibH{uAnKmtn*6kwmrFvqv_+n{^@V~wZSn zP+cNOAY&PeZ0IJ>b3d93r><$!An);C(b26sMjBuNSN4P?5baS0Pz&v z38MYxcZf;q0KupF_3v~#yVrX@>DWwYW)tLRE>RslCLbiKzn7?m<^T25LL5^`GG5Oo zI@W0n_(YMqDC(gBJ9_L)jua$&5DN+fDI8+bQfr;3)s_ay>SAYv&jRXwN=KDXvH7)< z%@p&RBOpprhP7!fMw9ty=V&BlBuCCV{iqr5P!I6S>dscPcKb2Nnmqrg+%`RBZUJp+k8s5aX}B7Gfl2si+d8h6iZII2dh(7^8)>5zKeqZ)G&l zqZX{qHCtg8lcKfeNzwI5@g@4(M2ibZ@f+?A3~8N|Ij7}apAetw5n_m8n*RX(OFU4@ z65_!WPP^ADVq*G3?9L7$g)8@L`FF^cugR8Yc2~iv25fo#=BTM&vd-0}%n1MWoqpvG ze1Hod`9bfD!6*>rJn=?)QZ>>=iWGPw9sAzmqB?uPjC8JYsc^}(I`Z@!Z=`d_hSaYIaCrK2YgX_8?gZ&Q2Yh&?jzrhB?eYu zM`&;oK&KUFaEtG(0VC7Vo@B}4eY%RMjecAMa*By>y@?ESEK-8iQds47J9rG)A~EIv z70-WZ-sXdjbqai4KfEV39Eswx-*n=Y3J{rpFtLme`$WpS?ZS=}$=4}9T9sObYNpf< zir4LDhIK}q_uOEl%2O0mLA*FLENj}#1E$t{U%A*hoWW{0MOMpx47Hl%C7Ia1U*$`L z%KEf*Z9H4;L-C8_XYh%g*{5UrmCZ)?GDaC5m(&})!cpuEK@duolqN%v zvOMjCeO??t!~WRmb9u8B<_F^STVeqVY>t>lj?Y#Byp^~aMeE5bvoNuuAxR%JlnRfi zkqH7{Liv~Xz%rU+J`_b_%>!#<=u)x-)s;*tbVVe6sa-(_OhSqYZ0ut<<>5FT$yQFe zRhA)y52E0w#bn<{7w~J}#u5Etxy)jCB6ba3l*CcolDiu@cTQG~&C!^E&P<0hm~jj zn>R%AYk;`nVs_jwcEgR@xRv_{%5BF6tjU~kBl##h_2qNUE;iWMan&9N+T7a*ldZ!U^gT{6r3 zk+;&%DEVWRl?J50poQRn);QIP;5 z4sa9%#4uVeX&@}8{uF8i%1AGJqJ-aHO=1LHYo(Wsv&$O6jS5&OM;yotBql+E%8h%~ zI0H%q5!Hn82X zer(A&88n=Hh>_dP{xgzVMmgQ0oB=4(g9zLQJ~$6(R3TvWsO}&775Jz!5sN4EsPh#l zdRF&G$|6>wIpi%d!8{WnVhs{8U|({wj&dAND=m{kwpFdG4@k+c5}5Gg|3W*XczQ9K+#w znOP})5-3&eQ%ykuS`<{?7zlUKRuK=vYdPK;%*W-&SWwuu)vN$|bfGLbBbvj~*?lmg z?=q)-6maiKf#Jp3kAMK_P)v{5B|qD9#(r7VtUzyXH(6x%du8ld!jDD@gYztxAe~4B zMOxg}zSnL|CDYJAg8(wA#<84racNulaLA5~E~s)1-Lz*A%T}^8G$V ze#HKxdLdr`)bKP9exD-ki8*7M@m=`ATxBf5Sd3}=_*ddF@ebLAcG;EV%V zh7L$EJA=uDA<-Q(L;tui%B%{_GBjA@J0STRzh!nOVUj_xJezyS@CC#7LY zhJ~i0;@EEqbx1I;O*`*hc$@sIo-Bf=OGKwFq;~S}tq1w(Va>c|+YqC}VZ>SV>tWnt zRe_g+YS@41PO`Fi#%8mP8Z7TVm4sbyonz9e~o0gj9jA}nYXnCcf|pLOKJAjUQr2N;7DFb%|w zN+W=)|9u)p{mlwmAVQ>6l!1*`4q6Bm)h`xDV_-5=P-F%*X&r;G@WkK8rR2ps7q5=o zR31r0h`yxV7*W~|Jjwl@CoG1(p$Ur!imoA|oG>JLfJenvsc6QZDB6=9aYbKCo8-6? zyvj4rep)x#bsTH{CDO6ftKAU3*KE+Ws>33_o~by_?1%-8wK3xoZ4E=Z)oI zVFi)qtGFl}$ls0cW-aq$!GHe5saptt!1>_{WNjNCfG5z`_-=kXnmZO$&SO~>wuwHB z=ShTtPlg-v1nx!$P`ad-F(!{ae>V1wk5SABpheTg!KQYN z*rJ8hB;`2FNAh)C9(NP27ARDbiWCtgsUV8v1QVr-qDWF9pIfa+pRusNIZmach`EVa zMOJ3y8G)ID-ybU`X(4YVJdA7$!UiIH%!L<-rwR^i}5JH$CEKJ*!Wdh$b`J&Qe`#pmBaX3yta zoD(c={nHQd^wVQ1_><3byDYrteEjzxvvaZ|9jgD#CoF@{?94-dIv*9^QhZvM`MCJ8 z&vE^)NwyUih6esy@4i91OG{uLW!wF+LvvenqD)jg`xz>a7Z3jtmm{wD)YDvl(fMy% ze;4TTSmLdE6e>H0-LCf`F648=3^4U4)q(2Tmx;`l+lA$=KejQGWgb4{Y9FH9=|d{( zs~_hp*g~5(a+1pGK1}8|KhzPIiW61OOb(;79aIlYt9{8PLen+u!QS`Z+@suYQ^<_o%n2SbH?wGm!560z|L^ zz$@0&t1yrb^I3K|!dE6z$5x~aBp)}gh#D#{cJc2f9d zGl+>)LK1l(+=`(zQ0jGV)PrCv{Xy*0iV&G8^B6>?Lga7|TN9@6GBuJE2i+E_yBs>= zBOp?nnG!Epb#j1sfit1O(J5X)_C7Q5Xrw9eC>>Pd5rUR@@a_Q@n|bZ zWY`mrd_abczAMEeA8KKkczmKif5G%qljgN&P>_p13!OMKN60X}{D&q0%LM+W-FZ8Z zg_-O8Fjyrt>cgw7ac%pw3SJN@>Y_Fz`?GhO$WPmLF%z8S;mK0|6YiuKO5W2Vba*QW zy2*}8F+(_y`e&C>%M4jYV_Q#yg+B#lC=r4wikBD-NYUP*4qd1lyDLY7ddz4b=P(+c zmlzFth|Q!Q4b-U7a9K1Oq1@E+S2Y^f8;zw4F`9qwxw-BCsJUS@-|V^h>jj#Y7ZA`3 z3&z%^_{wjK|LHe>D*R85B*_dJWn7F`io3I%y2bD5196^*xyjyA{IPEUJGWbW(O#YA z*&^XLamUe@V2ZG9&jF?F7>j$G97PWBDxgSFvBEpN7ipkSP{=AQ`5$_;5hMH$wW~~V zv;-4n6T|#iL*kX3`fOLSR`Iu)?_zcER3M1%ljO;BC#zhpk`MfpUXXBY-LVtKuacMf z;_#v`OyBZyhdd1L&UMr5*-;12Sda3?ZRRivkS?XL+=Vm3-FUxmjkz=${wW4~_xoS# zV4r(!gMBPie@%n^)0iXp%4B31jqyAq9JzdDNRbVI8c_PP%y1K}V4=&7R{&MUx)P#w zpr?Jq$rI=>V%}^{hYdq#+85UoDLRG9f)~n|&RG*$1IGW+QOx&AYepF!9`n3X?&+Dp zGwqT1D*51bl5)eky7U{??=Ls3f21$tUP5%MH7QfFc8TmPkP4j2V!lq}^|muvR<5WP zY3O~s12PVGr{scUoR`~*)+2xAObH%5bMty-%LI9lZoz&H0@_5{qp>4i6jH@CJBd=J zBuM#C_=a_0yJ(}ktx9D}!Gz>*)d2vVbV0V19kVKu&r|_{g$x8VCMNNI|8@-K&0}eP z6VRy%wR4t(be7KSCmzFzd1j)FmGD*}GX|l?4El!yn+#btHaXr{OEkM0hR>mrf1gf) ziyIKP8k%7wdB}NYS@Pa=8c$w)<Gv^ZcWD4# zOX{$0Xc|&BXpNI$nn9zM2lb%^g9=8o&4ZHRfX(apD2nIt4 zKo@p{avGWLuubUXX%UWK1i?UMu_`s|PB(g$Ev~kEGcewt0Y3nR1HISAXKh$6I(oOo zCNiHeDCAlmj9@{x)KKLLFLV50GJ+sD{p=JMDaq{hvV$E=IqOJ6GmU`jiU@MxifYY8 z%YiOPGF0=5WAURFBgSaZz(uf()D%HR4Nt-`1i6cI>C|K{<|7bw*f~1k5RE=hdbs3C z=nti)T0_V_`K5XPN5dlqqBU1M{AFJ14=<&~%GY3X!7ue(L=Ljss>2TeK{gdEM{wcQ zfH4)1(Vm(jOvC8}_K0kw4PnO~izh;rBt1|(?(g{;)G@(A3j4MKMcBSAkh7B4Wy|!_ zB336{b1DuAT{%YqVi*!GV5ZD5BO;J`14%Ta)&u2X6~DD4sYB>w zq|dX0xBuq_DV@GlS~&qBa1MP$;rG!kNe2s5b_PFFYFn*r^@DzXR)qSJ29b{E({XZp z3w|B2x!aB_p&_AAspJwp{$ujVZFlLy)b4YcmC%hWPK}`TbFtyd$U^mFZF=;%TIC{C z8Q27~%5D^qV~VOOe~Op{Irs=x5?%wdw;&sl3cT$T=E~|-GcUcWk)TKNgzyJ7rC^hi z$a$202_jf*&g??hmJd7i_tY zik~4>`-AqTm}iB_X+sKH3?>uR_q99Fs2cP2DIt5W-0j7ekqR<_W#?s??LjI(Vl7*X=|0X2 zl~6Ek{3n9z#ZwKv8cE{RFlni0MIFCWOo(tTehSzlfCyw>Sd0LUKjIw-?B5c(<4c(L z-h987(b+Tu2~lT2WQRBxe|n}$EP6`op2wSd7AWDzUm3O!5+m`jjqiR{u$7ULz-Ioj zpna$p&clHacrH9Zzn7>}K23qKBRox-msvDorkUrdmNWw*C3D-7q2*D7`ZhKuyWUr4 z8S#!fe7q7a3p1{qH3+2|9rS)#;AJydzWHD)Rt3+nA$zd5_rc~=;X$x3hZB3|`kKH# zDm?{ShvpO_@ENpNo7o@6hCtZ6gU#5wkYqMT8E1HCw~GPA97%ET8i_nCb zU3CV5`KXN$mDy@_@u*obtG80Y4z)>f%@=?BFbv?V;>d?k<#e>hrd~d4jN*}(?qXQ5 z?meX!=%UhQZ2f9#ab&|YOk;s(^b#ZJ6LDg~#M6jYg=k#!?Uqc8P-}saIMew1j0Gz4 zjD-;`OpFj)(4<+*47p5regqT-n-kG*!qy=I#eGxGTY zu9&wMrrOeX&ol8dUp&0%3wb6mlmk8%_i_KiFI3+Qr=OLC2|y#)i&%>30@<#Yfd$&& zsuJEd8N?hdiE!t=)H#_eB-SWh!$dw;I3W~je6J_NbJw=CHBQ@*SO=-hr**`|q`s*v zeX;)j0BQhN4k`hRkpRH#mSelD6glm+mF`hfwulaxQF@P&vTQ~|{j|OaS}|iwhhm%o z)|S+TLBK*Yf?Q25fbV^M7LBScybQ#iY1k+Sn0h*f6C1#bveqf<-M z4!6YJ6F{+GlIpUXWMVt(Mo zbi`&7knEImDDSGQKXYRm=a+IXZrgU$iBv~A3=N^rV?tS-z!h1im1CrG=VNzH8+JH( zM~vgI;tn7&iJe3yf{4@6e4ZEz7z6{Y7_!-4>+y+4r7p?Zls@bu5BH+6cvmSG?Yrgz zd&>SyLlD!jz+5mn)wOqnJwj8KE%|QEtuPfqj=D&#m0}J!tTFxuY+@^;0E7%5pCJqm z%}?iDFdcKl!J|c*49y$J5kT+)+{rnZJ%;5cKg?ssSu{bRKZsh*voF2%lR>7S*=bS* zl*rn0O?lJ{(#>$WMN)PNCUL`Za|O%A;x;npJbzQ7o-r7K!(pT}B{z0cASym5dXhP=oDdcl51`}guSB%>XV@b%4j^j- z57a?nP!_AQJo0M(KBh-^Fy=jrThf-lO*CKeNfb~1(mW)T8N&vU@;i^jy^UdOI^RqbW8YCY1dYEf$-oI!Vs) zJ={OXAL9i72zY+*pAw!QjY}W5X9UE|pTZ*ry?9kN150!avarf0e*>C8;`&`ZLAKqmwR0SSo074!y0K}A4+ zTs9G+BH~pc_)w9n0zP>1t_Y~OylZgY|NqrFJw1~|354H$zJW@gI;ZNZs&B8a>eP|h zHh5WlZP+ZeTSIvVpx@iv&^|kI*8{eKfCUr>95^b(9LS8K>Qp3@OiM41YLD+_fIGx* zln9l$A`Du>YyhS3y10#;3KbH7U$whr#s~&3L^2QCgn!^co0<08%dP&^5z z1$@U(=i3ma2F9;N_8t(7Gi)fjnE_mcWGMSke83#zhWrt4&WzlF6YWH;(T}asLZRI{ zbtXm0E(}se_8qCzm87F;1mmO~7-9I(LHj5jP!^p5@n!agf;?J<`hj^m1yrk338I9j zs@QK1;#U?Xa90Aw(#8>t-A9J$M?ZAf0i}=04;q0e;%UmL;g8DqS-6lxXHNW0a=AE$ zxC7dDXf$jN1BrgtM|htFUINcW?%xB7@hrJZRD9Fqu@!Csj}HlB#~XbddPOiq0LpFe zoOOw>jE^62QVjIC@U0z`5yc3mSKPx79~mf%iK~40NTd;wm-}e@9m7FB4>}4NRsrV? zLjfpnJgzT;2_6o z;y8IOL0Kdp-{lZ3h)EnM;ke*B9`n8wlSz`qjLSxSnPx8yfGk1V2;f!%_2pm2@X+JY zU;bsp5N`rdIkWu>2^ zui#O>0u1!0kQ2{=uRUYbfG*<qh`FdKUv!dzFWbY&=dF45T8TaD z8$IwBiku`IO<%};Km*THKf_6bdnAgHaaOL@K%rsoUA(RZrCDtszUtun+>t-yK@;lo&=zj-;8h4$Jf@I}R~<(PE#s1xg!)tm!ge^E9jF3R<7WPq)r7wf$9P{R~Pi8_>t1cT>!#B zK0(meLd(8hS>X%z6x1n)NrSD_DFQe&If#_*Y6!FjX&(A97)WD;wiO<0(+ zIH=n!6jcC8Ebu4h&x$u>C^G*ws0LmYhLMe4gz@PA z;NZBCjt|Jqge$|v6?f&4(NUd@3d8U^%8T&7_a+ZMcWh0*g!1pR$!m|X$=jSJQw7Az ziXSDOA|p7I*DCG6LIJTRwJLYI+#y<(?t?-s;*9W&Lgkb>AYzyP2$%itR&w9veI`_AfU@bKA z(mhZ{3sD4HvaY=s*ZKQEY`&!|Hlk8Pi!>YP?2gd?p)ufiB3iJ&psI9EGU2E{1xFRd z%01Y>fzj|9{}Td#VEI)Pkt&Z-Qj8^ZyAJeGC1Kup(?e+eNh$({w3vDHVY@3@aKP4B zN^9|;d*}QCOU|{KkWa(xO4>+Av=l|XY0WW9IK z0u;7LJ!f|(+D7!!C9=qZhY z@_BV7)_Ua7lS+B%wpi=b1=V10-Ii`%Rf|{)C*AQ~FwylC5cS^V@fw4CKyoByw{vzz zu^yg|fbwMi!e$hiV_(3N`VS*(D_ zH)16EC8Z))VM0RZ=_NvzDAsGdk{A~&D>uZRT%0*t43Cct9uKfb5Wr3-Lgzn`K+eHU z(`E9@y6}j3Uu`d^KCLW6th65vctt^sDIlh=6VwiEvB9 z7q^755tx?OVsJ;|;iM@e0XPIf4sB)3D)g9W0{dZ-9Dg87wpb_0sz(tr4({uZP5v3r>muL#bfZhX$7%4_2$z@rZ#i>I_de!jm z8R{YZDve0qSftZ2^kBn`@|oT#Y^P=?Q4SQE2mSNhHDJz4P#syhQ zO$aCs6@b7Hs%|coWivFWLa2rcq0+3#*{U=rQh30g{|8SmEWE(00un?+8(aevX{FE#c5R;OD~5>r=pYVN0(Pa#655`!mhNmQYL zv>5s3TeHSR;9Nf8a(7Ca?&{$zk4W6$cXUM`wXdEn*a9ss=;%Zcg(p~mi zgjT7D;6DU}eZQ;T4WLsYQXF-}9Eg}1{EJ0?Hms307PcQiTU*!zyM$~21{K|oV~`Mw z;aApZXAfe&C94@{6}VoABj|z>95smoz~V^~S%EVC_a;m95#UQZnj5`1c10ozPj$P>m3@?+}|-*Oj-t0B$CWf+9aCt=%+uT(<*U^yxg z-?Ut3PP?@9Mnf!3BHfj4+3Lt?4@k)$@*BJ(cvP|}2@5{>S|11s zwxSP(s_JDQ3LUaH^nvASTpfa!84M;{Za#&l~`d<8%n4qoWwN9_lru z0t58B5iY!lfpf7TgaW>hJ&%qR6dQ6BKs$~Z&?!gk5oRBkybn+kz_AAh14&S@hKCRD z@0dva@`&Xqa7Z4n1q=EzVo2Umg5qHe1{fln3E3r2Y9e|=E$QTglxM0g$KfDBY^w3{ zu;o)lH4FiT07E-)=SC8T6Xja;O7PJ{sOOm3 z^(Z0~J7z#ji~L*1{9<4#9-tgy;nYfTX3aZ+AjSYNAGB@lssck51jmq%3`6=6B?nr; zdP+0OUITGt9D31nRPJSPrA>TPLCs1NM2EjxSw#8Y3gWT5RM2~5dKJJp0X>NyK^Frt zSZ%<_;NyIPq#M5@bR+E`T06pSg2k+W2q5E7aGDTtLs8@%9gkjP8VR_dHCETv$J9_z zUaDJDKnXAkWBK}{2hfVl7-at*u0s$fF*b-Oe)$^*h9in^GxOYI(Ept8tt>zya><>u zD(I-G$sI8(p%|(nEV2|EG?y4O8@H=QxG3~;LKff{HXJDG5^+?iv5Vk<(3XN@i~CY^ zN0Em!AC5_^kG<5xJlsB6lvTbNOpO$9mU@IbF#3G4$95;wM?Wh;hZf`Kphx8A#*WBc zm|}&d(P-TPPeKd|LZTo$YI4r7PU-!EUBz~GainB+4F-z5{t22_0F8{5!_Fi7{>8Sp zxW#WWhVXj}?unIMuE41oo(v1`3LT~j0k8zMpbC$uyp9zJ7~pUXXp6NS6*s}8wq};E zX0Y2P0|;DNz<}`qFQQFe^OaFSCcq+e9M%*tq-?c=AwyNi5eTyE0KY{RbLBIZ&SH+j z52Q~ZErlfTKShn9oWEU2%rlj7<9A~XP1az%lrtO$G77O2ekkKI>3WkihN;M z$h@5If*pgtU~_>sHp7HIVxTiJBj9ozAlj?`V)bmLba<`n-bF1+n?Qt6QAjF^=3!t5 zXOd+>a@b>g(f}l2Th#Cnf+wNNM+rYf=JHg3qY!IAJHn>$FtK@jnThS=TCkl6!$5W} z)hONM0Q!X(EKJacc#{9+D=T%8Z{CG$W-Vs5V8annjUsmMFeWw!0DR+K@Vivuw;)Qx zF6wJPv_*z2L(aeDY2L71)cwc^e{i%AX#h~1hRHvdg)lCh4?*_i+T^3cZCpoGi=@N> zbl8hfar051+$D|-Nl7(=p}MkMo0T`u@E$Jx&!d&B>SIZH56mvP;3zN+2PV$Yw2L-s zY&>!Z4e`SX@LWM@7a1CN-{D;zHDtd&h;pzh-lEUXe{cg3_)ke_KDZIkBly(4 zg~=p!XCAw*aEnzjzohn{vBM7~7oX1&3{XL`Ba zJb`dI6n;=dPe%-HCE-Ja{_Oj_6PzbPCBn=`3iC@_Q*-nj`aE>v@DKpDLD5P39B8h% zu>;~3dFZzXIEO`0jaL%Eiad%dK(By)k$Xhau(Bg-Ou`K{-;L;8eqiyDEsN7iTp>GS#JYEWDnl}_Ut$K&G`WIeJEE76h0$Zd$qg?@ud=(f2NZ|WOM zaV2_%Uq=R<2>nC6B8I5~l!(Q*`Jo}9K(O0Ttxuqg?9O3nNG3-x6J0>3E48mI!`0oF zqUp;|snp;cK_oT>=i(+cR?+TDJi$B&Oyef*L**sxlHy*_N~F0L2X;xHARwXNV)2Wj zcr-8q#3jA``(?`CMHw7b@DJM>D|CZ(<(U#3j2?PTU%?~J1RKQfQTT2ykk0?;s~j|j zeHFev66&N<4|N8E6-OPc4Ard#X8^fCIxr%dd}P2iILog83ifE*J6=^ciET|QJReOH zfewo|9`!|riaC;;ikqa0dbbB6Ky5Muq?0pr!TEa?zf%=s`(9{!FgU>`tW@@4X2y?V z1ZT3&Z77U7_Kqi~&ix?v6uVNW5_=;A6#PsK7fG7mQ#gWZ)pK_R(<6VL+o)Y;BB zqkDLR+#ZP*Dr2{Kb3b|vAONEbkF6d6oV+|1Fe6h?Qs3E&e`l?n7M!RGkLLR6LV(GU z=bt%nm~sj_5C110jzLq!Gi>MK6R+YSBw)ltB3Wrx`6=kNkn~~)=8E*PdM^x?$PGb7 zI2gn|p$k-&q8*;9@qsmm3{evpV$sb7!7^rX;t__7MXLHV_J~=6++$n_(z6*E18!m< zp&9|eMif>83T2jdAu%uY%nMi8BvGPYXp#VS6moj#40OOo$y9SGG@t5S;oEEl!iK&G zek^nxO*cxeQ3uh0j7`$?Yz>pm*@`IAza>H+(MXpCz33e2M9(U6*EI*Uh=H*v&QYN| z0V3oGt&wXK{GJw?9mFPl(x6g-#u)H@6#>mleE*zW00NJ=+!>rIwITj^KfLCbhYsxd>&;a`Q^RL8k%D*jxxsA+7X&|1 z)|pH0N=FB_X1AwPyE?6&XreD319o(z1BRyg@QWYKL~<1+H?BQMb?ICt+g;ZX?&*m~ zTiP4jx|-V>+q)av!wt<1@o;NJ;W5^Za1kJj}iy3*0~U|l8~tIMRj>k_HD z{#2|sodK++*qpTnzb$BNR#AQl@*(6^=d5hX>PhtVSzS4_nI3g>*Y;Fj+;)S8BR zbCHfiKNI}}eHr%jHNZU;Fn^C!dVFAa=hB%}8o-ysFJ23nzd;HdAK2-5GzMHL9PbDG z(*XAsq=iUcq!J|3mbCUGvE8V(Jdqjbiw;^GcDz5H%to_`RMJYvv$=FK9O(&Au*!xZd$cXoc(Mk5R8->u3 z&h-QASx1Lr<*NCe7Wx^rI@hI=@lI=Jv@aKTik=bA zt)a25E1HS7G}VM_>lx!cMI4F?XQF+qLsXrdi zi}S%z<(V&jUW$BKQT>up&&x*T_oM6rq;PFZZ9^^-8|bU)NvD!op#YQ+vHmI!dYp(d zok)|Bocwk>|6Y0bNV;vhTj{n9=qK9(@5H11RxA;-lBulKjjlx#Nir+$Y~Hl8rcKi> zLY+#Koq$v|U+Ef02amx$;)8mTI*5M&&9mdQE$KuSB11(PwKj_QSefmqTwg4CLRM7# z2gN;__9yh2{Id~>ePrJq{X$$%LgM(RAd%0hpUFofdbB*%oukIdP_k;$@qtvPPSG&! zTy&?>ait#O=~z5dmrX|#S<%j#c9lordZ!J027cKl_1jD&+7=6`0*UyYjWh>|{Cz}w zIHGgMssMIHGyOGPiDYbBJXzC|gZ7MPpbna98|#ahajrL{b))?kkl+jMzaG~4;L6Tu zW-!@p^&~r?cQe2V)NW5Uo(8{AD^u+a+rM2Pd)z8EfZDeKmDnZL=OHUM zCMku{ZZw*K&}`aHqiL;8!EQi;Qt9ZnxH2SGEJt%>!R{$afcdiNTsKLfX$^qIKT2XF z()-09yfXBo4yG{LCl=5j($)j+=h1*4zr|y0LcSR(fb?FicX9uZxAnFHBds^va>BuFHj+hIXv#M6+GToP#O-X86OD@YsLVFB*rXrK6cU&4I2HIK#F z0*LcA;8XMc2(+Pwaq`cP%D+4+|DU7se;AcNG%D|gJ6;SQFR_ovn>O(Apl|8MneT zJ#AJZIgra*U4vOjGHhF46oth3skU~(V}jwsZDsM4Y-bjigtSdXZGC!FU%rYw`F{OQ zIR1U9UC?&%qy^#V&h^1PrCjE+(x}W09F4xm2RiENI+TT~qo=7YM>%@dr{Wh~*4E;e@+5-1J(bDg zdI0x076&Hv6Y1vUDIe5xD{SYQ!|bCO7)T{EajPGiidqR?O}|xbZG-yCz)j6=Cl=y; znfM)mPk2w^cRYTNFg9Q@D+7BSWyk{-65AYI)^?b*$zznqltP(xNKPKAPmMDbjlq*n zr8}%ODYz^fP@cSW0e%G!Mb8!Gmq)Wv;KGKxcKG?GRBB^CM!ZZY2^jlOhF-(+T>rpu z8=7|is5Xk8Z%$@%0|TivrY4&9oZUvz^TXPB+is&f9ZmLTwnM{XjAbF=83=msAlk1+ z9wtYNCI_{}xHfTJQ8|0g+<7Nd&0nyvx+YxT(Ad=6(%RO(G_vgE>6o%m z`PgyeCrnf|CQY6)b=ve9GiO;s$swDRLp4AQODKvC4S}W|ixv+JEjjTdRq>ziU+KAG zPYh*=J%ADT8O9Fqq6!pa$Ki9uH2-`U7}9hKCr4i(V-a_Z82!{~YJ9`IF>>@x&Ht3+ zA0DpV{gP3m9v-hMFnZL7A@H9F4JQr_9V7prH1z)u|6}w+CmrMXhyGt5|5c%owi?NY z^b~CJRYQNrNIP~J*ALnisrc>IMZf5? zFGh0kvjo>Cj=Fae@?ELeAbsFe42uf!Ote2Q^&jCu4A zz%}G#1&%(Q;lh06jQE8)Ozcks6x>6BQ#PK-IP&`%?XGxNO=gh6pT^qeHVOV<(L@45 zbqEe^Eou~AdHs}-){8OGzohRR?PDxp(CSLT!QK^*os4_@|9>UPGvx5kK1d!^^_ z4oJ)0(SfS@){-SwsxP(`8Eb*nFllN?y8wOu1qjc%(g)QshIF>7n3K$h?nAphXwO38 z{Kd)7#x*0X?~e`sK|m0g$}ymTcG{+ev^ah_H>)kma}LTmz4M%NMV48KME$|E3TZV` zcV8-lm?K#`g=GiKAi3C-*ck_pAc`gNtJEMK*bH>MVqvGCZT^uzKZsaZ-}I5OFo*vg z`6zCm@^LDXgPXOuK5f*!b;vWewlcXs*^Ri7Qr-QCGb8?p#jX_YexP)>C)wc{DiZv8 z^rZ~R$zO?U&dr_ty||u(^nvy%8_o3AWgs00HcKp0@#PcfTpUlQvI(x^05Q%GVu*n`*D7W@ z5KVJPaRhs!=vp$K-IYrBs(wNj#rlf7)0avOaClf^N>U8W1WweMQ$2xqbx*6qChCx=Dixu8S1z%WBDRc9?FvxXfsE34)VZ zu(o4XfG?0Q)0Ku1N?HSnfw(iOSZY@?8jAt<8EG!M6Pr+oN9QJD$GJ@0UM6KcHXa)e z%vw<>eB5!M6~+D;Xf0j~D5`|U;@J`T9yAdH`}HRf)CM_Y@g(FHD+(L~+wMu_z_V4U zjJ@rF_Scbt`q?VJyBNQ;cZ%IHbOwBdAmDX760R2P0@_(9OWoOzU-}rMcg9F%$nmv! z&eh8^Y&jlXZXlXWboW98rZ{FiGmM2Wc)rmi@Vt?NXXGu^O?GdEgkv@ua8Bz|Z7wKH2}YgWo$r&&8s z@g-JAj%oAEcEE(j*p=k|nTFa%nKQw}IeW$i0Czobe-2U=QU=MfaR}XOIi#IPj?5g% zP9D}-!Z;x$e*SBAzdev2H||HF1!T3Hi!8F`;2&;}l0KoT=mqlK;eF}p=PFDVZBou- zXp21e=HuTu7TY|(wifH#fPw1TGMOWap;nit<+93b!$`z0qVb{i?V?J{bZ~v0OJx>x zJS-n$>$U5e{Ytg<@KPD5GtgJm3ja~ZBLN6I5v z{JSJj9jL~Sb*Xh}RiLUG_gUVd-)>xoFA9gl_2GtaW4I~Y9Bv7>hTFpJ_2K&Z`iA<( z`lkBk`j-0E`nLM^hHyiDLqkJjLlgELwluUhv^BIhh8yb}8yXuMn;M%NTN+y%u`{tL z+*IGx(A3z})YRP6($w12*3{k{Zmw@`Xl`t7YHn_BX>M(9Yi@4|x74>Zv^2IfwKTW1 zw6wOgwY0Z}TkBgJS{qxNTAN#2T3cJ&THD*gZS`#pZH;YBZOv^hZLMwC<=BocwxjuW zfNn>%cH9~{wmlfz6-axLs^(*{2@82J^%8&}eH;R*C*V1?A%ZkhE2WmEeR#g2$1V7+ z1RRI2hIhtr4@I5O5$vV?0Oh!D+=N74RX z&aJJjJ)i5{Hkv3;x|MEmZ!(t@x$ATnl-j-!OnYZAmW@bwC$(873K*fEh-IsrR$7g=y1 z@hFkZBoG9%s?<9Ed>Mk%|E1L-v6(&ir5#M-*Mr~DZBy>q_F=fo!FNH7t!@BQBe5Oi zR86}ZaOUEdF%9Z<9MkW1dpw5M_0$q1w8W&O3kWul8Q|u^Vpu;#VK}`gflE-oO9yl~;!}SNYia^-ZlEi!;MJraWIpu;_eD4jne)@Y)KT}#hAGg+QIrqE^ z5c|6BhA*PZcfR-HE3dv)TE1dUES}%{wMQR&{Kr3i>vvaNdCeVPcRUigpI zw|wJ=Pd@$3nsw{9oPEL8t3P)AS08xr@ozr)-Jh0EoOJGafBN&^hVuOv{_@2!vy!Rl zGqzrO***7O{`E&EPMSGu<*Ie-&pPM43og6--@fzQkAMEw@BWz1T%XN-a$arSo%cTY z_;;WA>5HFQdh;#e>u3Gwxu=KLtv}~nudgh0Lfsp0CR43TPFl8N-whkL<(~T9!DpZU z*{}aLq*+@l_q^!Zv)nh$b-Lw3=r2S@MyVdGJ^Ty{N^5wtp4oqHT20U%PmA(>BHaOEf$91+pf5qhKfrVduEvRWz$`A{4?DP-OF8L7UaL=nd6${ zs`51j*PXn()ju)do4ja6yV>pYhbQ7&m($$((l*zr?mAb%>-R3TPH>g@Tg(pkRIjVV zyJ1ahV`-ze))&}4?~HX-z6BGf&YM1dl7Af6*FP7s!9%g31-afTwg^hbPcd?V6N-cyVlF$!dRK<%(&meH%;H?Dnn<%rIB2 zX*I|A0-knnV0X)u{DXQ~L+KT__T+;3CqBBiyL4~e_0R5Eb^F76+Pw>0=XvG@RtBov zTv3pFlD^_x5Ab(HWjM8eCAAIl0f9i_oG3Zh=TXMD+QdCyr zYQtcve3k2VZz`E!x=pWth8c8w0s)T?S~dUuxq-c&qbg`yQEz3eLh0z!8bYF*8S~>> zOtJ5FCGwlngDbH&X(PQ5@jW+UdlI+gk1G3Nn7jc9-jX4sz1!ESo_wFm)EaPRc!e5qqlF+o{63w zfA;p%wHGSR&|Z3ZWBBFh=6im1`Tr2*Tgd(D6`Q(uI-C8${i@PG<}>MpMl6sYVH8a0@o zZnUF+PAfC?)w&CtVRYT6pROC;5?_~Y_=BEPjA?+U>#bvSwCE1%bNqUbOZT8t#uUS4 zhVW4w!|>?XXK!le3}Yt#TWaWDpKb*GI#j!!Gb;6+rpxf_9`iqd1oYNRh=$J-F!b=O zdRG{Ew_fEh!BLwiV7B2QDw-WW!??xNOLZ?BG>s>hYWlY;H1j&W)6zT%yw0ZwEMtQK zF93a?Vz~92jj3Zx^?AN2!CEtnu^Gk*`pLk&fn!sBdYz7Q15CqkW84c2pZ*5Xro+Js zVd)o8ex-lHt(h35tIBlgp9g%+_?KY4>k_@CY(7RAFzW%)t1mI;j#34&E!pQw-Vn(lA=IFL!iDCopey73$I%Y)x(#%3Sy>>w`iG;V^RZq2V7 ze+1RR4f;N`=F+V|l}D)LG0a*ZTk`@L`WX|^5kR@vg9d@47bAh^s8fl zg8@3C{7YP{t@00~Q?Xn(0+D(NF1bBA9;@jZG(5Yo-jd6BFfVVf4VM&eavvM6ZK!Rl Rx2nP|4bf3K?qL7` From 36ce024665d5b69bc4bd15ce62f671496b8343d7 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 5 Dec 2022 19:47:32 -0500 Subject: [PATCH 15/44] Improve the thing --- backend/src/settings/driver.rs | 12 +----------- backend/src/settings/steam_deck/mod.rs | 2 +- backend/src/settings/steam_deck/util.rs | 25 ++++++++++++++++++++++++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index 7a2e498..b637da4 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -80,17 +80,7 @@ impl Driver { pub fn maybe_do_button() { match super::auto_detect_provider() { DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => { - let period = std::time::Duration::from_millis(500); - for _ in 0..10 { - if let Err(e) = crate::settings::steam_deck::set_led(false, true, false) { - log::error!("Thing err: {}", e); - } - std::thread::sleep(period); - if let Err(e) = crate::settings::steam_deck::set_led(false, false, false) { - log::error!("Thing err: {}", e); - }; - std::thread::sleep(period); - } + crate::settings::steam_deck::flash_led(); }, DriverJson::Generic => log::warn!("You need to come up with something fun on generic"), DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs index a49088e..fb836a1 100644 --- a/backend/src/settings/steam_deck/mod.rs +++ b/backend/src/settings/steam_deck/mod.rs @@ -7,4 +7,4 @@ pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; -pub use util::set_led; +pub use util::flash_led; diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs index a8cd99e..1d89d1c 100644 --- a/backend/src/settings/steam_deck/util.rs +++ b/backend/src/settings/steam_deck/util.rs @@ -60,11 +60,34 @@ fn wait_ready_for_read() -> Result<(), Error> { } pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result { - let payload: u8 = 0x80 + (red_unused as u8 & 1) + ((green_aka_white as u8 & 1) << 1) + ((blue_unused as u8 & 1) << 2); + let payload: u8 = 0x80 | (red_unused as u8 & 1) | ((green_aka_white as u8 & 1) << 1) | ((blue_unused as u8 & 1) << 2); //log::info!("Payload: {:b}", payload); write2(Setting::LEDStatus as _, payload) } +const THINGS: &[u8] = &[ + 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, +]; + +const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200); + +pub fn flash_led() { + let old_led_state = write_read(Setting::LEDStatus as _).map_err(|e| log::error!("Failed to read LED status: {}", e)); + for &code in THINGS { + let on = code != 0; + if let Err(e) = set_led(on, on, false) { + log::error!("Thing err: {}", e); + } + std::thread::sleep(TIME_UNIT); + } + if let Ok(old_led_state) = old_led_state { + log::debug!("Restoring LED state to {:#02b}", old_led_state); + write2(Setting::LEDStatus as _, old_led_state).map_err(|e| log::error!("Failed to restore LED status: {}", e)).unwrap(); + } +} + pub fn set(setting: Setting, mode: u8) -> Result { write2(setting as u8, mode) } From 5fe4e9d15d201294c9bd599de3fe33668e2f7b02 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 24 Dec 2022 10:21:27 -0500 Subject: [PATCH 16/44] Complete switch to linux kernel SMT toggle #48 --- backend/limits_srv/src/main.rs | 4 ++-- backend/src/api/handler.rs | 1 + backend/src/settings/generic/cpu.rs | 4 ++++ backend/src/settings/steam_deck/cpu.rs | 4 ++++ backend/src/settings/steam_deck_adv/cpu.rs | 4 ++++ backend/src/settings/traits.rs | 2 ++ backend/src/settings/unknown/cpu.rs | 4 ++++ main.py | 2 +- 8 files changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/limits_srv/src/main.rs b/backend/limits_srv/src/main.rs index 7f423f3..d0054ce 100644 --- a/backend/limits_srv/src/main.rs +++ b/backend/limits_srv/src/main.rs @@ -9,13 +9,13 @@ static VISIT_COUNT: AtomicU64 = AtomicU64::new(0); fn get_limits(base: Base) -> impl warp::Reply { VISIT_COUNT.fetch_add(1, Ordering::AcqRel); - //println!("Count: {} + 1", old_count); + println!("Limits got"); warp::reply::json(&base) } fn get_visits() -> impl warp::Reply { let count = VISIT_COUNT.load(Ordering::Relaxed); - //println!("Count: {}", count); + println!("Count got"); warp::reply::json(&count) } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index bf31495..cd77ed3 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -67,6 +67,7 @@ impl CpuMessage { } }, Self::SetSmt(status, cb) => { + *settings.smt() = status; let mut result = Vec::with_capacity(settings.len()); for i in 0..settings.len() { *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index df5a6d4..568b40f 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -188,6 +188,10 @@ impl TCpus for Cpus { self.cpus.len() } + fn smt(&mut self) -> &'_ mut bool { + &mut self.smt + } + fn provider(&self) -> crate::persist::DriverJson { crate::persist::DriverJson::Generic } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 8f02867..35f498b 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -152,6 +152,10 @@ impl TCpus for Cpus { self.cpus.len() } + fn smt(&mut self) -> &'_ mut bool { + &mut self.smt + } + fn provider(&self) -> crate::persist::DriverJson { crate::persist::DriverJson::SteamDeck } diff --git a/backend/src/settings/steam_deck_adv/cpu.rs b/backend/src/settings/steam_deck_adv/cpu.rs index 2b13c23..50e4f49 100644 --- a/backend/src/settings/steam_deck_adv/cpu.rs +++ b/backend/src/settings/steam_deck_adv/cpu.rs @@ -152,6 +152,10 @@ impl TCpus for Cpus { self.cpus.len() } + fn smt(&mut self) -> &'_ mut bool { + &mut self.smt + } + fn provider(&self) -> crate::persist::DriverJson { crate::persist::DriverJson::SteamDeckAdvance } diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index 219cc95..c2f70bf 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -44,6 +44,8 @@ pub trait TCpus: OnResume + OnSet + Debug + Send { fn len(&self) -> usize; + fn smt(&mut self) -> &'_ mut bool; + fn provider(&self) -> crate::persist::DriverJson { crate::persist::DriverJson::AutoDetect } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index d4c183a..2e677ba 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -151,6 +151,10 @@ impl TCpus for Cpus { self.cpus.len() } + fn smt(&mut self) -> &'_ mut bool { + &mut self.smt + } + fn provider(&self) -> crate::persist::DriverJson { crate::persist::DriverJson::Unknown } diff --git a/main.py b/main.py index 6c1ab39..3e7acb9 100644 --- a/main.py +++ b/main.py @@ -11,6 +11,6 @@ class Plugin: # Asyncio-compatible long-running code, executed in a task when the plugin is loaded async def _main(self): # startup - #self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"]) + self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"]) while True: await asyncio.sleep(1) From 1dc0acca8e759d36a803da977a18e8df40c4cf3a Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Fri, 30 Dec 2022 23:27:22 -0500 Subject: [PATCH 17/44] Combine SD advance mode back into regular SD driver, implement custom clock file support --- backend/limits_core/Cargo.lock | 89 ++++ backend/limits_core/src/json/base.rs | 17 + backend/limits_core/src/json/conditions.rs | 4 +- backend/limits_srv/pt_limits.json | 21 + backend/src/settings/detect/auto_detect.rs | 12 +- backend/src/settings/driver.rs | 5 +- backend/src/settings/mod.rs | 1 - backend/src/settings/steam_deck/battery.rs | 41 +- backend/src/settings/steam_deck/cpu.rs | 74 ++-- backend/src/settings/steam_deck/gpu.rs | 77 ++-- backend/src/settings/steam_deck/mod.rs | 1 + backend/src/settings/steam_deck/oc_limits.rs | 115 +++++ backend/src/settings/steam_deck_adv/cpu.rs | 428 ------------------- backend/src/settings/steam_deck_adv/gpu.rs | 310 -------------- backend/src/settings/steam_deck_adv/mod.rs | 7 - 15 files changed, 318 insertions(+), 884 deletions(-) create mode 100644 backend/limits_core/Cargo.lock create mode 100644 backend/src/settings/steam_deck/oc_limits.rs delete mode 100644 backend/src/settings/steam_deck_adv/cpu.rs delete mode 100644 backend/src/settings/steam_deck_adv/gpu.rs delete mode 100644 backend/src/settings/steam_deck_adv/mod.rs diff --git a/backend/limits_core/Cargo.lock b/backend/limits_core/Cargo.lock new file mode 100644 index 0000000..9eb5c72 --- /dev/null +++ b/backend/limits_core/Cargo.lock @@ -0,0 +1,89 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "limits_core" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "proc-macro2" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" diff --git a/backend/limits_core/src/json/base.rs b/backend/limits_core/src/json/base.rs index c25e5de..6e77b71 100644 --- a/backend/limits_core/src/json/base.rs +++ b/backend/limits_core/src/json/base.rs @@ -14,6 +14,21 @@ impl Default for Base { fn default() -> Self { Base { configs: vec![ + super::Config { + name: "Steam Deck Custom".to_owned(), + conditions: super::Conditions { + dmi: None, + cpuinfo: Some("model name\t: AMD Custom APU 0405\n".to_owned()), + os: None, + command: None, + file_exists: Some("./pt_oc.json".into()), + }, + limits: vec![ + super::Limits::Cpu(super::CpuLimit::SteamDeckAdvance), + super::Limits::Gpu(super::GpuLimit::SteamDeckAdvance), + super::Limits::Battery(super::BatteryLimit::SteamDeckAdvance), + ] + }, super::Config { name: "Steam Deck".to_owned(), conditions: super::Conditions { @@ -21,6 +36,7 @@ impl Default for Base { cpuinfo: Some("model name\t: AMD Custom APU 0405\n".to_owned()), os: None, command: None, + file_exists: None, }, limits: vec![ super::Limits::Cpu(super::CpuLimit::SteamDeck), @@ -35,6 +51,7 @@ impl Default for Base { cpuinfo: None, os: None, command: None, + file_exists: None, }, limits: vec![ super::Limits::Cpu(super::CpuLimit::Unknown), diff --git a/backend/limits_core/src/json/conditions.rs b/backend/limits_core/src/json/conditions.rs index 2016cb9..e584c4a 100644 --- a/backend/limits_core/src/json/conditions.rs +++ b/backend/limits_core/src/json/conditions.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -/// Conditions under which a config applies +/// Conditions under which a config applies (ANDed together) #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Conditions { /// Regex pattern for dmidecode output @@ -11,6 +11,8 @@ pub struct Conditions { pub os: Option, /// Custom command to run, where an exit code of 0 means a successful match pub command: Option, + /// Check if file exists + pub file_exists: Option, } impl Conditions { diff --git a/backend/limits_srv/pt_limits.json b/backend/limits_srv/pt_limits.json index 4dcef89..7a4143a 100644 --- a/backend/limits_srv/pt_limits.json +++ b/backend/limits_srv/pt_limits.json @@ -1,5 +1,26 @@ { "configs": [ + { + "name": "Steam Deck Custom", + "conditions": { + "cpuinfo": "model name\t: AMD Custom APU 0405\n", + "file_exists": "./pt_oc.json" + }, + "limits": [ + { + "limits": "Cpu", + "target": "SteamDeck" + }, + { + "limits": "Gpu", + "target": "SteamDeck" + }, + { + "limits": "Battery", + "target": "SteamDeck" + } + ] + }, { "name": "Steam Deck", "conditions": { diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index 18a6fd2..5306d78 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -84,6 +84,10 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa Err(e) => log::warn!("Ignoring bash limits error: {}", e), } } + if let Some(file_exists) = &conditions.file_exists { + let exists = std::path::Path::new(file_exists).exists(); + matches &= exists; + } } if matches { if let Some(settings) = &settings_opt { @@ -92,7 +96,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa Limits::Cpu(cpus) => { let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), - CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::from_json(settings.cpus.clone(), settings.version)), + CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), }; @@ -101,7 +105,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa Limits::Gpu(gpu) => { let driver: Box = match gpu { GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), - GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::from_json(settings.gpu.clone(), settings.version)), + GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::from_json(settings.gpu.clone(), settings.version)), }; @@ -124,7 +128,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa Limits::Cpu(cpus) => { let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), - CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::system_default()), + CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), }; @@ -133,7 +137,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa Limits::Gpu(gpu) => { let driver: Box = match gpu { GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()), - GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::system_default()), + GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::system_default()), GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_limits(x)), GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::system_default()), }; diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index b637da4..e1d1b0e 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -40,6 +40,7 @@ impl Driver { gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), + // There's nothing special about SteamDeckAdvance, it just appears different DriverJson::SteamDeckAdvance => Ok(Self { general: Box::new(General { persistent: settings.persistent, @@ -47,8 +48,8 @@ impl Driver { name: settings.name, driver: DriverJson::SteamDeckAdvance, }), - cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)), + cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), + gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), DriverJson::Generic => Ok(Self { diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 68e5bd7..22a591f 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -7,7 +7,6 @@ mod traits; pub mod generic; pub mod steam_deck; -pub mod steam_deck_adv; pub mod unknown; pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn}; diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 13fe425..3732bee 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -1,15 +1,17 @@ use std::convert::Into; use crate::api::RangeLimit; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TBattery; use crate::persist::BatteryJson; use super::util::ChargeMode; +use super::oc_limits::{BatteryLimits, OverclockLimits}; #[derive(Debug, Clone)] pub struct Battery { pub charge_rate: Option, pub charge_mode: Option, + limits: BatteryLimits, state: crate::state::steam_deck::Battery, } @@ -24,15 +26,18 @@ const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_ impl Battery { #[inline] pub fn from_json(other: BatteryJson, version: u64) -> Self { + let oc_limits = OverclockLimits::load_or_default().battery; match version { 0 => Self { charge_rate: other.charge_rate, charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), + limits: oc_limits, state: crate::state::steam_deck::Battery::default(), }, _ => Self { charge_rate: other.charge_rate, charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), + limits: oc_limits, state: crate::state::steam_deck::Battery::default(), }, } @@ -68,7 +73,7 @@ impl Battery { )?; } else if self.state.charge_rate_set { self.state.charge_rate_set = false; - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, Self::max().charge_rate.unwrap()).map_err( + usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, self.limits.charge_rate.max).map_err( |e| SettingError { msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), setting: crate::settings::SettingVariant::Battery, @@ -96,10 +101,8 @@ impl Battery { } fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); if let Some(charge_rate) = &mut self.charge_rate { - *charge_rate = (*charge_rate).clamp(min.charge_rate.unwrap(), max.charge_rate.unwrap()); + *charge_rate = (*charge_rate).clamp(self.limits.charge_rate.min, self.limits.charge_rate.max); } } @@ -181,9 +184,11 @@ impl Battery { } pub fn system_default() -> Self { + let oc_limits = OverclockLimits::load_or_default().battery; Self { charge_rate: None, charge_mode: None, + limits: oc_limits, state: crate::state::steam_deck::Battery::default(), } } @@ -212,34 +217,12 @@ impl OnResume for Battery { } } -impl SettingsRange for Battery { - #[inline] - fn max() -> Self { - Self { - charge_rate: Some(2500), - charge_mode: None, - state: crate::state::steam_deck::Battery::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - charge_rate: Some(250), - charge_mode: None, - state: crate::state::steam_deck::Battery::default(), - } - } -} - impl TBattery for Battery { fn limits(&self) -> crate::api::BatteryLimits { - let max = Self::max(); - let min = Self::min(); crate::api::BatteryLimits { charge_current: Some(RangeLimit{ - min: min.charge_rate.unwrap(), - max: max.charge_rate.unwrap(), + min: self.limits.charge_rate.min, + max: self.limits.charge_rate.max }), charge_current_step: 50, charge_modes: vec!["normal".to_owned(), "discharge".to_owned(), "idle".to_owned()], diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 35f498b..9b78d62 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -2,9 +2,10 @@ use std::convert::Into; use crate::api::RangeLimit; use crate::settings::MinMax; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; use crate::persist::CpuJson; +use super::oc_limits::{OverclockLimits, CpusLimits, CpuLimits}; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; @@ -14,6 +15,8 @@ pub struct Cpus { pub cpus: Vec, pub smt: bool, pub smt_capable: bool, + #[allow(dead_code)] // in case this may be useful in the future + pub(super) limits: CpusLimits, } impl OnSet for Cpus { @@ -81,28 +84,32 @@ impl Cpus { } pub fn system_default() -> Self { + let oc_limits = OverclockLimits::load_or_default().cpus; if let Some(max_cpu) = Self::cpu_count() { let mut sys_cpus = Vec::with_capacity(max_cpu); for i in 0..max_cpu { - sys_cpus.push(Cpu::from_sys(i)); + sys_cpus.push(Cpu::from_sys(i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); } let (smt_status, can_smt) = Self::system_smt_capabilities(); Self { cpus: sys_cpus, smt: smt_status, smt_capable: can_smt, + limits: oc_limits, } } else { Self { cpus: vec![], smt: false, smt_capable: false, + limits: oc_limits, } } } #[inline] pub fn from_json(mut other: Vec, version: u64) -> Self { + let oc_limits = OverclockLimits::load_or_default().cpus; let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); @@ -113,7 +120,7 @@ impl Cpus { break; } } - result.push(Cpu::from_json(cpu, version, i)); + result.push(Cpu::from_json(cpu, version, i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); } if let Some(max_cpus) = max_cpus { if result.len() != max_cpus { @@ -127,6 +134,7 @@ impl Cpus { cpus: result, smt: true, smt_capable: can_smt, + limits: oc_limits, } } } @@ -166,6 +174,7 @@ pub struct Cpu { pub online: bool, pub clock_limits: Option>, pub governor: String, + limits: CpuLimits, index: usize, state: crate::state::steam_deck::Cpu, } @@ -175,12 +184,13 @@ const CPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force impl Cpu { #[inline] - pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { + fn from_json(other: CpuJson, version: u64, i: usize, oc_limits: CpuLimits) -> Self { match version { 0 => Self { online: other.online, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), governor: other.governor, + limits: oc_limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, @@ -188,6 +198,7 @@ impl Cpu { online: other.online, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), governor: other.governor, + limits: oc_limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, @@ -250,7 +261,7 @@ impl Cpu { // disable manual clock limits log::debug!("Setting CPU {} to default clockspeed", self.index); // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, Self::max().clock_limits.unwrap().max); + let payload_max = format!("p {} 1 {}\n", self.index / 2, self.limits.clock_max.max); usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( |e| SettingError { msg: format!( @@ -261,7 +272,7 @@ impl Cpu { }, )?; // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, Self::min().clock_limits.unwrap().min); + let payload_min = format!("p {} 0 {}\n", self.index / 2, self.limits.clock_min.min); usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( |e| SettingError { msg: format!( @@ -297,41 +308,33 @@ impl Cpu { } fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); if let Some(clock_limits) = &mut self.clock_limits { - let max_boost = max.clock_limits.as_ref().unwrap(); - let min_boost = min.clock_limits.as_ref().unwrap(); - clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); - clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); + clock_limits.min = clock_limits.min.clamp(self.limits.clock_min.min, self.limits.clock_min.max); + clock_limits.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max); } } - fn from_sys(cpu_index: usize) -> Self { + fn from_sys(cpu_index: usize, oc_limits: CpuLimits) -> Self { Self { online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, clock_limits: None, governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) .unwrap_or("schedutil".to_owned()), + limits: oc_limits, index: cpu_index, state: crate::state::steam_deck::Cpu::default(), } } fn limits(&self) -> crate::api::CpuLimits { - let max = Self::max(); - let max_clocks = max.clock_limits.unwrap(); - - let min = Self::min(); - let min_clocks = min.clock_limits.unwrap(); crate::api::CpuLimits { clock_min_limits: Some(RangeLimit { - min: min_clocks.min, - max: max_clocks.min + min: self.limits.clock_min.min, + max: self.limits.clock_min.max }), clock_max_limits: Some(RangeLimit { - min: min_clocks.max, - max: max_clocks.max + min: self.limits.clock_max.min, + max: self.limits.clock_max.max }), clock_step: 100, governors: self.governors(), @@ -404,33 +407,6 @@ impl TCpu for Cpu { } } -impl SettingsRange for Cpu { - #[inline] - fn max() -> Self { - Self { - online: true, - clock_limits: Some(MinMax { - max: 3500, - min: 3500, - }), - governor: "schedutil".to_owned(), - index: usize::MAX, - state: crate::state::steam_deck::Cpu::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - online: false, - clock_limits: Some(MinMax { max: 500, min: 1400 }), - governor: "schedutil".to_owned(), - index: usize::MIN, - state: crate::state::steam_deck::Cpu::default(), - } - } -} - #[inline] fn cpu_online_path(index: usize) -> String { format!("/sys/devices/system/cpu/cpu{}/online", index) diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 59827fe..99fce9c 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -2,9 +2,10 @@ use std::convert::Into; use crate::api::RangeLimit; use crate::settings::MinMax; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; +use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TGpu; use crate::persist::GpuJson; +use super::oc_limits::{OverclockLimits, GpuLimits}; const SLOW_PPT: u8 = 1; const FAST_PPT: u8 = 2; @@ -15,6 +16,7 @@ pub struct Gpu { pub slow_ppt: Option, pub clock_limits: Option>, pub slow_memory: bool, + limits: GpuLimits, state: crate::state::steam_deck::Gpu, } @@ -26,12 +28,14 @@ const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk impl Gpu { #[inline] pub fn from_json(other: GpuJson, version: u64) -> Self { + let oc_limits = OverclockLimits::load_or_default().gpu; match version { 0 => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), slow_memory: other.slow_memory, + limits: oc_limits, state: crate::state::steam_deck::Gpu::default(), }, _ => Self { @@ -39,6 +43,7 @@ impl Gpu { slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), slow_memory: other.slow_memory, + limits: oc_limits, state: crate::state::steam_deck::Gpu::default(), }, } @@ -120,7 +125,7 @@ impl Gpu { self.state.clock_limits_set = false; // disable manual clock limits // max clock - let payload_max = format!("s 1 {}\n", Self::max().clock_limits.unwrap().max); + let payload_max = format!("s 1 {}\n", self.limits.clock_max.max); usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( |e| SettingError { msg: format!( @@ -131,7 +136,7 @@ impl Gpu { }, )?; // min clock - let payload_min = format!("s 0 {}\n", Self::min().clock_limits.unwrap().min); + let payload_min = format!("s 0 {}\n", self.limits.clock_min.min); usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( |e| SettingError { msg: format!( @@ -154,34 +159,32 @@ impl Gpu { } fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); if let Some(fast_ppt) = &mut self.fast_ppt { *fast_ppt = (*fast_ppt).clamp( - *min.fast_ppt.as_ref().unwrap(), - *max.fast_ppt.as_ref().unwrap(), + self.limits.fast_ppt.min, + self.limits.fast_ppt.max, ); } if let Some(slow_ppt) = &mut self.slow_ppt { *slow_ppt = (*slow_ppt).clamp( - *min.slow_ppt.as_ref().unwrap(), - *max.slow_ppt.as_ref().unwrap(), + self.limits.slow_ppt.min, + self.limits.slow_ppt.max, ); } if let Some(clock_limits) = &mut self.clock_limits { - let max_boost = max.clock_limits.as_ref().unwrap(); - let min_boost = min.clock_limits.as_ref().unwrap(); - clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); - clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); + clock_limits.min = clock_limits.min.clamp(self.limits.clock_min.min, self.limits.clock_min.max); + clock_limits.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max); } } pub fn system_default() -> Self { + let oc_limits = OverclockLimits::load_or_default().gpu; Self { fast_ppt: None, slow_ppt: None, clock_limits: None, slow_memory: false, + limits: oc_limits, state: crate::state::steam_deck::Gpu::default(), } } @@ -214,62 +217,30 @@ impl OnResume for Gpu { } } -impl SettingsRange for Gpu { - #[inline] - fn max() -> Self { - Self { - fast_ppt: Some(30_000_000), - slow_ppt: Some(29_000_000), - clock_limits: Some(MinMax { - min: 1600, - max: 1600, - }), - slow_memory: false, - state: crate::state::steam_deck::Gpu::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - fast_ppt: Some(0), - slow_ppt: Some(1000000), - clock_limits: Some(MinMax { min: 200, max: 200 }), - slow_memory: true, - state: crate::state::steam_deck::Gpu::default(), - } - } -} - const PPT_DIVISOR: u64 = 1_000_000; impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { - let max = Self::max(); - let max_clock_limits = max.clock_limits.unwrap(); - - let min = Self::min(); - let min_clock_limits = min.clock_limits.unwrap(); crate::api::GpuLimits { fast_ppt_limits: Some(RangeLimit { - min: min.fast_ppt.unwrap() / PPT_DIVISOR, - max: max.fast_ppt.unwrap() / PPT_DIVISOR, + min: self.limits.fast_ppt.min / PPT_DIVISOR, + max: self.limits.fast_ppt.max / PPT_DIVISOR, }), slow_ppt_limits: Some(RangeLimit { - min: min.slow_ppt.unwrap() / PPT_DIVISOR, - max: max.slow_ppt.unwrap() / PPT_DIVISOR, + min: self.limits.slow_ppt.min / PPT_DIVISOR, + max: self.limits.slow_ppt.max / PPT_DIVISOR, }), ppt_step: 1, tdp_limits: None, tdp_boost_limits: None, tdp_step: 42, clock_min_limits: Some(RangeLimit { - min: min_clock_limits.min, - max: max_clock_limits.max, + min: self.limits.clock_min.min, + max: self.limits.clock_min.max, }), clock_max_limits: Some(RangeLimit { - min: min_clock_limits.min, - max: max_clock_limits.max, + min: self.limits.clock_max.min, + max: self.limits.clock_max.max, }), clock_step: 100, memory_control_capable: true, diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs index fb836a1..9c325b6 100644 --- a/backend/src/settings/steam_deck/mod.rs +++ b/backend/src/settings/steam_deck/mod.rs @@ -1,6 +1,7 @@ mod battery; mod cpu; mod gpu; +mod oc_limits; mod util; pub use battery::Battery; diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs new file mode 100644 index 0000000..f81bde1 --- /dev/null +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -0,0 +1,115 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub(super) struct MinMaxLimits { + pub min: T, + pub max: T, +} + +const OC_LIMITS_FILEPATH: &str = "./pt_oc.json"; + +#[derive(Serialize, Deserialize, Debug)] +pub(super) struct OverclockLimits { + pub battery: BatteryLimits, + pub cpus: CpusLimits, + pub gpu: GpuLimits, +} + +impl Default for OverclockLimits { + fn default() -> Self { + Self { + battery: BatteryLimits::default(), + cpus: CpusLimits::default(), + gpu: GpuLimits::default(), + } + } +} + +impl OverclockLimits { + pub fn load_or_default() -> Self { + let path = std::path::Path::new(OC_LIMITS_FILEPATH); + if path.exists() { + log::info!("Steam Deck limits file {} found", path.display()); + let mut file = match std::fs::File::open(&path) { + Ok(f) => f, + Err(e) => { + log::warn!("Steam Deck limits file {} err: {} (using default fallback)", path.display(), e); + return Self::default(); + }, + }; + match serde_json::from_reader(&mut file) { + Ok(result) => { + log::debug!("Steam Deck limits file {} successfully loaded", path.display()); + result + }, + Err(e) => { + log::warn!("Steam Deck limits file {} json err: {} (using default fallback)", path.display(), e); + Self::default() + } + } + } else { + log::info!("Steam Deck limits file {} not found (using default fallback)", path.display()); + Self::default() + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub(super) struct BatteryLimits { + pub charge_rate: MinMaxLimits, +} + +impl Default for BatteryLimits { + fn default() -> Self { + Self { + charge_rate: MinMaxLimits { min: 250, max: 2500 }, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub(super) struct CpusLimits { + pub cpus: Vec, +} + +impl Default for CpusLimits { + fn default() -> Self { + Self { + cpus: [(); 8].iter().map(|_| CpuLimits::default()).collect() + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub(super) struct CpuLimits { + pub clock_min: MinMaxLimits, + pub clock_max: MinMaxLimits, +} + +impl Default for CpuLimits { + fn default() -> Self { + Self { + clock_min: MinMaxLimits { min: 1400, max: 3500 }, + clock_max: MinMaxLimits { min: 500, max: 3500 } + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub(super) struct GpuLimits { + pub fast_ppt: MinMaxLimits, + pub slow_ppt: MinMaxLimits, + pub clock_min: MinMaxLimits, + pub clock_max: MinMaxLimits, +} + +impl Default for GpuLimits { + fn default() -> Self { + Self { + fast_ppt: MinMaxLimits { min: 1000000, max: 30_000_000 }, + slow_ppt: MinMaxLimits { min: 1000000, max: 29_000_000 }, + clock_min: MinMaxLimits { min: 200, max: 1600 }, + clock_max: MinMaxLimits { min: 200, max: 1600 } + } + } +} diff --git a/backend/src/settings/steam_deck_adv/cpu.rs b/backend/src/settings/steam_deck_adv/cpu.rs deleted file mode 100644 index 50e4f49..0000000 --- a/backend/src/settings/steam_deck_adv/cpu.rs +++ /dev/null @@ -1,428 +0,0 @@ -use std::convert::Into; - -use crate::api::RangeLimit; -use crate::settings::MinMax; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; -use crate::settings::{TCpus, TCpu}; -use crate::persist::CpuJson; - -const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; -const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; - -#[derive(Debug, Clone)] -pub struct Cpus { - pub cpus: Vec, - pub smt: bool, - pub smt_capable: bool, -} - -impl OnSet for Cpus { - fn on_set(&mut self) -> Result<(), SettingError> { - if self.smt_capable { - // toggle SMT - if self.smt { - usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { - SettingError { - msg: format!( - "Failed to write `on` to `{}`: {}", - CPU_SMT_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } else { - usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { - SettingError { - msg: format!( - "Failed to write `off` to `{}`: {}", - CPU_SMT_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } - } - for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { - cpu.state.do_set_online = self.smt || i % 2 == 0; - cpu.on_set()?; - } - Ok(()) - } -} - -impl OnResume for Cpus { - fn on_resume(&self) -> Result<(), SettingError> { - for cpu in &self.cpus { - cpu.on_resume()?; - } - Ok(()) - } -} - -impl Cpus { - pub fn cpu_count() -> Option { - let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) - .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); - if let Some(dash_index) = data.find('-') { - let data = data.split_off(dash_index + 1); - if let Ok(max_cpu) = data.parse::() { - return Some(max_cpu + 1); - } - } - log::warn!("Failed to parse CPU info from kernel, is Tux evil?"); - None - } - - fn system_smt_capabilities() -> (bool, bool) { - match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { - Ok(val) => (val.trim().to_lowercase() == "on", true), - Err(_) => (false, false) - } - } - - pub fn system_default() -> Self { - if let Some(max_cpu) = Self::cpu_count() { - let mut sys_cpus = Vec::with_capacity(max_cpu); - for i in 0..max_cpu { - sys_cpus.push(Cpu::from_sys(i)); - } - let (smt_status, can_smt) = Self::system_smt_capabilities(); - Self { - cpus: sys_cpus, - smt: smt_status, - smt_capable: can_smt, - } - } else { - Self { - cpus: vec![], - smt: false, - smt_capable: false, - } - } - } - - #[inline] - pub fn from_json(mut other: Vec, version: u64) -> Self { - let (_, can_smt) = Self::system_smt_capabilities(); - let mut result = Vec::with_capacity(other.len()); - let max_cpus = Self::cpu_count(); - for (i, cpu) in other.drain(..).enumerate() { - // prevent having more CPUs than available - if let Some(max_cpus) = max_cpus { - if i == max_cpus { - break; - } - } - result.push(Cpu::from_json(cpu, version, i)); - } - if let Some(max_cpus) = max_cpus { - if result.len() != max_cpus { - let mut sys_cpus = Cpus::system_default(); - for i in result.len()..sys_cpus.cpus.len() { - result.push(sys_cpus.cpus.remove(i)); - } - } - } - Self { - cpus: result, - smt: true, - smt_capable: can_smt, - } - } -} - -impl TCpus for Cpus { - fn limits(&self) -> crate::api::CpusLimits { - crate::api::CpusLimits { - cpus: self.cpus.iter().map(|x| x.limits()).collect(), - count: self.cpus.len(), - smt_capable: self.smt_capable, - } - } - - fn json(&self) -> Vec { - self.cpus.iter().map(|x| x.to_owned().into()).collect() - } - - fn cpus(&mut self) -> Vec<&mut dyn TCpu> { - self.cpus.iter_mut().map(|x| x as &mut dyn TCpu).collect() - } - - fn len(&self) -> usize { - self.cpus.len() - } - - fn smt(&mut self) -> &'_ mut bool { - &mut self.smt - } - - fn provider(&self) -> crate::persist::DriverJson { - crate::persist::DriverJson::SteamDeckAdvance - } -} - -#[derive(Debug, Clone)] -pub struct Cpu { - pub online: bool, - pub clock_limits: Option>, - pub governor: String, - index: usize, - state: crate::state::steam_deck::Cpu, -} - -const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; -const CPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; - -impl Cpu { - #[inline] - pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { - match version { - 0 => Self { - online: other.online, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), - governor: other.governor, - index: i, - state: crate::state::steam_deck::Cpu::default(), - }, - _ => Self { - online: other.online, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), - governor: other.governor, - index: i, - state: crate::state::steam_deck::Cpu::default(), - }, - } - } - - fn set_all(&mut self) -> Result<(), SettingError> { - // set cpu online/offline - if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled - let online_path = cpu_online_path(self.index); - usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { - SettingError { - msg: format!("Failed to write to `{}`: {}", &online_path, e), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } - // set clock limits - log::debug!("Setting {} to manual", CPU_FORCE_LIMITS_PATH); - let mode: String = usdpl_back::api::files::read_single(CPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); - if mode != "manual" { - // set manual control - usdpl_back::api::files::write_single(CPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { - SettingError { - msg: format!( - "Failed to write `manual` to `{}`: {}", - CPU_FORCE_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } - if let Some(clock_limits) = &self.clock_limits { - log::debug!("Setting CPU {} (min, max) clockspeed to ({}, {})", self.index, clock_limits.min, clock_limits.max); - self.state.clock_limits_set = true; - // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }, - )?; - // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, clock_limits.min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }, - )?; - } else if self.state.clock_limits_set || self.state.is_resuming { - self.state.clock_limits_set = false; - // disable manual clock limits - log::debug!("Setting CPU {} to default clockspeed", self.index); - // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, Self::max().clock_limits.unwrap().max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }, - )?; - // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, Self::min().clock_limits.unwrap().min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }, - )?; - } - // commit changes - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - SettingError { - msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - - // set governor - if self.index == 0 || self.online { - let governor_path = cpu_governor_path(self.index); - usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { - SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &self.governor, &governor_path, e - ), - setting: crate::settings::SettingVariant::Cpu, - } - })?; - } - Ok(()) - } - - fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); - if let Some(clock_limits) = &mut self.clock_limits { - let max_boost = max.clock_limits.as_ref().unwrap(); - let min_boost = min.clock_limits.as_ref().unwrap(); - clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); - clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); - } - } - - fn from_sys(cpu_index: usize) -> Self { - Self { - online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, - clock_limits: None, - governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) - .unwrap_or("schedutil".to_owned()), - index: cpu_index, - state: crate::state::steam_deck::Cpu::default(), - } - } - - fn limits(&self) -> crate::api::CpuLimits { - let max = Self::max(); - let max_clocks = max.clock_limits.unwrap(); - - let min = Self::min(); - let min_clocks = min.clock_limits.unwrap(); - crate::api::CpuLimits { - clock_min_limits: Some(RangeLimit { - min: min_clocks.min, - max: max_clocks.min - }), - clock_max_limits: Some(RangeLimit { - min: min_clocks.max, - max: max_clocks.max - }), - clock_step: 100, - governors: vec![], // TODO - } - } -} - -impl Into for Cpu { - #[inline] - fn into(self) -> CpuJson { - CpuJson { - online: self.online, - clock_limits: self.clock_limits.map(|x| x.into()), - governor: self.governor, - } - } -} - -impl OnSet for Cpu { - fn on_set(&mut self) -> Result<(), SettingError> { - self.clamp_all(); - self.set_all() - } -} - -impl OnResume for Cpu { - fn on_resume(&self) -> Result<(), SettingError> { - let mut copy = self.clone(); - copy.state.is_resuming = true; - copy.set_all() - } -} - -impl TCpu for Cpu { - fn online(&mut self) -> &mut bool { - &mut self.online - } - - fn governor(&mut self, governor: String) { - self.governor = governor; - } - - fn get_governor(&self) -> &'_ str { - &self.governor - } - - fn clock_limits(&mut self, limits: Option>) { - self.clock_limits = limits; - } - - fn get_clock_limits(&self) -> Option<&MinMax> { - self.clock_limits.as_ref() - } -} - -impl SettingsRange for Cpu { - #[inline] - fn max() -> Self { - Self { - online: true, - clock_limits: Some(MinMax { - max: 3500, - min: 3500, - }), - governor: "schedutil".to_owned(), - index: usize::MAX, - state: crate::state::steam_deck::Cpu::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - online: false, - clock_limits: Some(MinMax { max: 500, min: 1400 }), - governor: "schedutil".to_owned(), - index: usize::MIN, - state: crate::state::steam_deck::Cpu::default(), - } - } -} - -#[inline] -fn cpu_online_path(index: usize) -> String { - format!("/sys/devices/system/cpu/cpu{}/online", index) -} - -#[inline] -fn cpu_governor_path(index: usize) -> String { - format!( - "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor", - index - ) -} diff --git a/backend/src/settings/steam_deck_adv/gpu.rs b/backend/src/settings/steam_deck_adv/gpu.rs deleted file mode 100644 index 7ae25b8..0000000 --- a/backend/src/settings/steam_deck_adv/gpu.rs +++ /dev/null @@ -1,310 +0,0 @@ -use std::convert::Into; - -use crate::api::RangeLimit; -use crate::settings::MinMax; -use crate::settings::{OnResume, OnSet, SettingError, SettingsRange}; -use crate::settings::TGpu; -use crate::persist::GpuJson; - -const SLOW_PPT: u8 = 1; -const FAST_PPT: u8 = 2; - -#[derive(Debug, Clone)] -pub struct Gpu { - pub fast_ppt: Option, - pub slow_ppt: Option, - pub clock_limits: Option>, - pub slow_memory: bool, - state: crate::state::steam_deck::Gpu, -} - -// same as CPU -const GPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; -const GPU_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; -const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk"; - -impl Gpu { - #[inline] - pub fn from_json(other: GpuJson, version: u64) -> Self { - match version { - 0 => Self { - fast_ppt: other.fast_ppt, - slow_ppt: other.slow_ppt, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), - slow_memory: other.slow_memory, - state: crate::state::steam_deck::Gpu::default(), - }, - _ => Self { - fast_ppt: other.fast_ppt, - slow_ppt: other.slow_ppt, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), - slow_memory: other.slow_memory, - state: crate::state::steam_deck::Gpu::default(), - }, - } - } - - fn set_all(&mut self) -> Result<(), SettingError> { - // set fast PPT - if let Some(fast_ppt) = &self.fast_ppt { - let fast_ppt_path = gpu_power_path(FAST_PPT); - usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt).map_err(|e| { - SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - fast_ppt, &fast_ppt_path, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // set slow PPT - if let Some(slow_ppt) = &self.slow_ppt { - let slow_ppt_path = gpu_power_path(SLOW_PPT); - usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt).map_err(|e| { - SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - slow_ppt, &slow_ppt_path, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // settings using force_performance_level - let mode: String = usdpl_back::api::files::read_single(GPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); - if mode != "manual" { - // set manual control - usdpl_back::api::files::write_single(GPU_FORCE_LIMITS_PATH, "manual").map_err(|e| { - SettingError { - msg: format!( - "Failed to write `manual` to `{}`: {}", - GPU_FORCE_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - } - // enable/disable downclock of GPU memory (to 400Mhz?) - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - })?; - if let Some(clock_limits) = &self.clock_limits { - // set clock limits - self.state.clock_limits_set = true; - // max clock - let payload_max = format!("s 1 {}\n", clock_limits.max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }, - )?; - // min clock - let payload_min = format!("s 0 {}\n", clock_limits.min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }, - )?; - } else if self.state.clock_limits_set || self.state.is_resuming { - self.state.clock_limits_set = false; - // disable manual clock limits - // max clock - let payload_max = format!("s 1 {}\n", Self::max().clock_limits.unwrap().max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }, - )?; - // min clock - let payload_min = format!("s 0 {}\n", Self::min().clock_limits.unwrap().min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( - |e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }, - )?; - } - // commit changes - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - SettingError { - msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - } - })?; - - Ok(()) - } - - fn clamp_all(&mut self) { - let min = Self::min(); - let max = Self::max(); - if let Some(fast_ppt) = &mut self.fast_ppt { - *fast_ppt = (*fast_ppt).clamp( - *min.fast_ppt.as_ref().unwrap(), - *max.fast_ppt.as_ref().unwrap(), - ); - } - if let Some(slow_ppt) = &mut self.slow_ppt { - *slow_ppt = (*slow_ppt).clamp( - *min.slow_ppt.as_ref().unwrap(), - *max.slow_ppt.as_ref().unwrap(), - ); - } - if let Some(clock_limits) = &mut self.clock_limits { - let max_boost = max.clock_limits.as_ref().unwrap(); - let min_boost = min.clock_limits.as_ref().unwrap(); - clock_limits.min = clock_limits.min.clamp(min_boost.min, max_boost.min); - clock_limits.max = clock_limits.max.clamp(min_boost.max, max_boost.max); - } - } - - pub fn system_default() -> Self { - Self { - fast_ppt: None, - slow_ppt: None, - clock_limits: None, - slow_memory: false, - state: crate::state::steam_deck::Gpu::default(), - } - } -} - -impl Into for Gpu { - #[inline] - fn into(self) -> GpuJson { - GpuJson { - fast_ppt: self.fast_ppt, - slow_ppt: self.slow_ppt, - clock_limits: self.clock_limits.map(|x| x.into()), - slow_memory: self.slow_memory, - } - } -} - -impl OnSet for Gpu { - fn on_set(&mut self) -> Result<(), SettingError> { - self.clamp_all(); - self.set_all() - } -} - -impl OnResume for Gpu { - fn on_resume(&self) -> Result<(), SettingError> { - let mut copy = self.clone(); - copy.state.is_resuming = true; - copy.set_all() - } -} - -impl SettingsRange for Gpu { - #[inline] - fn max() -> Self { - Self { - fast_ppt: Some(30_000_000), - slow_ppt: Some(29_000_000), - clock_limits: Some(MinMax { - min: 1600, - max: 1600, - }), - slow_memory: false, - state: crate::state::steam_deck::Gpu::default(), - } - } - - #[inline] - fn min() -> Self { - Self { - fast_ppt: Some(0), - slow_ppt: Some(1000000), - clock_limits: Some(MinMax { min: 200, max: 200 }), - slow_memory: true, - state: crate::state::steam_deck::Gpu::default(), - } - } -} - -impl TGpu for Gpu { - fn limits(&self) -> crate::api::GpuLimits { - let max = Self::max(); - let max_clock_limits = max.clock_limits.unwrap(); - - let min = Self::min(); - let min_clock_limits = min.clock_limits.unwrap(); - crate::api::GpuLimits { - fast_ppt_limits: Some(RangeLimit { - min: min.fast_ppt.unwrap(), - max: max.fast_ppt.unwrap(), - }), - slow_ppt_limits: Some(RangeLimit { - min: min.slow_ppt.unwrap(), - max: max.slow_ppt.unwrap(), - }), - ppt_step: 1_000_000, - tdp_limits: None, - tdp_boost_limits: None, - tdp_step: 42, - clock_min_limits: Some(RangeLimit { - min: min_clock_limits.min, - max: max_clock_limits.max, - }), - clock_max_limits: Some(RangeLimit { - min: min_clock_limits.min, - max: max_clock_limits.max, - }), - clock_step: 100, - memory_control_capable: true, - } - } - - fn json(&self) -> crate::persist::GpuJson { - self.clone().into() - } - - fn ppt(&mut self, fast: Option, slow: Option) { - self.fast_ppt = fast; - self.slow_ppt = slow; - } - - fn get_ppt(&self) -> (Option, Option) { - (self.fast_ppt, self.slow_ppt) - } - - fn clock_limits(&mut self, limits: Option>) { - self.clock_limits = limits; - } - - fn get_clock_limits(&self) -> Option<&MinMax> { - self.clock_limits.as_ref() - } - - fn slow_memory(&mut self) -> &mut bool { - &mut self.slow_memory - } - - fn provider(&self) -> crate::persist::DriverJson { - crate::persist::DriverJson::SteamDeckAdvance - } -} - -#[inline] -fn gpu_power_path(power_number: u8) -> String { - format!("/sys/class/hwmon/hwmon4/power{}_cap", power_number) -} diff --git a/backend/src/settings/steam_deck_adv/mod.rs b/backend/src/settings/steam_deck_adv/mod.rs deleted file mode 100644 index 4a6bb90..0000000 --- a/backend/src/settings/steam_deck_adv/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//mod battery; -mod cpu; -mod gpu; - -//pub use battery::Battery; -pub use cpu::{Cpu, Cpus}; -pub use gpu::Gpu; From 3031a1c9bfa8e06b3f15ba189fc654f1b6d2b44b Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 31 Dec 2022 16:28:37 -0500 Subject: [PATCH 18/44] Groundwork for RyzenAdj and fix some system defaults --- backend/limits_core/src/json/conditions.rs | 6 +- backend/limits_core/src/json/cpu_limit.rs | 7 +- backend/limits_core/src/json/gpu_limit.rs | 12 +- backend/limits_core/src/json/mod.rs | 2 + backend/limits_core/src/json/range.rs | 8 ++ backend/src/api/api_types.rs | 7 + backend/src/persist/driver.rs | 2 + backend/src/settings/detect/auto_detect.rs | 4 + backend/src/settings/driver.rs | 14 +- backend/src/settings/generic/battery.rs | 19 ++- backend/src/settings/generic/cpu.rs | 130 ++++++++++--------- backend/src/settings/generic/gpu.rs | 32 +++-- backend/src/settings/generic_amd/cpu.rs | 91 +++++++++++++ backend/src/settings/generic_amd/gpu.rs | 72 ++++++++++ backend/src/settings/generic_amd/mod.rs | 5 + backend/src/settings/min_max.rs | 21 ++- backend/src/settings/mod.rs | 3 +- backend/src/settings/steam_deck/cpu.rs | 17 ++- backend/src/settings/steam_deck/gpu.rs | 6 +- backend/src/settings/steam_deck/oc_limits.rs | 35 +++-- backend/src/settings/unknown/cpu.rs | 7 +- 21 files changed, 356 insertions(+), 144 deletions(-) create mode 100644 backend/limits_core/src/json/range.rs create mode 100644 backend/src/settings/generic_amd/cpu.rs create mode 100644 backend/src/settings/generic_amd/gpu.rs create mode 100644 backend/src/settings/generic_amd/mod.rs diff --git a/backend/limits_core/src/json/conditions.rs b/backend/limits_core/src/json/conditions.rs index e584c4a..be08a1c 100644 --- a/backend/limits_core/src/json/conditions.rs +++ b/backend/limits_core/src/json/conditions.rs @@ -17,6 +17,10 @@ pub struct Conditions { impl Conditions { pub fn is_empty(&self) -> bool { - self.dmi.is_none() && self.cpuinfo.is_none() && self.os.is_none() && self.command.is_none() + self.dmi.is_none() + && self.cpuinfo.is_none() + && self.os.is_none() + && self.command.is_none() + && self.file_exists.is_none() } } diff --git a/backend/limits_core/src/json/cpu_limit.rs b/backend/limits_core/src/json/cpu_limit.rs index d413cda..053ef29 100644 --- a/backend/limits_core/src/json/cpu_limit.rs +++ b/backend/limits_core/src/json/cpu_limit.rs @@ -1,15 +1,20 @@ use serde::{Deserialize, Serialize}; +use super::RangeLimit; + #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(tag = "target")] pub enum CpuLimit { SteamDeck, SteamDeckAdvance, Generic(GenericCpuLimit), + GenericAMD(GenericCpuLimit), Unknown, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct GenericCpuLimit { - /* TODO */ + pub clock_min: Option>, + pub clock_max: Option>, + pub clock_step: u64, } diff --git a/backend/limits_core/src/json/gpu_limit.rs b/backend/limits_core/src/json/gpu_limit.rs index 712b8b1..be77676 100644 --- a/backend/limits_core/src/json/gpu_limit.rs +++ b/backend/limits_core/src/json/gpu_limit.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use super::RangeLimit; #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(tag = "target")] @@ -6,10 +7,19 @@ pub enum GpuLimit { SteamDeck, SteamDeckAdvance, Generic(GenericGpuLimit), + GenericAMD(GenericGpuLimit), Unknown, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct GenericGpuLimit { - /* TODO */ + pub fast_ppt: Option>, + pub slow_ppt: Option>, + pub ppt_step: Option, + pub tdp: Option>, + pub tdp_boost: Option>, + pub tdp_step: Option, + pub clock_min: Option>, + pub clock_max: Option>, + pub clock_step: Option, } diff --git a/backend/limits_core/src/json/mod.rs b/backend/limits_core/src/json/mod.rs index 250e218..73047bc 100644 --- a/backend/limits_core/src/json/mod.rs +++ b/backend/limits_core/src/json/mod.rs @@ -5,6 +5,7 @@ mod config; mod cpu_limit; mod gpu_limit; mod limits; +mod range; mod target; pub use base::Base; @@ -14,4 +15,5 @@ pub use cpu_limit::{CpuLimit, GenericCpuLimit}; pub use gpu_limit::{GpuLimit, GenericGpuLimit}; pub use config::Config; pub use limits::Limits; +pub use range::RangeLimit; pub use target::Target; diff --git a/backend/limits_core/src/json/range.rs b/backend/limits_core/src/json/range.rs new file mode 100644 index 0000000..2ea3718 --- /dev/null +++ b/backend/limits_core/src/json/range.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +/// Base JSON limits information +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct RangeLimit { + pub min: T, + pub max: T, +} diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index 0be7136..f70c69a 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -6,6 +6,13 @@ pub struct RangeLimit { pub max: T, } +impl From> for RangeLimit { + #[inline] + fn from(other: limits_core::json::RangeLimit) -> Self { + RangeLimit { min: other.min, max: other.max } + } +} + #[derive(Serialize, Deserialize)] pub struct SettingsLimits { pub battery: BatteryLimits, diff --git a/backend/src/persist/driver.rs b/backend/src/persist/driver.rs index f1486b5..1a774bd 100644 --- a/backend/src/persist/driver.rs +++ b/backend/src/persist/driver.rs @@ -10,6 +10,8 @@ pub enum DriverJson { SteamDeckAdvance, #[serde(rename = "generic")] Generic, + #[serde(rename = "generic-amd")] + GenericAMD, #[serde(rename = "unknown")] Unknown, #[default] diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index 5306d78..e7fb679 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -98,6 +98,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), + CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), }; builder.cpus = Some(cpu_driver); @@ -107,6 +108,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), + GpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::from_json(settings.gpu.clone(), settings.version)), }; builder.gpu = Some(driver); @@ -130,6 +132,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)), + CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_limits(x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), }; builder.cpus = Some(cpu_driver); @@ -139,6 +142,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()), GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::system_default()), GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_limits(x)), + GpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Gpu::from_limits(x)), GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::system_default()), }; builder.gpu = Some(driver); diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index e1d1b0e..59deec3 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -52,17 +52,7 @@ impl Driver { gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), }), - DriverJson::Generic => Ok(Self { - general: Box::new(General { - persistent: settings.persistent, - path: json_path, - name: settings.name, - driver: DriverJson::Unknown, - }), - cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)), - gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)), - battery: Box::new(super::generic::Battery), - }), + DriverJson::Generic | DriverJson::GenericAMD => Ok(super::detect::auto_detect0(Some(settings), json_path)), DriverJson::Unknown => Ok(super::detect::auto_detect0(Some(settings), json_path)), DriverJson::AutoDetect => Ok(super::detect::auto_detect0(Some(settings), json_path)), } @@ -83,7 +73,7 @@ pub fn maybe_do_button() { DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => { crate::settings::steam_deck::flash_led(); }, - DriverJson::Generic => log::warn!("You need to come up with something fun on generic"), + DriverJson::Generic | DriverJson::GenericAMD => log::warn!("You need to come up with something fun on generic"), DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), DriverJson::AutoDetect => log::warn!("WTF, why is auto_detect detecting AutoDetect???") } diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index bd300b7..1ca4cc6 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -1,11 +1,16 @@ use std::convert::Into; +use limits_core::json::GenericBatteryLimit; + use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TBattery; use crate::persist::BatteryJson; #[derive(Debug, Clone)] -pub struct Battery; +pub struct Battery { + #[allow(dead_code)] + limits: GenericBatteryLimit, +} impl Into for Battery { #[inline] @@ -39,14 +44,18 @@ impl Battery { } } - pub fn from_limits(_limits: limits_core::json::GenericBatteryLimit) -> Self { + pub fn from_limits(limits: limits_core::json::GenericBatteryLimit) -> Self { // TODO - Self + Self { + limits + } } - pub fn from_json_and_limits(_other: BatteryJson, _version: u64, _limits: limits_core::json::GenericBatteryLimit) -> Self { + pub fn from_json_and_limits(_other: BatteryJson, _version: u64, limits: limits_core::json::GenericBatteryLimit) -> Self { // TODO - Self + Self { + limits + } } } diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 568b40f..f1df70e 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -1,5 +1,7 @@ use std::convert::Into; +use limits_core::json::GenericCpuLimit; + use crate::settings::MinMax; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; @@ -42,7 +44,7 @@ impl OnSet for Cpus { } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { - cpu.state.do_set_online = self.smt || i % 2 == 0; + cpu.state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; cpu.on_set()?; } Ok(()) @@ -79,69 +81,26 @@ impl Cpus { } } - pub fn system_default() -> Self { - if let Some(max_cpu) = Self::cpu_count() { - let mut sys_cpus = Vec::with_capacity(max_cpu); - for i in 0..max_cpu { - sys_cpus.push(Cpu::from_sys(i)); - } - let (smt_status, can_smt) = Self::system_smt_capabilities(); - Self { - cpus: sys_cpus, - smt: smt_status, - smt_capable: can_smt, - } - } else { - Self { - cpus: vec![], - smt: false, - smt_capable: false, - } - } - } - - #[inline] - pub fn from_json(mut other: Vec, version: u64) -> Self { + pub fn from_limits(limits: limits_core::json::GenericCpuLimit) -> Self { + let cpu_count = Self::cpu_count().unwrap_or(8); let (_, can_smt) = Self::system_smt_capabilities(); - let mut result = Vec::with_capacity(other.len()); - let max_cpus = Self::cpu_count(); - for (i, cpu) in other.drain(..).enumerate() { - // prevent having more CPUs than available - if let Some(max_cpus) = max_cpus { - if i == max_cpus { - break; - } - } - result.push(Cpu::from_json(cpu, version, i)); - } - if let Some(max_cpus) = max_cpus { - if result.len() != max_cpus { - let mut sys_cpus = Cpus::system_default(); - for i in result.len()..sys_cpus.cpus.len() { - result.push(sys_cpus.cpus.remove(i)); - } - } + let mut new_cpus = Vec::with_capacity(cpu_count); + for i in 0..cpu_count { + let new_cpu = Cpu::from_limits(i, limits.clone()); + new_cpus.push(new_cpu); } Self { - cpus: result, + cpus: new_cpus, smt: true, smt_capable: can_smt, } } - pub fn from_limits(_limits: limits_core::json::GenericCpuLimit) -> Self { - // TODO - Self { - cpus: vec![], - smt: false, - smt_capable: false, - } - } - - pub fn from_json_and_limits(mut other: Vec, version: u64, _limits: limits_core::json::GenericCpuLimit) -> Self { + pub fn from_json_and_limits(mut other: Vec, version: u64, limits: limits_core::json::GenericCpuLimit) -> Self { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); + let mut smt_disabled = false; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -149,11 +108,13 @@ impl Cpus { break; } } - result.push(Cpu::from_json(cpu, version, i)); + let new_cpu = Cpu::from_json_and_limits(cpu, version, i, limits.clone()); + smt_disabled &= new_cpu.online as usize != i % 2; + result.push(new_cpu); } if let Some(max_cpus) = max_cpus { if result.len() != max_cpus { - let mut sys_cpus = Cpus::system_default(); + let mut sys_cpus = Cpus::from_limits(limits.clone()); for i in result.len()..sys_cpus.cpus.len() { result.push(sys_cpus.cpus.remove(i)); } @@ -161,7 +122,7 @@ impl Cpus { } Self { cpus: result, - smt: true, + smt: !smt_disabled, smt_capable: can_smt, } } @@ -201,6 +162,7 @@ impl TCpus for Cpus { pub struct Cpu { pub online: bool, pub governor: String, + limits: GenericCpuLimit, index: usize, state: crate::state::steam_deck::Cpu, } @@ -208,17 +170,30 @@ pub struct Cpu { impl Cpu { #[inline] - pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { + pub fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self { + Self { + online: true, + governor: "schedutil".to_owned(), + limits, + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } + } + + #[inline] + pub fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { match version { 0 => Self { online: other.online, governor: other.governor, + limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, _ => Self { online: other.online, governor: other.governor, + limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, @@ -253,7 +228,7 @@ impl Cpu { Ok(()) } - fn from_sys(cpu_index: usize) -> Self { + /*fn from_sys(cpu_index: usize) -> Self { Self { online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) @@ -261,14 +236,31 @@ impl Cpu { index: cpu_index, state: crate::state::steam_deck::Cpu::default(), } + }*/ + + fn governors(&self) -> Vec { + // NOTE: this eats errors + let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { + Ok(s) => s, + Err((Some(e), None)) => { + log::warn!("Error getting available CPU governors: {}", e); + return vec![]; + }, + Err((None, Some(e))) => { + log::warn!("Error getting available CPU governors: {}", e); + return vec![]; + }, + Err(_) => return vec![], + }; + gov_str.split(' ').map(|s| s.to_owned()).collect() } fn limits(&self) -> crate::api::CpuLimits { crate::api::CpuLimits { - clock_min_limits: None, - clock_max_limits: None, - clock_step: 100, - governors: vec![], // TODO + clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), + clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_step: self.limits.clock_step, + governors: self.governors(), } } } @@ -312,11 +304,13 @@ impl TCpu for Cpu { &self.governor } - fn clock_limits(&mut self, _limits: Option>) { + fn clock_limits(&mut self, limits: Option>) { + self.limits.clock_min = limits.clone(); + self.limits.clock_max = limits.clone(); } fn get_clock_limits(&self) -> Option<&MinMax> { - None + self.limits.clock_max.as_ref() } } @@ -332,3 +326,11 @@ fn cpu_governor_path(index: usize) -> String { index ) } + +#[inline] +fn cpu_available_governors_path(index: usize) -> String { + format!( + "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_available_governors", + index + ) +} diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 3344915..5a92bfd 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -1,5 +1,7 @@ use std::convert::Into; +use limits_core::json::GenericGpuLimit; + use crate::settings::MinMax; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TGpu; @@ -8,15 +10,16 @@ use crate::persist::GpuJson; #[derive(Debug, Clone)] pub struct Gpu { slow_memory: bool, // ignored + limits: GenericGpuLimit, } impl Gpu { - #[inline] + /*#[inline] pub fn from_json(_other: GpuJson, _version: u64) -> Self { Self { slow_memory: false, } - } + }*/ /*pub fn system_default() -> Self { Self { @@ -24,16 +27,17 @@ impl Gpu { } }*/ - pub fn from_limits(_limits: limits_core::json::GenericGpuLimit) -> Self { - // TODO + pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, + limits, } } - pub fn from_json_and_limits(_other: GpuJson, _version: u64, _limits: limits_core::json::GenericGpuLimit) -> Self { + pub fn from_json_and_limits(_other: GpuJson, _version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, + limits, } } } @@ -65,15 +69,15 @@ impl OnResume for Gpu { impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { crate::api::GpuLimits { - fast_ppt_limits: None, - slow_ppt_limits: None, - ppt_step: 1_000_000, - tdp_limits: None, - tdp_boost_limits: None, - tdp_step: 42, - clock_min_limits: None, - clock_max_limits: None, - clock_step: 100, + fast_ppt_limits: self.limits.fast_ppt.clone().map(|x| x.into()), + slow_ppt_limits: self.limits.slow_ppt.clone().map(|x| x.into()), + ppt_step: self.limits.ppt_step.unwrap_or(1_000_000), + tdp_limits: self.limits.tdp.clone().map(|x| x.into()), + tdp_boost_limits: self.limits.tdp_boost.clone().map(|x| x.into()), + tdp_step: self.limits.tdp_step.unwrap_or(42), + clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), + clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_step: self.limits.clock_step.unwrap_or(100), memory_control_capable: false, } } diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs new file mode 100644 index 0000000..312f8e3 --- /dev/null +++ b/backend/src/settings/generic_amd/cpu.rs @@ -0,0 +1,91 @@ +use crate::persist::CpuJson; +use crate::settings::MinMax; +use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus}; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{TCpus, TCpu}; + +#[derive(Debug)] +pub struct Cpus { + generic: GenericCpus, +} + +impl Cpus { + pub fn from_limits(limits: limits_core::json::GenericCpuLimit) -> Self { + Self { + generic: GenericCpus::from_limits(limits), + } + } + + pub fn from_json_and_limits(other: Vec, version: u64, limits: limits_core::json::GenericCpuLimit) -> Self { + Self { + generic: GenericCpus::from_json_and_limits(other, version, limits), + } + } +} + +impl OnResume for Cpus { + fn on_resume(&self) -> Result<(), SettingError> { + self.generic.on_resume() + // TODO + } +} + +impl OnSet for Cpus { + fn on_set(&mut self) -> Result<(), SettingError> { + self.generic.on_set() + // TODO + } +} + +impl TCpus for Cpus { + fn limits(&self) -> crate::api::CpusLimits { + self.generic.limits() + } + + fn json(&self) -> Vec { + self.generic.json() // TODO + } + + fn cpus(&mut self) -> Vec<&mut dyn TCpu> { + self.generic.cpus() // TODO + } + + fn len(&self) -> usize { + self.generic.len() // TODO + } + + fn smt(&mut self) -> &'_ mut bool { + self.generic.smt() + } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::GenericAMD + } +} + +#[derive(Debug)] +pub struct Cpu { + generic: GenericCpu, +} + +impl TCpu for Cpu { + fn online(&mut self) -> &mut bool { + self.generic.online() + } + + fn governor(&mut self, governor: String) { + self.generic.governor(governor) + } + + fn get_governor(&self) -> &'_ str { + self.generic.get_governor() + } + + fn clock_limits(&mut self, limits: Option>) { + self.generic.clock_limits(limits) // TODO + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.generic.get_clock_limits() // TODO + } +} diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs new file mode 100644 index 0000000..18f8b94 --- /dev/null +++ b/backend/src/settings/generic_amd/gpu.rs @@ -0,0 +1,72 @@ +use crate::persist::GpuJson; +use crate::settings::MinMax; +use crate::settings::generic::Gpu as GenericGpu; +use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::TGpu; + +#[derive(Debug)] +pub struct Gpu { + generic: GenericGpu, +} + +impl Gpu { + pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { + Self { + generic: GenericGpu::from_limits(limits), + } + } + + pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { + Self { + generic: GenericGpu::from_json_and_limits(other, version, limits), + } + } +} + +impl OnResume for Gpu { + fn on_resume(&self) -> Result<(), SettingError> { + self.generic.on_resume() + // TODO + } +} + +impl OnSet for Gpu { + fn on_set(&mut self) -> Result<(), SettingError> { + self.generic.on_set() + // TODO + } +} + +impl TGpu for Gpu { + fn limits(&self) -> crate::api::GpuLimits { + self.generic.limits() + } + + fn json(&self) -> crate::persist::GpuJson { + self.generic.json() + } + + fn ppt(&mut self, fast: Option, slow: Option) { + // TODO + } + + fn get_ppt(&self) -> (Option, Option) { + self.generic.get_ppt() // TODO + } + + fn clock_limits(&mut self, limits: Option>) { + // TODO + } + + fn get_clock_limits(&self) -> Option<&MinMax> { + self.generic.get_clock_limits() + } + + fn slow_memory(&mut self) -> &mut bool { + self.generic.slow_memory() + } + + fn provider(&self) -> crate::persist::DriverJson { + crate::persist::DriverJson::GenericAMD + } +} diff --git a/backend/src/settings/generic_amd/mod.rs b/backend/src/settings/generic_amd/mod.rs new file mode 100644 index 0000000..6a8e412 --- /dev/null +++ b/backend/src/settings/generic_amd/mod.rs @@ -0,0 +1,5 @@ +mod cpu; +mod gpu; + +pub use cpu::{Cpu, Cpus}; +pub use gpu::Gpu; diff --git a/backend/src/settings/min_max.rs b/backend/src/settings/min_max.rs index 00ea8fd..c1c9563 100644 --- a/backend/src/settings/min_max.rs +++ b/backend/src/settings/min_max.rs @@ -1,24 +1,19 @@ use std::convert::Into; +use limits_core::json::RangeLimit; + use crate::persist::MinMaxJson; -#[derive(Debug, Clone)] -pub struct MinMax { - pub max: T, - pub min: T, -} +pub type MinMax = RangeLimit; -impl MinMax { - #[inline] - pub fn from_json>(other: MinMaxJson, _version: u64) -> Self { - Self { - max: other.max.into(), - min: other.min.into(), - } +pub fn min_max_from_json>(other: MinMaxJson, _version: u64) -> MinMax { + MinMax { + max: other.max.into(), + min: other.min.into(), } } -impl, Y> Into> for MinMax { +impl, Y> Into> for RangeLimit { #[inline] fn into(self) -> MinMaxJson { MinMaxJson { diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 22a591f..a24b57e 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -6,13 +6,14 @@ mod min_max; mod traits; pub mod generic; +pub mod generic_amd; pub mod steam_deck; pub mod unknown; pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn}; pub use driver::Driver; pub use general::{SettingVariant, Settings, General}; -pub use min_max::MinMax; +pub use min_max::{MinMax, min_max_from_json}; pub use error::SettingError; pub use traits::{OnResume, OnSet, SettingsRange, TGeneral, TGpu, TCpus, TBattery, TCpu}; diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 9b78d62..f1b33b8 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -1,7 +1,7 @@ use std::convert::Into; use crate::api::RangeLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; use crate::persist::CpuJson; @@ -90,10 +90,10 @@ impl Cpus { for i in 0..max_cpu { sys_cpus.push(Cpu::from_sys(i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); } - let (smt_status, can_smt) = Self::system_smt_capabilities(); + let (_, can_smt) = Self::system_smt_capabilities(); Self { cpus: sys_cpus, - smt: smt_status, + smt: true, smt_capable: can_smt, limits: oc_limits, } @@ -113,6 +113,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); + let mut smt_disabled = false; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -120,7 +121,9 @@ impl Cpus { break; } } - result.push(Cpu::from_json(cpu, version, i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); + let new_cpu = Cpu::from_json(cpu, version, i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default()); + smt_disabled &= new_cpu.online as usize != i % 2; + result.push(new_cpu); } if let Some(max_cpus) = max_cpus { if result.len() != max_cpus { @@ -132,7 +135,7 @@ impl Cpus { } Self { cpus: result, - smt: true, + smt: !smt_disabled, smt_capable: can_smt, limits: oc_limits, } @@ -188,7 +191,7 @@ impl Cpu { match version { 0 => Self { online: other.online, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), governor: other.governor, limits: oc_limits, index: i, @@ -196,7 +199,7 @@ impl Cpu { }, _ => Self { online: other.online, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), governor: other.governor, limits: oc_limits, index: i, diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 99fce9c..9e77ba8 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -1,7 +1,7 @@ use std::convert::Into; use crate::api::RangeLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TGpu; use crate::persist::GpuJson; @@ -33,7 +33,7 @@ impl Gpu { 0 => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), slow_memory: other.slow_memory, limits: oc_limits, state: crate::state::steam_deck::Gpu::default(), @@ -41,7 +41,7 @@ impl Gpu { _ => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, - clock_limits: other.clock_limits.map(|x| MinMax::from_json(x, version)), + clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), slow_memory: other.slow_memory, limits: oc_limits, state: crate::state::steam_deck::Gpu::default(), diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index f81bde1..9712831 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -1,10 +1,5 @@ use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub(super) struct MinMaxLimits { - pub min: T, - pub max: T, -} +use crate::settings::MinMax; const OC_LIMITS_FILEPATH: &str = "./pt_oc.json"; @@ -56,13 +51,13 @@ impl OverclockLimits { #[derive(Serialize, Deserialize, Clone, Debug)] pub(super) struct BatteryLimits { - pub charge_rate: MinMaxLimits, + pub charge_rate: MinMax, } impl Default for BatteryLimits { fn default() -> Self { Self { - charge_rate: MinMaxLimits { min: 250, max: 2500 }, + charge_rate: MinMax { min: 250, max: 2500 }, } } } @@ -82,34 +77,34 @@ impl Default for CpusLimits { #[derive(Serialize, Deserialize, Clone, Debug)] pub(super) struct CpuLimits { - pub clock_min: MinMaxLimits, - pub clock_max: MinMaxLimits, + pub clock_min: MinMax, + pub clock_max: MinMax, } impl Default for CpuLimits { fn default() -> Self { Self { - clock_min: MinMaxLimits { min: 1400, max: 3500 }, - clock_max: MinMaxLimits { min: 500, max: 3500 } + clock_min: MinMax { min: 1400, max: 3500 }, + clock_max: MinMax { min: 500, max: 3500 } } } } #[derive(Serialize, Deserialize, Clone, Debug)] pub(super) struct GpuLimits { - pub fast_ppt: MinMaxLimits, - pub slow_ppt: MinMaxLimits, - pub clock_min: MinMaxLimits, - pub clock_max: MinMaxLimits, + pub fast_ppt: MinMax, + pub slow_ppt: MinMax, + pub clock_min: MinMax, + pub clock_max: MinMax, } impl Default for GpuLimits { fn default() -> Self { Self { - fast_ppt: MinMaxLimits { min: 1000000, max: 30_000_000 }, - slow_ppt: MinMaxLimits { min: 1000000, max: 29_000_000 }, - clock_min: MinMaxLimits { min: 200, max: 1600 }, - clock_max: MinMaxLimits { min: 200, max: 1600 } + fast_ppt: MinMax { min: 1000000, max: 30_000_000 }, + slow_ppt: MinMax { min: 1000000, max: 29_000_000 }, + clock_min: MinMax { min: 200, max: 1600 }, + clock_max: MinMax { min: 200, max: 1600 } } } } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 2e677ba..76982f4 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -105,6 +105,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); + let mut smt_disabled = false; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -112,7 +113,9 @@ impl Cpus { break; } } - result.push(Cpu::from_json(cpu, version, i)); + let new_cpu = Cpu::from_json(cpu, version, i); + smt_disabled &= new_cpu.online as usize != i % 2; + result.push(new_cpu); } if let Some(max_cpus) = max_cpus { if result.len() != max_cpus { @@ -124,7 +127,7 @@ impl Cpus { } Self { cpus: result, - smt: true, + smt: !smt_disabled, smt_capable: can_smt, } } From 5614937012362066caafcc05808cd67059e84414 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 2 Jan 2023 09:04:07 -0500 Subject: [PATCH 19/44] Implement full generic driver to simplify custom implementations --- backend/Cargo.lock | 129 +++++++++++++++++++++ backend/Cargo.toml | 1 + backend/src/settings/detect/auto_detect.rs | 4 +- backend/src/settings/generic/cpu.rs | 75 ++++++++---- backend/src/settings/generic/gpu.rs | 43 +++++-- backend/src/settings/generic/mod.rs | 2 + backend/src/settings/generic/traits.rs | 8 ++ backend/src/settings/generic_amd/cpu.rs | 50 +++++++- backend/src/settings/generic_amd/gpu.rs | 6 +- 9 files changed, 278 insertions(+), 40 deletions(-) create mode 100644 backend/src/settings/generic/traits.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 290e4a9..4a85e0f 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -102,6 +102,28 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -149,6 +171,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -170,6 +201,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -217,6 +259,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -323,6 +371,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "h2" version = "0.3.15" @@ -481,12 +535,34 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "limits_core" version = "0.1.0" @@ -526,6 +602,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -565,6 +647,16 @@ dependencies = [ "twoway", ] +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num_cpus" version = "1.14.0" @@ -602,6 +694,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.2.0" @@ -660,6 +758,7 @@ dependencies = [ "limits_core", "log", "regex", + "ryzenadj-rs", "serde", "serde_json", "simplelog", @@ -763,6 +862,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustls-pemfile" version = "0.2.1" @@ -778,6 +883,13 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "ryzenadj-rs" +version = "0.1.0" +dependencies = [ + "bindgen", +] + [[package]] name = "safemem" version = "0.3.3" @@ -855,6 +967,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "simplelog" version = "0.12.0" @@ -1265,6 +1383,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index fab0846..8f8daec 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -21,6 +21,7 @@ simplelog = "0.12" # limits & driver functionality limits_core = { version = "0.1.0", path = "./limits_core" } regex = "1" +ryzenadj-rs = { version = "0.1", path = "../../ryzenadj-rs" } # ureq's tls feature does not like musl targets ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index e7fb679..a85e6a5 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -97,7 +97,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), - CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), }; @@ -131,7 +131,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::system_default()), - CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::::from_limits(x)), CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_limits(x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), }; diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index f1df70e..fcf90c9 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -1,23 +1,24 @@ -use std::convert::Into; +use std::convert::{Into, AsMut, AsRef}; use limits_core::json::GenericCpuLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; use crate::persist::CpuJson; +use super::FromGenericCpuInfo; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; #[derive(Debug, Clone)] -pub struct Cpus { - pub cpus: Vec, +pub struct Cpus + AsRef + TCpu> { + pub cpus: Vec, pub smt: bool, pub smt_capable: bool, } -impl OnSet for Cpus { +impl + AsRef + TCpu + OnSet> OnSet for Cpus { fn on_set(&mut self) -> Result<(), SettingError> { if self.smt_capable { // toggle SMT @@ -44,14 +45,14 @@ impl OnSet for Cpus { } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { - cpu.state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; + cpu.as_mut().state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; cpu.on_set()?; } Ok(()) } } -impl OnResume for Cpus { +impl + AsRef + TCpu + OnResume> OnResume for Cpus { fn on_resume(&self) -> Result<(), SettingError> { for cpu in &self.cpus { cpu.on_resume()?; @@ -60,7 +61,7 @@ impl OnResume for Cpus { } } -impl Cpus { +impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { pub fn cpu_count() -> Option { let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); @@ -86,7 +87,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut new_cpus = Vec::with_capacity(cpu_count); for i in 0..cpu_count { - let new_cpu = Cpu::from_limits(i, limits.clone()); + let new_cpu = C::from_limits(i, limits.clone()); new_cpus.push(new_cpu); } Self { @@ -108,8 +109,8 @@ impl Cpus { break; } } - let new_cpu = Cpu::from_json_and_limits(cpu, version, i, limits.clone()); - smt_disabled &= new_cpu.online as usize != i % 2; + let mut new_cpu = C::from_json_and_limits(cpu, version, i, limits.clone()); + smt_disabled &= *new_cpu.online() as usize != i % 2; result.push(new_cpu); } if let Some(max_cpus) = max_cpus { @@ -128,17 +129,17 @@ impl Cpus { } } -impl TCpus for Cpus { +impl + AsRef + TCpu + OnResume + OnSet> TCpus for Cpus { fn limits(&self) -> crate::api::CpusLimits { crate::api::CpusLimits { - cpus: self.cpus.iter().map(|x| x.limits()).collect(), + cpus: self.cpus.iter().map(|x| x.as_ref().limits()).collect(), count: self.cpus.len(), smt_capable: self.smt_capable, } } fn json(&self) -> Vec { - self.cpus.iter().map(|x| x.to_owned().into()).collect() + self.cpus.iter().map(|x| x.as_ref().to_owned().into()).collect() } fn cpus(&mut self) -> Vec<&mut dyn TCpu> { @@ -162,18 +163,40 @@ impl TCpus for Cpus { pub struct Cpu { pub online: bool, pub governor: String, + pub clock_limits: Option>, limits: GenericCpuLimit, index: usize, state: crate::state::steam_deck::Cpu, } - impl Cpu { #[inline] - pub fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self { + pub fn index(&self) -> usize { + self.index + } +} + +impl AsRef for Cpu { + #[inline] + fn as_ref(&self) -> &Cpu { + self + } +} + +impl AsMut for Cpu { + #[inline] + fn as_mut(&mut self) -> &mut Cpu { + self + } +} + +impl FromGenericCpuInfo for Cpu { + #[inline] + fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self { Self { online: true, governor: "schedutil".to_owned(), + clock_limits: None, limits, index: cpu_index, state: crate::state::steam_deck::Cpu::default(), @@ -181,11 +204,17 @@ impl Cpu { } #[inline] - pub fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { + fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { + let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { + other.clock_limits.map(|x| min_max_from_json(x, version)) + } else { + None + }; match version { 0 => Self { online: other.online, governor: other.governor, + clock_limits: clock_lims, limits, index: i, state: crate::state::steam_deck::Cpu::default(), @@ -193,13 +222,16 @@ impl Cpu { _ => Self { online: other.online, governor: other.governor, + clock_limits: clock_lims, limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, } } +} +impl Cpu { fn set_all(&mut self) -> Result<(), SettingError> { // set cpu online/offline if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled @@ -270,7 +302,7 @@ impl Into for Cpu { fn into(self) -> CpuJson { CpuJson { online: self.online, - clock_limits: None, + clock_limits: self.clock_limits.map(|x| x.into()), governor: self.governor, } } @@ -305,12 +337,13 @@ impl TCpu for Cpu { } fn clock_limits(&mut self, limits: Option>) { - self.limits.clock_min = limits.clone(); - self.limits.clock_max = limits.clone(); + if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { + self.clock_limits = limits; + } } fn get_clock_limits(&self) -> Option<&MinMax> { - self.limits.clock_max.as_ref() + self.clock_limits.as_ref() } } diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 5a92bfd..aa1a111 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -2,14 +2,17 @@ use std::convert::Into; use limits_core::json::GenericGpuLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TGpu; use crate::persist::GpuJson; #[derive(Debug, Clone)] pub struct Gpu { - slow_memory: bool, // ignored + slow_memory: bool, + fast_ppt: Option, + slow_ppt: Option, + clock_limits: Option>, limits: GenericGpuLimit, } @@ -30,13 +33,24 @@ impl Gpu { pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, + fast_ppt: None, + slow_ppt: None, + clock_limits: None, limits, } } - pub fn from_json_and_limits(_other: GpuJson, _version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { + pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { + let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { + other.clock_limits.map(|x| min_max_from_json(x, version)) + } else { + None + }; Self { slow_memory: false, + fast_ppt: if limits.fast_ppt.is_some() {other.fast_ppt} else {None}, + slow_ppt: if limits.slow_ppt.is_some() {other.slow_ppt} else {None}, + clock_limits: clock_lims, limits, } } @@ -46,9 +60,9 @@ impl Into for Gpu { #[inline] fn into(self) -> GpuJson { GpuJson { - fast_ppt: None, - slow_ppt: None, - clock_limits: None, + fast_ppt: self.fast_ppt, + slow_ppt: self.slow_ppt, + clock_limits: self.clock_limits.map(|x| x.into()), slow_memory: false, } } @@ -86,18 +100,27 @@ impl TGpu for Gpu { self.clone().into() } - fn ppt(&mut self, _fast: Option, _slow: Option) { + fn ppt(&mut self, fast: Option, slow: Option) { + if self.limits.fast_ppt.is_some() { + self.fast_ppt = fast; + } + if self.limits.slow_ppt.is_some() { + self.slow_ppt = slow; + } } fn get_ppt(&self) -> (Option, Option) { - (None, None) + (self.fast_ppt, self.slow_ppt) } - fn clock_limits(&mut self, _limits: Option>) { + fn clock_limits(&mut self, limits: Option>) { + if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { + self.clock_limits = limits; + } } fn get_clock_limits(&self) -> Option<&MinMax> { - None + self.clock_limits.as_ref() } fn slow_memory(&mut self) -> &mut bool { diff --git a/backend/src/settings/generic/mod.rs b/backend/src/settings/generic/mod.rs index 2039cae..6989a23 100644 --- a/backend/src/settings/generic/mod.rs +++ b/backend/src/settings/generic/mod.rs @@ -1,7 +1,9 @@ mod battery; mod cpu; mod gpu; +mod traits; pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; +pub use traits::FromGenericCpuInfo; diff --git a/backend/src/settings/generic/traits.rs b/backend/src/settings/generic/traits.rs new file mode 100644 index 0000000..bf51e7f --- /dev/null +++ b/backend/src/settings/generic/traits.rs @@ -0,0 +1,8 @@ +use limits_core::json::GenericCpuLimit; +use crate::persist::CpuJson; + +pub trait FromGenericCpuInfo { + fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self; + + fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: GenericCpuLimit) -> Self; +} diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs index 312f8e3..e698c72 100644 --- a/backend/src/settings/generic_amd/cpu.rs +++ b/backend/src/settings/generic_amd/cpu.rs @@ -1,12 +1,12 @@ use crate::persist::CpuJson; use crate::settings::MinMax; -use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus}; +use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; #[derive(Debug)] pub struct Cpus { - generic: GenericCpus, + generic: GenericCpus, } impl Cpus { @@ -68,6 +68,48 @@ pub struct Cpu { generic: GenericCpu, } +impl FromGenericCpuInfo for Cpu { + fn from_limits(cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { + let gen = GenericCpu::from_limits(cpu_index, limits.clone()); + Self { + generic: gen, + } + } + + fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { + let gen = GenericCpu::from_json_and_limits(other, version, cpu_index, limits); + Self { + generic: gen, + } + } +} + +impl AsRef for Cpu { + fn as_ref(&self) -> &GenericCpu { + &self.generic + } +} + +impl AsMut for Cpu { + fn as_mut(&mut self) -> &mut GenericCpu { + &mut self.generic + } +} + +impl OnResume for Cpu { + fn on_resume(&self) -> Result<(), SettingError> { + self.generic.on_resume() + // TODO + } +} + +impl OnSet for Cpu { + fn on_set(&mut self) -> Result<(), SettingError> { + self.generic.on_set() + // TODO + } +} + impl TCpu for Cpu { fn online(&mut self) -> &mut bool { self.generic.online() @@ -82,10 +124,10 @@ impl TCpu for Cpu { } fn clock_limits(&mut self, limits: Option>) { - self.generic.clock_limits(limits) // TODO + self.generic.clock_limits(limits) } fn get_clock_limits(&self) -> Option<&MinMax> { - self.generic.get_clock_limits() // TODO + self.generic.get_clock_limits() } } diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 18f8b94..8c9654c 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -47,15 +47,15 @@ impl TGpu for Gpu { } fn ppt(&mut self, fast: Option, slow: Option) { - // TODO + self.generic.ppt(fast, slow) } fn get_ppt(&self) -> (Option, Option) { - self.generic.get_ppt() // TODO + self.generic.get_ppt() } fn clock_limits(&mut self, limits: Option>) { - // TODO + self.generic.clock_limits(limits) } fn get_clock_limits(&self) -> Option<&MinMax> { From 500fde964ca8692602220bfcdfb3607eae06fcb6 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 2 Jan 2023 18:47:14 -0500 Subject: [PATCH 20/44] Implement RyzenAdj driver for AMD --- backend/src/settings/generic/cpu.rs | 4 +- backend/src/settings/generic/gpu.rs | 26 ++-- backend/src/settings/generic_amd/cpu.rs | 5 +- backend/src/settings/generic_amd/gpu.rs | 153 +++++++++++++++++++++++- backend/src/state/generic/gpu.rs | 16 +++ backend/src/state/generic/mod.rs | 3 + backend/src/state/mod.rs | 1 + 7 files changed, 189 insertions(+), 19 deletions(-) create mode 100644 backend/src/state/generic/gpu.rs create mode 100644 backend/src/state/generic/mod.rs diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index fcf90c9..a2fe995 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -169,12 +169,12 @@ pub struct Cpu { state: crate::state::steam_deck::Cpu, } -impl Cpu { +/*impl Cpu { #[inline] pub fn index(&self) -> usize { self.index } -} +}*/ impl AsRef for Cpu { #[inline] diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index aa1a111..7e658a4 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -9,10 +9,10 @@ use crate::persist::GpuJson; #[derive(Debug, Clone)] pub struct Gpu { - slow_memory: bool, - fast_ppt: Option, - slow_ppt: Option, - clock_limits: Option>, + pub slow_memory: bool, + pub fast_ppt: Option, + pub slow_ppt: Option, + pub clock_limits: Option>, limits: GenericGpuLimit, } @@ -101,11 +101,11 @@ impl TGpu for Gpu { } fn ppt(&mut self, fast: Option, slow: Option) { - if self.limits.fast_ppt.is_some() { - self.fast_ppt = fast; + if let Some(fast_lims) = &self.limits.fast_ppt { + self.fast_ppt = fast.map(|x| x.clamp(fast_lims.min, fast_lims.max)); } - if self.limits.slow_ppt.is_some() { - self.slow_ppt = slow; + if let Some(slow_lims) = &self.limits.slow_ppt { + self.slow_ppt = slow.map(|x| x.clamp(slow_lims.min, slow_lims.max)); } } @@ -114,8 +114,14 @@ impl TGpu for Gpu { } fn clock_limits(&mut self, limits: Option>) { - if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { - self.clock_limits = limits; + if let Some(clock_min) = &self.limits.clock_min { + if let Some(clock_max) = &self.limits.clock_max { + self.clock_limits = limits.map(|mut x| { + x.min = x.min.clamp(clock_min.min, clock_min.max); + x.max = x.max.clamp(clock_max.max, clock_max.max); + x + }); + } } } diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs index e698c72..74f5c5b 100644 --- a/backend/src/settings/generic_amd/cpu.rs +++ b/backend/src/settings/generic_amd/cpu.rs @@ -123,8 +123,9 @@ impl TCpu for Cpu { self.generic.get_governor() } - fn clock_limits(&mut self, limits: Option>) { - self.generic.clock_limits(limits) + fn clock_limits(&mut self, _limits: Option>) { + //self.generic.clock_limits(limits) + // TODO: support this } fn get_clock_limits(&self) -> Option<&MinMax> { diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 8c9654c..ca4dffe 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -1,39 +1,182 @@ +use std::sync::Mutex; +use ryzenadj_rs::RyzenAccess; + use crate::persist::GpuJson; use crate::settings::MinMax; use crate::settings::generic::Gpu as GenericGpu; -use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{OnResume, OnSet, SettingError, SettingVariant}; use crate::settings::TGpu; +fn ryzen_adj_or_log() -> Option> { + match RyzenAccess::new() { + Ok(x) => Some(Mutex::new(x)), + Err(e) => { + log::error!("RyzenAdj init error: {}", e); + None + } + } +} + #[derive(Debug)] pub struct Gpu { generic: GenericGpu, + implementor: Option>, + state: crate::state::generic::Gpu, // NOTE this is re-used for simplicity } impl Gpu { pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { Self { generic: GenericGpu::from_limits(limits), + implementor: ryzen_adj_or_log(), + state: Default::default(), } } pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { Self { generic: GenericGpu::from_json_and_limits(other, version, limits), + implementor: ryzen_adj_or_log(), + state: Default::default(), + } + } + + fn set_all(&mut self) -> Result<(), SettingError> { + let mutex = match &self.implementor { + Some(x) => x, + None => { + return Err(SettingError { + msg: "RyzenAdj unavailable".to_owned(), + setting: SettingVariant::Gpu, + }); + } + }; + let lock = match mutex.lock() { + Ok(x) => x, + Err(e) => { + return Err(SettingError { + msg: format!("RyzenAdj lock acquire failed: {}", e), + setting: SettingVariant::Gpu, + }); + } + }; + if let Some(fast_ppt) = &self.generic.fast_ppt { + if self.state.old_fast_ppt.is_none() { + self.state.old_fast_ppt = Some(lock.get_fast_value() as _); + } + lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), + setting: SettingVariant::Gpu, + })?; + } else if let Some(fast_ppt) = &self.state.old_fast_ppt { + lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), + setting: SettingVariant::Gpu, + })?; + self.state.old_fast_ppt = None; + } + if let Some(slow_ppt) = &self.generic.slow_ppt { + if self.state.old_slow_ppt.is_none() { + self.state.old_slow_ppt = Some(lock.get_slow_value() as _); + } + lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), + setting: SettingVariant::Gpu, + })?; + } else if let Some(slow_ppt) = &self.state.old_slow_ppt { + lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), + setting: SettingVariant::Gpu, + })?; + self.state.old_slow_ppt = None; + } + if let Some(clock_limits) = &self.generic.clock_limits { + self.state.clock_limits_set = true; + lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e), + setting: SettingVariant::Gpu, + })?; + lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e), + setting: SettingVariant::Gpu, + })?; + } else if self.state.clock_limits_set { + self.state.clock_limits_set = false; + let limits = self.generic.limits(); + if let Some(min_limits) = limits.clock_min_limits { + if let Some(max_limits) = limits.clock_max_limits { + lock.set_max_gfxclk_freq(max_limits.max as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max_limits.max, e), + setting: SettingVariant::Gpu, + })?; + lock.set_min_gfxclk_freq(min_limits.min as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min_limits.min, e), + setting: SettingVariant::Gpu, + })?; + } + } + } + Ok(()) + } + + fn resume_all(&self) -> Result<(), SettingError> { + // like set_all() but without updating state + // -- assumption: state is already up to date + let mutex = match &self.implementor { + Some(x) => x, + None => { + return Err(SettingError { + msg: "RyzenAdj unavailable".to_owned(), + setting: SettingVariant::Gpu, + }); + } + }; + let lock = match mutex.lock() { + Ok(x) => x, + Err(e) => { + return Err(SettingError { + msg: format!("RyzenAdj lock acquire failed: {}", e), + setting: SettingVariant::Gpu, + }); + } + }; + if let Some(fast_ppt) = &self.generic.fast_ppt { + lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), + setting: SettingVariant::Gpu, + })?; + } + if let Some(slow_ppt) = &self.generic.slow_ppt { + lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), + setting: SettingVariant::Gpu, + })?; + } + if let Some(clock_limits) = &self.generic.clock_limits { + lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e), + setting: SettingVariant::Gpu, + })?; + lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e), + setting: SettingVariant::Gpu, + })?; } + Ok(()) } } impl OnResume for Gpu { fn on_resume(&self) -> Result<(), SettingError> { - self.generic.on_resume() - // TODO + self.generic.on_resume()?; + self.resume_all() } } impl OnSet for Gpu { fn on_set(&mut self) -> Result<(), SettingError> { - self.generic.on_set() - // TODO + self.generic.on_set()?; + self.set_all() } } diff --git a/backend/src/state/generic/gpu.rs b/backend/src/state/generic/gpu.rs new file mode 100644 index 0000000..51e0909 --- /dev/null +++ b/backend/src/state/generic/gpu.rs @@ -0,0 +1,16 @@ +#[derive(Debug, Clone)] +pub struct Gpu { + pub clock_limits_set: bool, + pub old_fast_ppt: Option, + pub old_slow_ppt: Option, +} + +impl std::default::Default for Gpu { + fn default() -> Self { + Self { + clock_limits_set: false, + old_fast_ppt: None, + old_slow_ppt: None, + } + } +} diff --git a/backend/src/state/generic/mod.rs b/backend/src/state/generic/mod.rs new file mode 100644 index 0000000..d91c88c --- /dev/null +++ b/backend/src/state/generic/mod.rs @@ -0,0 +1,3 @@ +mod gpu; + +pub use gpu::Gpu; diff --git a/backend/src/state/mod.rs b/backend/src/state/mod.rs index 72ca58f..570de60 100644 --- a/backend/src/state/mod.rs +++ b/backend/src/state/mod.rs @@ -1,6 +1,7 @@ mod error; mod traits; +pub mod generic; pub mod steam_deck; pub use error::StateError; From cda1111cd33a3c0be50b76f023d2ab056f136737 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 2 Jan 2023 21:22:53 -0500 Subject: [PATCH 21/44] Add driver in debug UI and misc config stuff --- backend/Cargo.lock | 2 + backend/Cargo.toml | 2 +- backend/Dockerfile | 4 +- backend/src/api/general.rs | 29 ++++++++ backend/src/api/handler.rs | 9 +++ backend/src/main.rs | 4 ++ src/backend.ts | 4 ++ src/index.tsx | 9 +++ src/python.ts | 139 ------------------------------------- 9 files changed, 61 insertions(+), 141 deletions(-) delete mode 100644 src/python.ts diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 4a85e0f..01c9e77 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -886,6 +886,8 @@ checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "ryzenadj-rs" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc77f2824d9c46759ba4907c8d3c3ca7131593a41fc389335bcdfda339a866bd" dependencies = [ "bindgen", ] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 8f8daec..c289281 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -21,7 +21,7 @@ simplelog = "0.12" # limits & driver functionality limits_core = { version = "0.1.0", path = "./limits_core" } regex = "1" -ryzenadj-rs = { version = "0.1", path = "../../ryzenadj-rs" } +ryzenadj-rs = { version = "0.1" } # ureq's tls feature does not like musl targets ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } diff --git a/backend/Dockerfile b/backend/Dockerfile index f1a0ed3..94a2a88 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,3 +1,5 @@ FROM ghcr.io/steamdeckhomebrew/holo-toolchain-rust:latest -ENTRYPOINT [ "/backend/entrypoint.sh" ] \ No newline at end of file +RUN pacman -S --noconfirm cmake make + +ENTRYPOINT [ "/backend/entrypoint.sh" ] diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index 32e040b..309203d 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -178,6 +178,35 @@ pub fn get_limits( } } +/// Generate get current driver name +pub fn get_provider( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move |provider_name: String| { + let (tx, rx) = mpsc::channel(); + let callback = move |name: crate::persist::DriverJson| tx.send(name).expect("get_provider callback send failed"); + sender2.lock().unwrap().send(ApiMessage::GetProvider(provider_name, Box::new(callback))).expect("get_provider send failed"); + rx.recv().expect("get_provider callback recv failed") + } + }; + super::async_utils::AsyncIsh { + trans_setter: |mut params| { + if let Some(Primitive::String(name)) = params.pop() { + Ok(name.to_owned()) + } else { + Err(format!("Invalid/missing single param in get_provider")) + } + }, + set_get: getter, + trans_getter: |result| { + vec![format!("{:?}", result).into()] + } + } +} + pub fn gunter(_: super::ApiParameterType) -> super::ApiParameterType { std::thread::spawn(|| { log::info!("Zhu Li, do the thing!"); diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index cd77ed3..a1a9354 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -17,6 +17,7 @@ pub enum ApiMessage { LoadMainSettings, LoadSystemSettings, GetLimits(Callback), + GetProvider(String, Callback), } pub enum BatteryMessage { @@ -221,6 +222,14 @@ impl ApiMessageHandler { gpu: settings.gpu.limits(), general: settings.general.limits(), }); + }, + ApiMessage::GetProvider(name, cb) => { + cb(match &name as &str { + "battery" => settings.battery.provider(), + "cpu" | "cpus" => settings.cpus.provider(), + "gpu" => settings.gpu.provider(), + _ => settings.general.provider(), + }) } } } diff --git a/backend/src/main.rs b/backend/src/main.rs index e949d30..8390b97 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -212,6 +212,10 @@ fn main() -> Result<(), ()> { "GENERAL_get_limits", api::general::get_limits(api_sender.clone()) ) + .register_async( + "GENERAL_get_provider", + api::general::get_provider(api_sender.clone()) + ) .register("GENERAL_idk", api::general::gunter); api_worker::spawn(loaded_settings, api_handler); diff --git a/src/backend.ts b/src/backend.ts index d736630..53a1c9d 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -227,6 +227,10 @@ export async function getLimits(): Promise { return (await call_backend("GENERAL_get_limits", []))[0]; } +export async function getDriverProviderName(name: string): Promise { + return (await call_backend("GENERAL_get_provider", [name]))[0]; +} + export async function idk(): Promise { return (await call_backend("GENERAL_idk", []))[0]; } diff --git a/src/index.tsx b/src/index.tsx index 0391718..b804bcd 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -46,6 +46,7 @@ type MinMax = { // usdpl persistent store keys const BACKEND_INFO = "VINFO"; +const DRIVER_INFO = "GENERAL_provider"; const LIMITS_INFO = "LIMITS_all"; @@ -144,6 +145,7 @@ const reload = function() { backend.resolve(backend.getGeneralSettingsName(), (name: string) => { set_value(NAME_GEN, name) }); backend.resolve(backend.getInfo(), (info: string) => { set_value(BACKEND_INFO, info) }); + backend.resolve(backend.getDriverProviderName("gpu"), (driver: string) => { set_value(DRIVER_INFO, driver) }); }; // init USDPL WASM and connection to back-end @@ -842,6 +844,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {eggCount % 10 == 9 ? "<3 <3 <3" : target_usdpl()} + + eggCount++}> + {eggCount % 10 == 9 ? "Tracy Chapman" : get_value(DRIVER_INFO)} + + , setter: any) { - (async function () { - let data = await promise; - if (data.success) { - console.debug("Got resolved", data, "promise", promise); - setter(data.result); - } else { - console.warn("Resolve failed:", data, "promise", promise); - } - })(); -} - -export function execute(promise: Promise) { - (async function () { - let data = await promise; - if (data.success) { - console.debug("Got executed", data, "promise", promise); - } else { - console.warn("Execute failed:", data, "promise", promise); - } - - })(); -} - -export function setServer(s: ServerAPI) { - server = s; -} - -// Python functions -export function getVersion(): Promise { - return server!.callPluginMethod("get_version", {}); -} - -export function onViewReady(): Promise { - return server!.callPluginMethod("on_ready", {}); -} - -export function setCPUs(value: number, smt: boolean): Promise { - return server!.callPluginMethod("set_cpus", {"count":value, "smt": smt}); -} - -export function getCPUs(): Promise { - return server!.callPluginMethod("get_cpus", {}); -} - -export function getSMT(): Promise { - return server!.callPluginMethod("get_smt", {}); -} - -export function setCPUBoost(value: boolean): Promise { - return server!.callPluginMethod("set_boost", {"enabled": value}); -} - -export function getCPUBoost(): Promise { - return server!.callPluginMethod("get_boost", {}); -} - -export function setMaxBoost(index: number): Promise { - return server!.callPluginMethod("set_max_boost", {"index": index}); -} - -export function getMaxBoost(): Promise { - return server!.callPluginMethod("get_max_boost", {}); -} - -export function setGPUPower(value: number, index: number): Promise { - return server!.callPluginMethod("set_gpu_power", {"value": value, "power_number": index}); -} - -export function getGPUPower(index: number): Promise { - return server!.callPluginMethod("get_gpu_power", {"power_number": index}); -} - -export function setGPUPowerI(value: number, index: number): Promise { - return server!.callPluginMethod("set_gpu_power_index", {"index": value, "power_number": index}); -} - -export function getGPUPowerI(index: number): Promise { - return server!.callPluginMethod("get_gpu_power_index", {"power_number": index}); -} - -export function setFanTick(tick: number): Promise { - return server!.callPluginMethod("set_fan_tick", {"tick": tick}); -} - -export function getFanTick(): Promise { - return server!.callPluginMethod("get_fan_tick", {}); -} - -export function getFantastic(): Promise { - return server!.callPluginMethod("fantastic_installed", {}); -} - -export function getChargeNow(): Promise { - return server!.callPluginMethod("get_charge_now", {}); -} - -export function getChargeFull(): Promise { - return server!.callPluginMethod("get_charge_full", {}); -} - -export function getChargeDesign(): Promise { - return server!.callPluginMethod("get_charge_design", {}); -} - -export function setPersistent(value: boolean): Promise { - return server!.callPluginMethod("set_persistent", {"enabled": value}); -} - -export function getPersistent(): Promise { - return server!.callPluginMethod("get_persistent", {}); -} - -export function setPerGameProfile(value: boolean): Promise { - return server!.callPluginMethod("set_per_game_profile", {"enabled": value}); -} - -export function getPerGameProfile(): Promise { - return server!.callPluginMethod("get_per_game_profile", {}); -} - -export function getCurrentGame(): Promise { - return server!.callPluginMethod("get_current_game", {}); -} - -export function onGameStart(gameId: number, data: any): Promise { - const data2 = {appid: data.appid, display_name: data.display_name, gameid: gameId}; // Issue #17 - return server!.callPluginMethod("on_game_start", {"game_id": gameId, "data":data2}); -} - -export function onGameStop(gameId: number | null): Promise { - return server!.callPluginMethod("on_game_stop", {"game_id": gameId}); -} From 13bf31611d88b25c1e82239f579eb373abb5cfd1 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Wed, 4 Jan 2023 19:42:59 -0500 Subject: [PATCH 22/44] Send front-end logs to back and improve Steam Deck driver display --- backend/src/api/general.rs | 33 ++++++++++++ backend/src/main.rs | 1 + backend/src/settings/steam_deck/battery.rs | 14 +++-- backend/src/settings/steam_deck/cpu.rs | 14 +++-- backend/src/settings/steam_deck/gpu.rs | 17 +++--- backend/src/settings/steam_deck/oc_limits.rs | 11 ++-- src/backend.ts | 13 +++++ src/index.tsx | 54 ++++++++++---------- 8 files changed, 113 insertions(+), 44 deletions(-) diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index 309203d..aae871b 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -215,3 +215,36 @@ pub fn gunter(_: super::ApiParameterType) -> super::ApiParameterType { }); vec![true.into()] } + +/// API web method to send log messages to the back-end log, callable from the front-end +pub fn log_it() -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { + move |params| { + if let Some(Primitive::F64(level)) = params.get(0) { + if let Some(Primitive::String(msg)) = params.get(1) { + log_msg_by_level(*level as u8, msg); + vec![true.into()] + } else if let Some(Primitive::Json(msg)) = params.get(1) { + log_msg_by_level(*level as u8, msg); + vec![true.into()] + } else { + log::warn!("Got log_it call with wrong/missing 2nd parameter"); + vec![false.into()] + } + } else { + log::warn!("Got log_it call with wrong/missing 1st parameter"); + vec![false.into()] + } + } +} + +fn log_msg_by_level(level: u8, msg: &str) { + match level { + 1 => log::trace!("FRONT-END: {}", msg), + 2 => log::debug!("FRONT-END: {}", msg), + 3 => log::info!("FRONT-END: {}", msg), + 4 => log::warn!("FRONT-END: {}", msg), + 5 => log::error!("FRONT-END: {}", msg), + _ => log::trace!("FRONT-END: {}", msg), + } +} + diff --git a/backend/src/main.rs b/backend/src/main.rs index 8390b97..d8b4397 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -75,6 +75,7 @@ fn main() -> Result<(), ()> { .register("V_INFO", |_: Vec| { vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()] }) + .register("LOG", api::general::log_it()) // battery API functions .register_async("BATTERY_current_now", api::battery::current_now(api_sender.clone())) .register_async("BATTERY_charge_now", api::battery::charge_now(api_sender.clone())) diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 3732bee..c2fdb60 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -13,6 +13,7 @@ pub struct Battery { pub charge_mode: Option, limits: BatteryLimits, state: crate::state::steam_deck::Battery, + driver_mode: crate::persist::DriverJson, } const BATTERY_VOLTAGE: f64 = 7.7; @@ -26,19 +27,23 @@ const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_ impl Battery { #[inline] pub fn from_json(other: BatteryJson, version: u64) -> Self { - let oc_limits = OverclockLimits::load_or_default().battery; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); + let oc_limits = oc_limits.battery; + let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; match version { 0 => Self { charge_rate: other.charge_rate, charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), limits: oc_limits, state: crate::state::steam_deck::Battery::default(), + driver_mode: driver, }, _ => Self { charge_rate: other.charge_rate, charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), limits: oc_limits, state: crate::state::steam_deck::Battery::default(), + driver_mode: driver, }, } } @@ -184,12 +189,15 @@ impl Battery { } pub fn system_default() -> Self { - let oc_limits = OverclockLimits::load_or_default().battery; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); + let oc_limits = oc_limits.battery; + let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; Self { charge_rate: None, charge_mode: None, limits: oc_limits, state: crate::state::steam_deck::Battery::default(), + driver_mode: driver, } } } @@ -290,6 +298,6 @@ impl TBattery for Battery { } fn provider(&self) -> crate::persist::DriverJson { - crate::persist::DriverJson::SteamDeck + self.driver_mode.clone() } } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index f1b33b8..7ae9630 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -17,6 +17,7 @@ pub struct Cpus { pub smt_capable: bool, #[allow(dead_code)] // in case this may be useful in the future pub(super) limits: CpusLimits, + driver_mode: crate::persist::DriverJson, } impl OnSet for Cpus { @@ -84,7 +85,9 @@ impl Cpus { } pub fn system_default() -> Self { - let oc_limits = OverclockLimits::load_or_default().cpus; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); + let oc_limits = oc_limits.cpus; + let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; if let Some(max_cpu) = Self::cpu_count() { let mut sys_cpus = Vec::with_capacity(max_cpu); for i in 0..max_cpu { @@ -96,6 +99,7 @@ impl Cpus { smt: true, smt_capable: can_smt, limits: oc_limits, + driver_mode: driver, } } else { Self { @@ -103,13 +107,16 @@ impl Cpus { smt: false, smt_capable: false, limits: oc_limits, + driver_mode: driver, } } } #[inline] pub fn from_json(mut other: Vec, version: u64) -> Self { - let oc_limits = OverclockLimits::load_or_default().cpus; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); + let oc_limits = oc_limits.cpus; + let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); @@ -138,6 +145,7 @@ impl Cpus { smt: !smt_disabled, smt_capable: can_smt, limits: oc_limits, + driver_mode: driver, } } } @@ -168,7 +176,7 @@ impl TCpus for Cpus { } fn provider(&self) -> crate::persist::DriverJson { - crate::persist::DriverJson::SteamDeck + self.driver_mode.clone() } } diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 9e77ba8..8f3f826 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -18,6 +18,7 @@ pub struct Gpu { pub slow_memory: bool, limits: GpuLimits, state: crate::state::steam_deck::Gpu, + driver_mode: crate::persist::DriverJson, } // same as CPU @@ -28,23 +29,26 @@ const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk impl Gpu { #[inline] pub fn from_json(other: GpuJson, version: u64) -> Self { - let oc_limits = OverclockLimits::load_or_default().gpu; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); + let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; match version { 0 => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), slow_memory: other.slow_memory, - limits: oc_limits, + limits: oc_limits.gpu, state: crate::state::steam_deck::Gpu::default(), + driver_mode: driver, }, _ => Self { fast_ppt: other.fast_ppt, slow_ppt: other.slow_ppt, clock_limits: other.clock_limits.map(|x| min_max_from_json(x, version)), slow_memory: other.slow_memory, - limits: oc_limits, + limits: oc_limits.gpu, state: crate::state::steam_deck::Gpu::default(), + driver_mode: driver, }, } } @@ -178,14 +182,15 @@ impl Gpu { } pub fn system_default() -> Self { - let oc_limits = OverclockLimits::load_or_default().gpu; + let (oc_limits, is_default) = OverclockLimits::load_or_default(); Self { fast_ppt: None, slow_ppt: None, clock_limits: None, slow_memory: false, - limits: oc_limits, + limits: oc_limits.gpu, state: crate::state::steam_deck::Gpu::default(), + driver_mode: if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }, } } } @@ -273,7 +278,7 @@ impl TGpu for Gpu { } fn provider(&self) -> crate::persist::DriverJson { - crate::persist::DriverJson::SteamDeck + self.driver_mode.clone() } } diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index 9712831..fe45826 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -21,7 +21,8 @@ impl Default for OverclockLimits { } impl OverclockLimits { - pub fn load_or_default() -> Self { + /// (Self, is_default) + pub fn load_or_default() -> (Self, bool) { let path = std::path::Path::new(OC_LIMITS_FILEPATH); if path.exists() { log::info!("Steam Deck limits file {} found", path.display()); @@ -29,22 +30,22 @@ impl OverclockLimits { Ok(f) => f, Err(e) => { log::warn!("Steam Deck limits file {} err: {} (using default fallback)", path.display(), e); - return Self::default(); + return (Self::default(), true); }, }; match serde_json::from_reader(&mut file) { Ok(result) => { log::debug!("Steam Deck limits file {} successfully loaded", path.display()); - result + (result, false) }, Err(e) => { log::warn!("Steam Deck limits file {} json err: {} (using default fallback)", path.display(), e); - Self::default() + (Self::default(), true) } } } else { log::info!("Steam Deck limits file {} not found (using default fallback)", path.display()); - Self::default() + (Self::default(), true) } } } diff --git a/src/backend.ts b/src/backend.ts index 53a1c9d..59a4f4d 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -12,6 +12,7 @@ export function resolve(promise: Promise, setter: (t: T) => void) { setter(data); } else { console.warn("Resolve failed:", data); + log(LogLevel.Warn, ""); } })(); } @@ -231,6 +232,18 @@ export async function getDriverProviderName(name: string): Promise { return (await call_backend("GENERAL_get_provider", [name]))[0]; } +export enum LogLevel { + Trace = 1, + Debug = 2, + Info = 3, + Warn = 4, + Error = 5, +} + +export async function log(level: LogLevel, msg: string): Promise { + return (await call_backend("LOG", [level, msg]))[0]; +} + export async function idk(): Promise { return (await call_backend("GENERAL_idk", []))[0]; } diff --git a/src/index.tsx b/src/index.tsx index b804bcd..ef25c48 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -104,7 +104,7 @@ const reload = function() { backend.resolve(backend.getLimits(), (limits) => { set_value(LIMITS_INFO, limits); - console.debug("POWERTOOLS: got limits", limits); + console.debug("POWERTOOLS: got limits ", limits); }); backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) }); @@ -128,7 +128,7 @@ const reload = function() { }); backend.resolve(backend.getCpusGovernor(), (governors: string[]) => { set_value(GOVERNOR_CPU, governors); - console.log("POWERTOOLS: Governors from backend", governors); + backend.log(backend.LogLevel.Info, "POWERTOOLS: Governors from backend " + governors.toString()); }); backend.resolve(backend.getGpuPpt(), (ppts: number[]) => { @@ -159,12 +159,12 @@ const reload = function() { //@ts-ignore lifetimeHook = SteamClient.GameSessions.RegisterForAppLifetimeNotifications((update) => { if (update.bRunning) { - //console.debug("AppID " + update.unAppID.toString() + " is now running"); + //backend.log(backend.LogLevel.Debug, "AppID " + update.unAppID.toString() + " is now running"); } else { - //console.debug("AppID " + update.unAppID.toString() + " is no longer running"); + //backend.log(backend.LogLevel.Debug, "AppID " + update.unAppID.toString() + " is no longer running"); backend.resolve( backend.loadGeneralDefaultSettings(), - (ok: boolean) => {console.debug("Loading default settings ok? " + ok)} + (ok: boolean) => {backend.log(backend.LogLevel.Debug, "Loading default settings ok? " + ok)} ); } }); @@ -175,11 +175,11 @@ const reload = function() { // don't use gameInfo.appid, haha backend.resolve( backend.loadGeneralSettings(id.toString() + ".json", gameInfo.display_name), - (ok: boolean) => {console.debug("Loading settings ok? " + ok)} + (ok: boolean) => {backend.log(backend.LogLevel.Debug, "Loading settings ok? " + ok)} ); }); - console.debug("Registered PowerTools callbacks, hello!"); + backend.log(backend.LogLevel.Debug, "Registered PowerTools callbacks, hello!"); })(); const periodicals = function() { @@ -250,7 +250,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="SMT" description="Enables odd-numbered CPUs" onChange={(smt: boolean) => { - console.debug("SMT is now " + smt.toString()); + backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); const cpus = get_value(ONLINE_CPUS); const smtNow = smt && smtAllowed; backend.resolve(backend.setCpuSmt(smtNow), (newVal: boolean) => { @@ -280,7 +280,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { min={1} showValue={true} onChange={(cpus: number) => { - console.debug("CPU slider is now " + cpus.toString()); + backend.log(backend.LogLevel.Debug, "CPU slider is now " + cpus.toString()); const onlines = get_value(ONLINE_CPUS); if (cpus != onlines) { set_value(ONLINE_CPUS, cpus); @@ -340,7 +340,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MIN_CPU) == null} onChange={(freq: number) => { - console.debug("Min freq slider is now " + freq.toString()); + backend.log(backend.LogLevel.Debug, "Min freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_CPU); if (freq != freqNow) { set_value(CLOCK_MIN_CPU, freq); @@ -370,7 +370,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MAX_CPU) == null} onChange={(freq: number) => { - console.debug("Max freq slider is now " + freq.toString()); + backend.log(backend.LogLevel.Debug, "Max freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MAX_CPU); if (freq != freqNow) { set_value(CLOCK_MAX_CPU, freq); @@ -410,7 +410,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Online" description="Allow the CPU thread to do work" onChange={(status: boolean) => { - console.debug("CPU " + advancedCpu.toString() + " is now " + status.toString()); + backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); if (get_value(SMT_CPU)) { backend.resolve(backend.setCpuSmt(false), (newVal: boolean) => { set_value(SMT_CPU, newVal); @@ -463,7 +463,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min == null} onChange={(freq: number) => { - console.debug("Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + backend.log(backend.LogLevel.Debug, "Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; if (freq != freqNow.min) { backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), @@ -488,7 +488,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max == null} onChange={(freq: number) => { - console.debug("Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + backend.log(backend.LogLevel.Debug, "Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; if (freq != freqNow.max) { backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), @@ -511,13 +511,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { menuLabel="Governor" rgOptions={governorOptions} selectedOption={governorOptions.find((val: SingleDropdownOption, _index, _arr) => { - console.debug("POWERTOOLS: array item", val); - console.debug("POWERTOOLS: looking for data", get_value(GOVERNOR_CPU)[advancedCpuIndex]); + backend.log(backend.LogLevel.Debug, "POWERTOOLS: array item " + val.toString()); + backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + get_value(GOVERNOR_CPU)[advancedCpuIndex].toString()); return val.data == get_value(GOVERNOR_CPU)[advancedCpuIndex]; })} strDefaultLabel={get_value(GOVERNOR_CPU)[advancedCpuIndex]} onChange={(elem: SingleDropdownOption) => { - console.debug("Governor dropdown selected", elem); + backend.log(backend.LogLevel.Debug, "Governor dropdown selected " + elem.data.toString()); backend.resolve(backend.setCpuGovernor(advancedCpuIndex, elem.data as string), (gov: string) => { const governors = get_value(GOVERNOR_CPU); governors[advancedCpuIndex] = gov; @@ -567,7 +567,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(SLOW_PPT_GPU) == null} onChange={(ppt: number) => { - console.debug("SlowPPT is now " + ppt.toString()); + backend.log(backend.LogLevel.Debug, "SlowPPT is now " + ppt.toString()); const pptNow = get_value(SLOW_PPT_GPU); const realPpt = ppt; if (realPpt != pptNow) { @@ -591,7 +591,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(FAST_PPT_GPU) == null} onChange={(ppt: number) => { - console.debug("FastPPT is now " + ppt.toString()); + backend.log(backend.LogLevel.Debug, "FastPPT is now " + ppt.toString()); const pptNow = get_value(FAST_PPT_GPU); const realPpt = ppt; if (realPpt != pptNow) { @@ -641,7 +641,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MIN_GPU) == null} onChange={(val: number) => { - console.debug("GPU Clock Min is now " + val.toString()); + backend.log(backend.LogLevel.Debug, "GPU Clock Min is now " + val.toString()); const valNow = get_value(CLOCK_MIN_GPU); if (val != valNow) { backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), @@ -664,7 +664,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CLOCK_MAX_GPU) == null} onChange={(val: number) => { - console.debug("GPU Clock Max is now " + val.toString()); + backend.log(backend.LogLevel.Debug, "GPU Clock Max is now " + val.toString()); const valNow = get_value(CLOCK_MAX_GPU); if (val != valNow) { backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), @@ -736,7 +736,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { showValue={true} disabled={get_value(CHARGE_RATE_BATT) == null} onChange={(val: number) => { - console.debug("Charge rate is now " + val.toString()); + backend.log(backend.LogLevel.Debug, "Charge rate is now " + val.toString()); const rateNow = get_value(CHARGE_RATE_BATT); if (val != rateNow) { backend.resolve(backend.setBatteryChargeRate(val), @@ -776,7 +776,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { })} strDefaultLabel={get_value(CHARGE_MODE_BATT)} onChange={(elem: SingleDropdownOption) => { - console.debug("Charge mode dropdown selected", elem); + backend.log(backend.LogLevel.Debug, "Charge mode dropdown selected " + elem.data.toString()); backend.resolve(backend.setBatteryChargeMode(elem.data as string), (mode: string) => { set_value(CHARGE_MODE_BATT, mode); reloadGUI("BATTChargeMode"); @@ -803,7 +803,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Persistent" description="Save profile and load it next time" onChange={(persist: boolean) => { - console.debug("Persist is now " + persist.toString()); + backend.log(backend.LogLevel.Debug, "Persist is now " + persist.toString()); backend.resolve( backend.setGeneralPersistent(persist), (val: boolean) => {set_value(PERSISTENT_GEN, val)} @@ -879,7 +879,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { { - console.debug("Loading default PowerTools settings"); + backend.log(backend.LogLevel.Debug, "Loading default PowerTools settings"); backend.resolve( backend.setGeneralPersistent(false), (val: boolean) => { @@ -905,13 +905,13 @@ export default definePlugin((serverApi: ServerAPI) => { content: , icon: , onDismount() { - console.debug("PowerTools shutting down"); + backend.log(backend.LogLevel.Debug, "PowerTools shutting down"); clearInterval(periodicHook!); periodicHook = null; lifetimeHook!.unregister(); startHook!.unregister(); serverApi.routerHook.removeRoute("/decky-plugin-test"); - console.debug("Unregistered PowerTools callbacks, goodbye."); + backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, goodbye."); }, }; }); From fbb68e0d519e22dac4aa559866605dd5eba29832 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Thu, 5 Jan 2023 21:16:37 -0500 Subject: [PATCH 23/44] Fix SMT behaviour paper cuts --- backend/src/api/handler.rs | 34 ++++++++++++++++++++++++++++++++-- src/backend.ts | 4 ++-- src/index.tsx | 22 +++++++--------------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index a1a9354..e7672e6 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -60,6 +60,8 @@ pub enum CpuMessage { impl CpuMessage { fn process(self, settings: &mut dyn TCpus) { + // NOTE: "cpu" refers to the Linux kernel definition of a CPU, which is actually a hardware thread + // not to be confused with a CPU chip, which usually has multiple hardware threads (cpu cores/threads) in the chip match self { Self::SetCpuOnline(index, status) => {settings.cpus().get_mut(index).map(|c| *c.online() = status);}, Self::SetCpusOnline(cpus) => { @@ -68,10 +70,38 @@ impl CpuMessage { } }, Self::SetSmt(status, cb) => { - *settings.smt() = status; + if *settings.smt() == status { + // already set, do nothing + } else if status { + // set SMT on + *settings.smt() = true; + let mut should_be_online = false; + let cpu_count = settings.len(); + for i in (0..cpu_count).rev() { + if *settings.cpus()[i].online() && !should_be_online { + should_be_online = true; + // enable the odd-numbered thread right before + // for 1c:2t configs (i.e. anything with SMT2), the highest cpu core is always odd + // (e.g. 4c8t has CPUs 0-7, inclusive) + // this enables the """fake""" (i.e. odd) cpu which is disabled when SMT is set off + if i % 2 == 0 && i+1 != cpu_count { + *(settings.cpus()[i+1].online()) = true; + } + } else { + *settings.cpus()[i].online() = should_be_online; + } + } + } else { + // set SMT off + *settings.smt() = false; + for i in 0..settings.len() { + // this disables the """fake""" (odd) cpu for appearances' sake + // the kernel will automatically disable that same cpu when SMT is changed + *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); + } + } let mut result = Vec::with_capacity(settings.len()); for i in 0..settings.len() { - *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); result.push(*settings.cpus()[i].online()); } cb(result); diff --git a/src/backend.ts b/src/backend.ts index 59a4f4d..70f1fee 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -120,8 +120,8 @@ export async function unsetBatteryChargeMode(): Promise { // CPU -export async function setCpuSmt(status: boolean): Promise { - return (await call_backend("CPU_set_smt", [status]))[0]; +export async function setCpuSmt(status: boolean): Promise { + return await call_backend("CPU_set_smt", [status]); } /*export async function getCpuCount(): Promise { diff --git a/src/index.tsx b/src/index.tsx index ef25c48..4de4a06 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -251,18 +251,10 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { description="Enables odd-numbered CPUs" onChange={(smt: boolean) => { backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); - const cpus = get_value(ONLINE_CPUS); + //const cpus = get_value(ONLINE_CPUS); const smtNow = smt && smtAllowed; - backend.resolve(backend.setCpuSmt(smtNow), (newVal: boolean) => { - set_value(SMT_CPU, newVal); - }); - let onlines: boolean[] = []; - for (let i = 0; i < total_cpus; i++) { - const online = (smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2)) - || (!smtNow && cpus == 4); - onlines.push(online); - } - backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { + backend.resolve(backend.setCpuSmt(smtNow), (statii: boolean[]) => { + set_value(SMT_CPU, smtNow); set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); @@ -276,7 +268,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Threads" value={get_value(ONLINE_CPUS)} step={1} - max={get_value(SMT_CPU) || !smtAllowed ? total_cpus : total_cpus/2} + max={(get_value(SMT_CPU) || !smtAllowed) ? total_cpus : total_cpus/2} min={1} showValue={true} onChange={(cpus: number) => { @@ -411,9 +403,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { description="Allow the CPU thread to do work" onChange={(status: boolean) => { backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); - if (get_value(SMT_CPU)) { - backend.resolve(backend.setCpuSmt(false), (newVal: boolean) => { - set_value(SMT_CPU, newVal); + if (!get_value(SMT_CPU)) { + backend.resolve(backend.setCpuSmt(true), (_newVal: boolean[]) => { + set_value(SMT_CPU, true); }); } backend.resolve(backend.setCpuOnline(advancedCpuIndex, status), (newVal: boolean) => { From 8c763f241f8f0be9d63bc4ce44c23b66c0f2fcfc Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Thu, 5 Jan 2023 21:35:53 -0500 Subject: [PATCH 24/44] Improve SMT heuristic when loading from saved --- backend/src/settings/generic/cpu.rs | 7 +++---- backend/src/settings/mod.rs | 1 + backend/src/settings/steam_deck/cpu.rs | 5 ++--- backend/src/settings/unknown/cpu.rs | 5 ++--- backend/src/settings/util.rs | 7 +++++++ 5 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 backend/src/settings/util.rs diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index a2fe995..b4bba83 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -101,7 +101,7 @@ impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); - let mut smt_disabled = false; + let smt_guess = crate::settings::util::guess_smt(&other) && can_smt; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -109,8 +109,7 @@ impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { break; } } - let mut new_cpu = C::from_json_and_limits(cpu, version, i, limits.clone()); - smt_disabled &= *new_cpu.online() as usize != i % 2; + let new_cpu = C::from_json_and_limits(cpu, version, i, limits.clone()); result.push(new_cpu); } if let Some(max_cpus) = max_cpus { @@ -123,7 +122,7 @@ impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { } Self { cpus: result, - smt: !smt_disabled, + smt: smt_guess, smt_capable: can_smt, } } diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index a24b57e..3541526 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -4,6 +4,7 @@ mod error; mod general; mod min_max; mod traits; +mod util; pub mod generic; pub mod generic_amd; diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 7ae9630..83a1909 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -120,7 +120,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); - let mut smt_disabled = false; + let smt_guess = crate::settings::util::guess_smt(&other) && can_smt; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -129,7 +129,6 @@ impl Cpus { } } let new_cpu = Cpu::from_json(cpu, version, i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default()); - smt_disabled &= new_cpu.online as usize != i % 2; result.push(new_cpu); } if let Some(max_cpus) = max_cpus { @@ -142,7 +141,7 @@ impl Cpus { } Self { cpus: result, - smt: !smt_disabled, + smt: smt_guess, smt_capable: can_smt, limits: oc_limits, driver_mode: driver, diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 76982f4..909c746 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -105,7 +105,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); - let mut smt_disabled = false; + let smt_guess = crate::settings::util::guess_smt(&other) && can_smt; for (i, cpu) in other.drain(..).enumerate() { // prevent having more CPUs than available if let Some(max_cpus) = max_cpus { @@ -114,7 +114,6 @@ impl Cpus { } } let new_cpu = Cpu::from_json(cpu, version, i); - smt_disabled &= new_cpu.online as usize != i % 2; result.push(new_cpu); } if let Some(max_cpus) = max_cpus { @@ -127,7 +126,7 @@ impl Cpus { } Self { cpus: result, - smt: !smt_disabled, + smt: smt_guess, smt_capable: can_smt, } } diff --git a/backend/src/settings/util.rs b/backend/src/settings/util.rs new file mode 100644 index 0000000..83f032d --- /dev/null +++ b/backend/src/settings/util.rs @@ -0,0 +1,7 @@ +pub fn guess_smt(cpus: &Vec) -> bool { + let mut guess = true; + for i in (0..cpus.len()).step_by(2) { + guess &= cpus[i].online == cpus[i+1].online; + } + guess +} From 3b34bad28a5a9100199cd113e617a71c3eabae0f Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 7 Jan 2023 18:45:12 -0500 Subject: [PATCH 25/44] Refactor UI so not *everything* updates when one thing changes... I hate React --- src/components/debug.tsx | 83 +++++++++++ src/components/gpu.tsx | 195 ++++++++++++++++++++++++++ src/consts.ts | 29 ++++ src/index.tsx | 287 ++++++--------------------------------- 4 files changed, 345 insertions(+), 249 deletions(-) create mode 100644 src/components/debug.tsx create mode 100644 src/components/gpu.tsx create mode 100644 src/consts.ts diff --git a/src/components/debug.tsx b/src/components/debug.tsx new file mode 100644 index 0000000..05b254c --- /dev/null +++ b/src/components/debug.tsx @@ -0,0 +1,83 @@ +import { Fragment } from "react"; +import {Component} from "react"; +import { + ButtonItem, + Field, + PanelSectionRow, + staticClasses, + Router, +} from "decky-frontend-lib"; +import * as backend from "../backend"; +import { + BACKEND_INFO, + DRIVER_INFO, +} from "../consts"; +import { get_value, target_usdpl, version_usdpl} from "usdpl-front"; + +let eggCount = 0; + +export class Debug extends Component<{}> { + render() { + return buildDebug(); + } +} + +function buildDebug() { + return ({/* Version Info */} +
+ {eggCount % 10 == 9 ? "Ha! Nerd" : "Debug"} +
+ + { + if (eggCount % 10 == 9) { + // you know you're bored and/or conceited when you spend time adding an easter egg + // that just sends people to your own project's repo + Router.NavigateToExternalWeb("https://github.com/NGnius/PowerTools"); + } + eggCount++; + }}> + {eggCount % 10 == 9 ? "by NGnius" : get_value(BACKEND_INFO)} + + + + eggCount++}> + {eggCount % 10 == 9 ? "<3 <3 <3" : target_usdpl()} + + + + eggCount++}> + {eggCount % 10 == 9 ? "Tracy Chapman" : get_value(DRIVER_INFO)} + + + + { + if (eggCount % 10 == 9) { + // you know you're bored and/or conceited when you spend time adding an easter egg + // that just sends people to your own project's repo + Router.NavigateToExternalWeb("https://github.com/NGnius/usdpl-rs"); + } + eggCount++; + }}> + v{version_usdpl()} + + + {eggCount % 10 == 9 && + { + backend.idk(); + }} + > + ??? + + } +
); +} diff --git a/src/components/gpu.tsx b/src/components/gpu.tsx new file mode 100644 index 0000000..0dd41d3 --- /dev/null +++ b/src/components/gpu.tsx @@ -0,0 +1,195 @@ +import { Fragment } from "react"; +import {Component} from "react"; +import { + ToggleField, + SliderField, + PanelSectionRow, + staticClasses, +} from "decky-frontend-lib"; +import * as backend from "../backend"; +import { + LIMITS_INFO, + SLOW_PPT_GPU, + FAST_PPT_GPU, + CLOCK_MIN_GPU, + CLOCK_MAX_GPU, + SLOW_MEMORY_GPU, +} from "../consts"; +import { set_value, get_value} from "usdpl-front"; + +export class Gpu extends Component<{}> { + constructor(props: {}) { + super(props); + this.state = { + reloadThingy: "/shrug", + }; + } + + render() { + const reloadGUI = (x: string) => this.setState({reloadThingy: x}); + return ( + {/* GPU */} +
+ GPU +
+ { ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null ||(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) && + { + if (value) { + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) { + set_value(SLOW_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits!.max); + } + + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null) { + set_value(FAST_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits!.max); + } + reloadGUI("GPUPPTToggle"); + } else { + set_value(SLOW_PPT_GPU, null); + set_value(FAST_PPT_GPU, null); + backend.resolve(backend.unsetGpuPpt(), (_: any[]) => { + reloadGUI("GPUUnsetPPT"); + }); + } + }} + /> + } + + { get_value(SLOW_PPT_GPU) != null && { + backend.log(backend.LogLevel.Debug, "SlowPPT is now " + ppt.toString()); + const pptNow = get_value(SLOW_PPT_GPU); + const realPpt = ppt; + if (realPpt != pptNow) { + backend.resolve(backend.setGpuPpt(get_value(FAST_PPT_GPU), realPpt), + (limits: number[]) => { + set_value(FAST_PPT_GPU, limits[0]); + set_value(SLOW_PPT_GPU, limits[1]); + reloadGUI("GPUSlowPPT"); + }); + } + }} + />} + + + {get_value(FAST_PPT_GPU) != null && { + backend.log(backend.LogLevel.Debug, "FastPPT is now " + ppt.toString()); + const pptNow = get_value(FAST_PPT_GPU); + const realPpt = ppt; + if (realPpt != pptNow) { + backend.resolve(backend.setGpuPpt(realPpt, get_value(SLOW_PPT_GPU)), + (limits: number[]) => { + set_value(FAST_PPT_GPU, limits[0]); + set_value(SLOW_PPT_GPU, limits[1]); + reloadGUI("GPUFastPPT"); + }); + } + }} + />} + + {((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits != null || (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits != null) && + { + if (value) { + let clock_min_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits; + let clock_max_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits; + if (clock_min_limits != null) { + set_value(CLOCK_MIN_GPU, clock_min_limits.min); + } + if (clock_max_limits != null) { + set_value(CLOCK_MAX_GPU, clock_max_limits.max); + } + reloadGUI("GPUFreqToggle"); + } else { + set_value(CLOCK_MIN_GPU, null); + set_value(CLOCK_MAX_GPU, null); + backend.resolve(backend.unsetGpuClockLimits(), (_: any[]) => { + reloadGUI("GPUUnsetFreq"); + }); + } + }} + /> + } + + { get_value(CLOCK_MIN_GPU) != null && { + backend.log(backend.LogLevel.Debug, "GPU Clock Min is now " + val.toString()); + const valNow = get_value(CLOCK_MIN_GPU); + if (val != valNow) { + backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), + (limits: number[]) => { + set_value(CLOCK_MIN_GPU, limits[0]); + set_value(CLOCK_MAX_GPU, limits[1]); + reloadGUI("GPUMinClock"); + }); + } + }} + />} + + + {get_value(CLOCK_MAX_GPU) != null && { + backend.log(backend.LogLevel.Debug, "GPU Clock Max is now " + val.toString()); + const valNow = get_value(CLOCK_MAX_GPU); + if (val != valNow) { + backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), + (limits: number[]) => { + set_value(CLOCK_MIN_GPU, limits[0]); + set_value(CLOCK_MAX_GPU, limits[1]); + reloadGUI("GPUMaxClock"); + }); + } + }} + />} + + {(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control_capable && + { + backend.resolve(backend.setGpuSlowMemory(value), (val: boolean) => { + set_value(SLOW_MEMORY_GPU, val); + reloadGUI("GPUSlowMemory"); + }) + }} + /> + } +
); + } +} diff --git a/src/consts.ts b/src/consts.ts new file mode 100644 index 0000000..0efe070 --- /dev/null +++ b/src/consts.ts @@ -0,0 +1,29 @@ +export const BACKEND_INFO = "VINFO"; +export const DRIVER_INFO = "GENERAL_provider"; + +export const LIMITS_INFO = "LIMITS_all"; + +export const CURRENT_BATT = "BATTERY_current_now"; +export const CHARGE_RATE_BATT = "BATTERY_charge_rate"; +export const CHARGE_MODE_BATT = "BATTERY_charge_mode"; +export const CHARGE_NOW_BATT = "BATTERY_charge_now"; +export const CHARGE_FULL_BATT = "BATTERY_charge_full"; +export const CHARGE_DESIGN_BATT = "BATTERY_charge_design"; + +//export const TOTAL_CPUS = "CPUs_total"; +export const ONLINE_CPUS = "CPUs_online"; +export const ONLINE_STATUS_CPUS = "CPUs_status_online"; +export const SMT_CPU = "CPUs_SMT"; +export const CLOCK_MIN_CPU = "CPUs_min_clock"; +export const CLOCK_MAX_CPU = "CPUs_max_clock"; +export const CLOCK_MIN_MAX_CPU = "CPUs_minmax_clocks"; +export const GOVERNOR_CPU = "CPUs_governor"; + +export const FAST_PPT_GPU = "GPU_fastPPT"; +export const SLOW_PPT_GPU = "GPU_slowPPT"; +export const CLOCK_MIN_GPU = "GPU_min_clock"; +export const CLOCK_MAX_GPU = "GPU_max_clock"; +export const SLOW_MEMORY_GPU = "GPU_slow_memory"; + +export const PERSISTENT_GEN = "GENERAL_persistent"; +export const NAME_GEN = "GENERAL_name"; diff --git a/src/index.tsx b/src/index.tsx index 4de4a06..f24413b 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,7 +6,6 @@ import { //MenuItem, PanelSection, PanelSectionRow, - Router, ServerAPI, //showContextMenu, staticClasses, @@ -25,7 +24,39 @@ import { GiDrill } from "react-icons/gi"; //import * as python from "./python"; import * as backend from "./backend"; -import {set_value, get_value, target_usdpl, version_usdpl} from "usdpl-front"; +import { + BACKEND_INFO, + DRIVER_INFO, + + LIMITS_INFO, + + CURRENT_BATT, + CHARGE_RATE_BATT, + CHARGE_MODE_BATT, + CHARGE_NOW_BATT, + CHARGE_FULL_BATT, + CHARGE_DESIGN_BATT, + + ONLINE_CPUS, + ONLINE_STATUS_CPUS, + SMT_CPU, + CLOCK_MIN_CPU, + CLOCK_MAX_CPU, + CLOCK_MIN_MAX_CPU, + GOVERNOR_CPU, + + FAST_PPT_GPU, + SLOW_PPT_GPU, + CLOCK_MIN_GPU, + CLOCK_MAX_GPU, + SLOW_MEMORY_GPU, + + PERSISTENT_GEN, + NAME_GEN, +} from "./consts"; +import {set_value, get_value} from "usdpl-front"; +import {Debug} from "./components/debug"; +import {Gpu} from "./components/gpu"; var periodicHook: NodeJS.Timer | null = null; var lifetimeHook: any = null; @@ -45,36 +76,6 @@ type MinMax = { // usdpl persistent store keys -const BACKEND_INFO = "VINFO"; -const DRIVER_INFO = "GENERAL_provider"; - -const LIMITS_INFO = "LIMITS_all"; - -const CURRENT_BATT = "BATTERY_current_now"; -const CHARGE_RATE_BATT = "BATTERY_charge_rate"; -const CHARGE_MODE_BATT = "BATTERY_charge_mode"; -const CHARGE_NOW_BATT = "BATTERY_charge_now"; -const CHARGE_FULL_BATT = "BATTERY_charge_full"; -const CHARGE_DESIGN_BATT = "BATTERY_charge_design" - -//const TOTAL_CPUS = "CPUs_total"; -const ONLINE_CPUS = "CPUs_online"; -const ONLINE_STATUS_CPUS = "CPUs_status_online"; -const SMT_CPU = "CPUs_SMT"; -const CLOCK_MIN_CPU = "CPUs_min_clock"; -const CLOCK_MAX_CPU = "CPUs_max_clock"; -const CLOCK_MIN_MAX_CPU = "CPUs_minmax_clocks"; -const GOVERNOR_CPU = "CPUs_governor"; - -const FAST_PPT_GPU = "GPU_fastPPT"; -const SLOW_PPT_GPU = "GPU_slowPPT"; -const CLOCK_MIN_GPU = "GPU_min_clock"; -const CLOCK_MAX_GPU = "GPU_max_clock"; -const SLOW_MEMORY_GPU = "GPU_slow_memory"; - -const PERSISTENT_GEN = "GENERAL_persistent"; -const NAME_GEN = "GENERAL_name"; - function countCpus(statii: boolean[]): number { let count = 0; for (let i = 0; i < statii.length; i++) { @@ -520,168 +521,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { />
} - {/* GPU */} -
- GPU -
- { ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null ||(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) && - { - if (value) { - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) { - set_value(SLOW_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits!.max); - } - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null) { - set_value(FAST_PPT_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits!.max); - } - reloadGUI("GPUPPTToggle"); - } else { - set_value(SLOW_PPT_GPU, null); - set_value(FAST_PPT_GPU, null); - backend.resolve(backend.unsetGpuPpt(), (_: any[]) => { - reloadGUI("GPUUnsetPPT"); - }); - } - }} - /> - } - - { get_value(SLOW_PPT_GPU) != null && { - backend.log(backend.LogLevel.Debug, "SlowPPT is now " + ppt.toString()); - const pptNow = get_value(SLOW_PPT_GPU); - const realPpt = ppt; - if (realPpt != pptNow) { - backend.resolve(backend.setGpuPpt(get_value(FAST_PPT_GPU), realPpt), - (limits: number[]) => { - set_value(FAST_PPT_GPU, limits[0]); - set_value(SLOW_PPT_GPU, limits[1]); - reloadGUI("GPUSlowPPT"); - }); - } - }} - />} - - - {get_value(FAST_PPT_GPU) != null && { - backend.log(backend.LogLevel.Debug, "FastPPT is now " + ppt.toString()); - const pptNow = get_value(FAST_PPT_GPU); - const realPpt = ppt; - if (realPpt != pptNow) { - backend.resolve(backend.setGpuPpt(realPpt, get_value(SLOW_PPT_GPU)), - (limits: number[]) => { - set_value(FAST_PPT_GPU, limits[0]); - set_value(SLOW_PPT_GPU, limits[1]); - reloadGUI("GPUFastPPT"); - }); - } - }} - />} - - {((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits != null || (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits != null) && - { - if (value) { - let clock_min_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits; - let clock_max_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits; - if (clock_min_limits != null) { - set_value(CLOCK_MIN_GPU, clock_min_limits.min); - } - if (clock_max_limits != null) { - set_value(CLOCK_MAX_GPU, clock_max_limits.max); - } - reloadGUI("GPUFreqToggle"); - } else { - set_value(CLOCK_MIN_GPU, null); - set_value(CLOCK_MAX_GPU, null); - backend.resolve(backend.unsetGpuClockLimits(), (_: any[]) => { - reloadGUI("GPUUnsetFreq"); - }); - } - }} - /> - } - - { get_value(CLOCK_MIN_GPU) != null && { - backend.log(backend.LogLevel.Debug, "GPU Clock Min is now " + val.toString()); - const valNow = get_value(CLOCK_MIN_GPU); - if (val != valNow) { - backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), - (limits: number[]) => { - set_value(CLOCK_MIN_GPU, limits[0]); - set_value(CLOCK_MAX_GPU, limits[1]); - reloadGUI("GPUMinClock"); - }); - } - }} - />} - - - {get_value(CLOCK_MAX_GPU) != null && { - backend.log(backend.LogLevel.Debug, "GPU Clock Max is now " + val.toString()); - const valNow = get_value(CLOCK_MAX_GPU); - if (val != valNow) { - backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), - (limits: number[]) => { - set_value(CLOCK_MIN_GPU, limits[0]); - set_value(CLOCK_MAX_GPU, limits[1]); - reloadGUI("GPUMaxClock"); - }); - } - }} - />} - - {(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control_capable && - { - backend.resolve(backend.setGpuSlowMemory(value), (val: boolean) => { - set_value(SLOW_MEMORY_GPU, val); - reloadGUI("GPUSlowMemory"); - }) - }} - /> - } + + {/* Battery */}
Battery @@ -811,62 +653,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {get_value(NAME_GEN)} - {/* Version Info */} -
- {eggCount % 10 == 9 ? "Ha! Nerd" : "Debug"} -
- - { - if (eggCount % 10 == 9) { - // you know you're bored and/or conceited when you spend time adding an easter egg - // that just sends people to your own project's repo - Router.NavigateToExternalWeb("https://github.com/NGnius/PowerTools"); - } - eggCount++; - }}> - {eggCount % 10 == 9 ? "by NGnius" : get_value(BACKEND_INFO)} - - - - eggCount++}> - {eggCount % 10 == 9 ? "<3 <3 <3" : target_usdpl()} - - - - eggCount++}> - {eggCount % 10 == 9 ? "Tracy Chapman" : get_value(DRIVER_INFO)} - - - - { - if (eggCount % 10 == 9) { - // you know you're bored and/or conceited when you spend time adding an easter egg - // that just sends people to your own project's repo - Router.NavigateToExternalWeb("https://github.com/NGnius/usdpl-rs"); - } - eggCount++; - }}> - v{version_usdpl()} - - - {eggCount % 10 == 9 && - { - backend.idk(); - }} - > - ??? - - } + + + Date: Sat, 7 Jan 2023 20:07:26 -0500 Subject: [PATCH 26/44] Convert the remaining UI sections into components too --- src/components/battery.tsx | 138 ++++++++++++ src/components/cpus.tsx | 397 +++++++++++++++++++++++++++++++++ src/index.tsx | 440 ++----------------------------------- 3 files changed, 548 insertions(+), 427 deletions(-) create mode 100644 src/components/battery.tsx create mode 100644 src/components/cpus.tsx diff --git a/src/components/battery.tsx b/src/components/battery.tsx new file mode 100644 index 0000000..b35cac2 --- /dev/null +++ b/src/components/battery.tsx @@ -0,0 +1,138 @@ +import { Fragment } from "react"; +import {Component} from "react"; +import { + ToggleField, + SliderField, + Field, + SingleDropdownOption, + Dropdown, + PanelSectionRow, + staticClasses, +} from "decky-frontend-lib"; +import * as backend from "../backend"; +import { + LIMITS_INFO, + CHARGE_DESIGN_BATT, + CHARGE_FULL_BATT, + CHARGE_NOW_BATT, + CHARGE_RATE_BATT, + CHARGE_MODE_BATT, + CURRENT_BATT, +} from "../consts"; +import { set_value, get_value} from "usdpl-front"; + +export class Battery extends Component<{}> { + constructor(props: {}) { + super(props); + this.state = { + reloadThingy: "/shrug", + }; + } + + render() { + const reloadGUI = (x: string) => this.setState({reloadThingy: x}); + const chargeModeOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_modes.map((elem) => {return { + data: elem, + label: {elem}, + };}); + return ( + {/* Battery */} +
+ Battery +
+ {get_value(CHARGE_NOW_BATT) != null && get_value(CHARGE_FULL_BATT) != null && + + {get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%) + + } + {get_value(CHARGE_FULL_BATT) != null && get_value(CHARGE_DESIGN_BATT) != null && + + {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) + + } + {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_current != null && + { + if (value) { + set_value(CHARGE_RATE_BATT, 2500); + reloadGUI("BATTChargeRateToggle"); + } else { + set_value(CHARGE_RATE_BATT, null); + backend.resolve(backend.unsetBatteryChargeRate(), (_: any[]) => { + reloadGUI("BATTUnsetChargeRate"); + }); + } + }} + /> + { get_value(CHARGE_RATE_BATT) != null && { + backend.log(backend.LogLevel.Debug, "Charge rate is now " + val.toString()); + const rateNow = get_value(CHARGE_RATE_BATT); + if (val != rateNow) { + backend.resolve(backend.setBatteryChargeRate(val), + (rate: number) => { + set_value(CHARGE_RATE_BATT, rate); + reloadGUI("BATTChargeRate"); + }); + } + }} + />} + } + {chargeModeOptions.length != 0 && + { + if (value) { + set_value(CHARGE_MODE_BATT, chargeModeOptions[0].data as string); + reloadGUI("BATTChargeModeToggle"); + } else { + set_value(CHARGE_MODE_BATT, null); + backend.resolve(backend.unsetBatteryChargeMode(), (_: any[]) => { + reloadGUI("BATTUnsetChargeMode"); + }); + } + }} + /> + {get_value(CHARGE_MODE_BATT) != null && + { + return val.data == get_value(CHARGE_MODE_BATT); + })} + strDefaultLabel={get_value(CHARGE_MODE_BATT)} + onChange={(elem: SingleDropdownOption) => { + backend.log(backend.LogLevel.Debug, "Charge mode dropdown selected " + elem.data.toString()); + backend.resolve(backend.setBatteryChargeMode(elem.data as string), (mode: string) => { + set_value(CHARGE_MODE_BATT, mode); + reloadGUI("BATTChargeMode"); + }); + }} + /> + } + } + + + {get_value(CURRENT_BATT)} mA + + +
); + } +} diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx new file mode 100644 index 0000000..1c97d87 --- /dev/null +++ b/src/components/cpus.tsx @@ -0,0 +1,397 @@ +import { Fragment } from "react"; +import { Component } from "react"; +import { + ToggleField, + SliderField, + Field, + SingleDropdownOption, + Dropdown, + PanelSectionRow, + staticClasses, +} from "decky-frontend-lib"; +import * as backend from "../backend"; +import { + LIMITS_INFO, + SMT_CPU, + CLOCK_MAX_CPU, + CLOCK_MIN_CPU, + CLOCK_MIN_MAX_CPU, + ONLINE_CPUS, + ONLINE_STATUS_CPUS, + GOVERNOR_CPU, +} from "../consts"; +import { set_value, get_value } from "usdpl-front"; + +interface CpuState { + reloadThingy: string; + advancedCpu: number; + advancedMode: boolean; +} + +export class Cpus extends Component<{}, CpuState> { + constructor(props: {}) { + super(props); + this.state = { + reloadThingy: "/shrug", + advancedCpu: 1, + advancedMode: false, + }; + } + + render() { + const reloadGUI = (x: string) => this.setState((state) => { + return { + reloadThingy: x, + advancedCpu: state.advancedCpu, + advancedMode: state.advancedMode, + }; + }); + + const total_cpus = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.count ?? 8; + const advancedCpuIndex = this.state.advancedCpu - 1; + const advancedCpu = this.state.advancedCpu; + const advancedMode = this.state.advancedMode; + const smtAllowed = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.smt_capable ?? true; + + const governorOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.map((elem) => {return { + data: elem, + label: {elem}, + };}); + + return ( + {/* CPU */} +
+ CPU +
+ + { + //advancedMode = advanced; + this.setState((state) => { + return { + reloadThingy: state.reloadThingy, + advancedCpu: state.advancedCpu, + advancedMode: advanced, + }; + }); + }} + /> + + {/* CPU plebeian mode */} + {!advancedMode && smtAllowed && + { + backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); + //const cpus = get_value(ONLINE_CPUS); + const smtNow = smt && smtAllowed; + backend.resolve(backend.setCpuSmt(smtNow), (statii: boolean[]) => { + set_value(SMT_CPU, smtNow); + set_value(ONLINE_STATUS_CPUS, statii); + const count = countCpus(statii); + set_value(ONLINE_CPUS, count); + reloadGUI("SMT"); + }); + }} + /> + } + {!advancedMode && + { + backend.log(backend.LogLevel.Debug, "CPU slider is now " + cpus.toString()); + const onlines = get_value(ONLINE_CPUS); + if (cpus != onlines) { + set_value(ONLINE_CPUS, cpus); + const smtNow = get_value(SMT_CPU); + let onlines: boolean[] = []; + for (let i = 0; i < total_cpus; i++) { + const online = smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2); + onlines.push(online); + } + backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { + set_value(ONLINE_STATUS_CPUS, statii); + const count = countCpus(statii); + set_value(ONLINE_CPUS, count); + reloadGUI("CPUs"); + }); + reloadGUI("CPUsImmediate"); + } + }} + /> + } + {!advancedMode && + { + if (value) { + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { + set_value(CLOCK_MIN_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits!.min); + } + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null) { + set_value(CLOCK_MAX_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits!.max); + } + syncPlebClockToAdvanced(); + reloadGUI("CPUFreqToggle"); + } else { + set_value(CLOCK_MIN_CPU, null); + set_value(CLOCK_MAX_CPU, null); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.unsetCpuClockLimits(i), (_idc: any[]) => {}); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUUnsetFreq"); + }); + syncPlebClockToAdvanced(); + } + }} + /> + } + {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null && + {get_value(CLOCK_MIN_CPU) != null && { + backend.log(backend.LogLevel.Debug, "Min freq slider is now " + freq.toString()); + const freqNow = get_value(CLOCK_MIN_CPU); + if (freq != freqNow) { + set_value(CLOCK_MIN_CPU, freq); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.setCpuClockLimits(i, freq, get_value(CLOCK_MAX_CPU)), + (limits: number[]) => { + set_value(CLOCK_MIN_CPU, limits[0]); + set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); + }); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUMinFreq"); + }); + reloadGUI("CPUMinFreqImmediate"); + } + }} + />} + } + {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null && + {get_value(CLOCK_MAX_CPU) != null && { + backend.log(backend.LogLevel.Debug, "Max freq slider is now " + freq.toString()); + const freqNow = get_value(CLOCK_MAX_CPU); + if (freq != freqNow) { + set_value(CLOCK_MAX_CPU, freq); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.setCpuClockLimits(i, get_value(CLOCK_MIN_CPU), freq), + (limits: number[]) => { + set_value(CLOCK_MIN_CPU, limits[0]); + set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); + }); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUMaxFreq"); + }); + reloadGUI("CPUMaxFreqImmediate"); + } + }} + />} + } + {/* CPU advanced mode */} + {advancedMode && + { + this.setState((state) => { + return { + reloadThingy: state.reloadThingy, + advancedCpu: cpuNum, + advancedMode: state.advancedMode, + }; + }); + }} + /> + } + {advancedMode && + { + backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); + if (!get_value(SMT_CPU)) { + backend.resolve(backend.setCpuSmt(true), (_newVal: boolean[]) => { + set_value(SMT_CPU, true); + }); + } + backend.resolve(backend.setCpuOnline(advancedCpuIndex, status), (newVal: boolean) => { + const onlines = get_value(ONLINE_STATUS_CPUS); + onlines[advancedCpuIndex] = newVal; + set_value(ONLINE_STATUS_CPUS, onlines); + }); + }} + /> + } + {advancedMode && + { + if (value) { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null) { + clocks[advancedCpuIndex].min = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits!.min; + } + + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null) { + clocks[advancedCpuIndex].max = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits!.max; + } + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUFreqToggle"); + } else { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = null; + clocks[advancedCpuIndex].max = null; + set_value(CLOCK_MIN_MAX_CPU, clocks); + backend.resolve(backend.unsetCpuClockLimits(advancedCpuIndex), (_idc: any[]) => { + reloadGUI("CPUUnsetFreq"); + }); + } + }} + /> + } + {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null && + {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min != null && { + backend.log(backend.LogLevel.Debug, "Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; + if (freq != freqNow.min) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMinFreq"); + }); + } + }} + />} + } + {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null && + {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max != null && { + backend.log(backend.LogLevel.Debug, "Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); + const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; + if (freq != freqNow.max) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMaxFreq"); + }); + } + }} + />} + } + {advancedMode && governorOptions.length != 0 && + + { + backend.log(backend.LogLevel.Debug, "POWERTOOLS: array item " + val.toString()); + backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + get_value(GOVERNOR_CPU)[advancedCpuIndex].toString()); + return val.data == get_value(GOVERNOR_CPU)[advancedCpuIndex]; + })} + strDefaultLabel={get_value(GOVERNOR_CPU)[advancedCpuIndex]} + onChange={(elem: SingleDropdownOption) => { + backend.log(backend.LogLevel.Debug, "Governor dropdown selected " + elem.data.toString()); + backend.resolve(backend.setCpuGovernor(advancedCpuIndex, elem.data as string), (gov: string) => { + const governors = get_value(GOVERNOR_CPU); + governors[advancedCpuIndex] = gov; + set_value(GOVERNOR_CPU, governors); + reloadGUI("CPUGovernor"); + }); + }} + /> + + } +
); + } +} + +function countCpus(statii: boolean[]): number { + let count = 0; + for (let i = 0; i < statii.length; i++) { + if (statii[i]) { + count += 1; + } + } + return count; +} + +type MinMax = { + min: number | null; + max: number | null; +} + +function syncPlebClockToAdvanced() { + const cpuCount = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.count; + const minClock = get_value(CLOCK_MIN_CPU); + const maxClock = get_value(CLOCK_MAX_CPU); + let clockArr = []; + for (let i = 0; i < cpuCount; i++) { + clockArr.push({ + min: minClock, + max: maxClock, + } as MinMax); + } + set_value(CLOCK_MIN_MAX_CPU, clockArr); +} diff --git a/src/index.tsx b/src/index.tsx index f24413b..45e58c2 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -9,12 +9,12 @@ import { ServerAPI, //showContextMenu, staticClasses, - SliderField, + //SliderField, ToggleField, - Dropdown, + //Dropdown, Field, //DropdownOption, - SingleDropdownOption, + //SingleDropdownOption, //NotchLabel //gamepadDialogClasses, //joinClassNames, @@ -54,28 +54,22 @@ import { PERSISTENT_GEN, NAME_GEN, } from "./consts"; -import {set_value, get_value} from "usdpl-front"; -import {Debug} from "./components/debug"; -import {Gpu} from "./components/gpu"; +import { set_value, get_value } from "usdpl-front"; +import { Debug } from "./components/debug"; +import { Gpu } from "./components/gpu"; +import { Battery } from "./components/battery"; +import { Cpus } from "./components/cpus"; var periodicHook: NodeJS.Timer | null = null; var lifetimeHook: any = null; var startHook: any = null; var usdplReady = false; -var eggCount = 0; - -//var smtAllowed = true; -var advancedMode = false; -var advancedCpu = 1; - type MinMax = { min: number | null; max: number | null; } -// usdpl persistent store keys - function countCpus(statii: boolean[]): number { let count = 0; for (let i = 0; i < statii.length; i++) { @@ -212,421 +206,15 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { reloadGUI("periodic" + (new Date()).getTime().toString()); }, 1000); - //const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard); - - const total_cpus = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.count ?? 8; - const advancedCpuIndex = advancedCpu - 1; - const smtAllowed = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.smt_capable ?? true; - - const governorOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.map((elem) => {return { - data: elem, - label: {elem}, - };}); - - const chargeModeOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_modes.map((elem) => {return { - data: elem, - label: {elem}, - };}); - return ( - {/* CPU */} -
- CPU -
- - { - advancedMode = advanced; - }} - /> - - {/* CPU plebeian mode */} - {!advancedMode && smtAllowed && - { - backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); - //const cpus = get_value(ONLINE_CPUS); - const smtNow = smt && smtAllowed; - backend.resolve(backend.setCpuSmt(smtNow), (statii: boolean[]) => { - set_value(SMT_CPU, smtNow); - set_value(ONLINE_STATUS_CPUS, statii); - const count = countCpus(statii); - set_value(ONLINE_CPUS, count); - reloadGUI("SMT"); - }); - }} - /> - } - {!advancedMode && - { - backend.log(backend.LogLevel.Debug, "CPU slider is now " + cpus.toString()); - const onlines = get_value(ONLINE_CPUS); - if (cpus != onlines) { - set_value(ONLINE_CPUS, cpus); - const smtNow = get_value(SMT_CPU); - let onlines: boolean[] = []; - for (let i = 0; i < total_cpus; i++) { - const online = smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2); - onlines.push(online); - } - backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { - set_value(ONLINE_STATUS_CPUS, statii); - const count = countCpus(statii); - set_value(ONLINE_CPUS, count); - reloadGUI("CPUs"); - }); - reloadGUI("CPUsImmediate"); - } - }} - /> - } - {!advancedMode && - { - if (value) { - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { - set_value(CLOCK_MIN_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits!.min); - } - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null) { - set_value(CLOCK_MAX_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits!.max); - } - syncPlebClockToAdvanced(); - reloadGUI("CPUFreqToggle"); - } else { - set_value(CLOCK_MIN_CPU, null); - set_value(CLOCK_MAX_CPU, null); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.unsetCpuClockLimits(i), (_idc: any[]) => {}); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUUnsetFreq"); - }); - syncPlebClockToAdvanced(); - } - }} - /> - } - {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null && - {get_value(CLOCK_MIN_CPU) != null && { - backend.log(backend.LogLevel.Debug, "Min freq slider is now " + freq.toString()); - const freqNow = get_value(CLOCK_MIN_CPU); - if (freq != freqNow) { - set_value(CLOCK_MIN_CPU, freq); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.setCpuClockLimits(i, freq, get_value(CLOCK_MAX_CPU)), - (limits: number[]) => { - set_value(CLOCK_MIN_CPU, limits[0]); - set_value(CLOCK_MAX_CPU, limits[1]); - syncPlebClockToAdvanced(); - }); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUMinFreq"); - }); - reloadGUI("CPUMinFreqImmediate"); - } - }} - />} - } - {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null && - {get_value(CLOCK_MAX_CPU) != null && { - backend.log(backend.LogLevel.Debug, "Max freq slider is now " + freq.toString()); - const freqNow = get_value(CLOCK_MAX_CPU); - if (freq != freqNow) { - set_value(CLOCK_MAX_CPU, freq); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.setCpuClockLimits(i, get_value(CLOCK_MIN_CPU), freq), - (limits: number[]) => { - set_value(CLOCK_MIN_CPU, limits[0]); - set_value(CLOCK_MAX_CPU, limits[1]); - syncPlebClockToAdvanced(); - }); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUMaxFreq"); - }); - reloadGUI("CPUMaxFreqImmediate"); - } - }} - />} - } - {/* CPU advanced mode */} - {advancedMode && - { - advancedCpu = cpuNum; - }} - /> - } - {advancedMode && - { - backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); - if (!get_value(SMT_CPU)) { - backend.resolve(backend.setCpuSmt(true), (_newVal: boolean[]) => { - set_value(SMT_CPU, true); - }); - } - backend.resolve(backend.setCpuOnline(advancedCpuIndex, status), (newVal: boolean) => { - const onlines = get_value(ONLINE_STATUS_CPUS); - onlines[advancedCpuIndex] = newVal; - set_value(ONLINE_STATUS_CPUS, onlines); - }); - }} - /> - } - {advancedMode && - { - if (value) { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null) { - clocks[advancedCpuIndex].min = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits!.min; - } - - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null) { - clocks[advancedCpuIndex].max = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits!.max; - } - set_value(CLOCK_MIN_MAX_CPU, clocks); - reloadGUI("CPUFreqToggle"); - } else { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = null; - clocks[advancedCpuIndex].max = null; - set_value(CLOCK_MIN_MAX_CPU, clocks); - backend.resolve(backend.unsetCpuClockLimits(advancedCpuIndex), (_idc: any[]) => { - reloadGUI("CPUUnsetFreq"); - }); - } - }} - /> - } - {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null && - {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min != null && { - backend.log(backend.LogLevel.Debug, "Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); - const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.min) { - backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), - (limits: number[]) => { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = limits[0]; - clocks[advancedCpuIndex].max = limits[1]; - set_value(CLOCK_MIN_MAX_CPU, clocks); - reloadGUI("CPUMinFreq"); - }); - } - }} - />} - } - {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null && - {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max != null && { - backend.log(backend.LogLevel.Debug, "Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); - const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.max) { - backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), - (limits: number[]) => { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = limits[0]; - clocks[advancedCpuIndex].max = limits[1]; - set_value(CLOCK_MIN_MAX_CPU, clocks); - reloadGUI("CPUMaxFreq"); - }); - } - }} - />} - } - {advancedMode && governorOptions.length != 0 && - - { - backend.log(backend.LogLevel.Debug, "POWERTOOLS: array item " + val.toString()); - backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + get_value(GOVERNOR_CPU)[advancedCpuIndex].toString()); - return val.data == get_value(GOVERNOR_CPU)[advancedCpuIndex]; - })} - strDefaultLabel={get_value(GOVERNOR_CPU)[advancedCpuIndex]} - onChange={(elem: SingleDropdownOption) => { - backend.log(backend.LogLevel.Debug, "Governor dropdown selected " + elem.data.toString()); - backend.resolve(backend.setCpuGovernor(advancedCpuIndex, elem.data as string), (gov: string) => { - const governors = get_value(GOVERNOR_CPU); - governors[advancedCpuIndex] = gov; - set_value(GOVERNOR_CPU, governors); - reloadGUI("CPUGovernor"); - }); - }} - /> - - } + - {/* Battery */} -
- Battery -
- {get_value(CHARGE_NOW_BATT) != null && get_value(CHARGE_FULL_BATT) != null && - eggCount++} - focusable={false}> - {get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%) - - } - {get_value(CHARGE_FULL_BATT) != null && get_value(CHARGE_DESIGN_BATT) != null && - eggCount++} - focusable={false}> - {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) - - } - {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_current != null && - { - if (value) { - set_value(CHARGE_RATE_BATT, 2500); - reloadGUI("BATTChargeRateToggle"); - } else { - set_value(CHARGE_RATE_BATT, null); - backend.resolve(backend.unsetBatteryChargeRate(), (_: any[]) => { - reloadGUI("BATTUnsetChargeRate"); - }); - } - }} - /> - { get_value(CHARGE_RATE_BATT) != null && { - backend.log(backend.LogLevel.Debug, "Charge rate is now " + val.toString()); - const rateNow = get_value(CHARGE_RATE_BATT); - if (val != rateNow) { - backend.resolve(backend.setBatteryChargeRate(val), - (rate: number) => { - set_value(CHARGE_RATE_BATT, rate); - reloadGUI("BATTChargeRate"); - }); - } - }} - />} - } - {chargeModeOptions.length != 0 && - { - if (value) { - set_value(CHARGE_MODE_BATT, chargeModeOptions[0].data as string); - reloadGUI("BATTChargeModeToggle"); - } else { - set_value(CHARGE_MODE_BATT, null); - backend.resolve(backend.unsetBatteryChargeMode(), (_: any[]) => { - reloadGUI("BATTUnsetChargeMode"); - }); - } - }} - /> - {get_value(CHARGE_MODE_BATT) != null && - { - return val.data == get_value(CHARGE_MODE_BATT); - })} - strDefaultLabel={get_value(CHARGE_MODE_BATT)} - onChange={(elem: SingleDropdownOption) => { - backend.log(backend.LogLevel.Debug, "Charge mode dropdown selected " + elem.data.toString()); - backend.resolve(backend.setBatteryChargeMode(elem.data as string), (mode: string) => { - set_value(CHARGE_MODE_BATT, mode); - reloadGUI("BATTChargeMode"); - }); - }} - /> - } - } - - eggCount++} - focusable={false}> - {get_value(CURRENT_BATT)} mA - - + + + {/* Persistence */}
Miscellaneous @@ -647,9 +235,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { eggCount++} - focusable={false}> + label="Profile"> {get_value(NAME_GEN)} From d33b657e8f2afee5848219cfe7ada7efc92a9c4c Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 7 Jan 2023 20:09:26 -0500 Subject: [PATCH 27/44] Add pnpm lock file to make Decky CI happy --- pnpm-lock.yaml | 931 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 pnpm-lock.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..b5caf79 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,931 @@ +lockfileVersion: 5.4 + +specifiers: + '@rollup/plugin-commonjs': ^21.1.0 + '@rollup/plugin-json': ^4.1.0 + '@rollup/plugin-node-resolve': ^13.2.1 + '@rollup/plugin-replace': ^4.0.0 + '@rollup/plugin-typescript': ^8.3.2 + '@types/react': 16.14.0 + '@types/webpack': ^5.28.0 + decky-frontend-lib: 3.* + react-icons: ^4.4.0 + rollup: ^2.70.2 + rollup-plugin-import-assets: ^1.1.1 + shx: ^0.3.4 + tslib: ^2.4.0 + typescript: ^4.6.4 + usdpl-front: file:./src/usdpl_front + +dependencies: + decky-frontend-lib: 3.18.5 + react-icons: 4.7.1 + usdpl-front: file:src/usdpl_front + +devDependencies: + '@rollup/plugin-commonjs': 21.1.0_rollup@2.79.1 + '@rollup/plugin-json': 4.1.0_rollup@2.79.1 + '@rollup/plugin-node-resolve': 13.3.0_rollup@2.79.1 + '@rollup/plugin-replace': 4.0.0_rollup@2.79.1 + '@rollup/plugin-typescript': 8.5.0_sbiskyiysxhldmns7rmnvoiszu + '@types/react': 16.14.0 + '@types/webpack': 5.28.0 + rollup: 2.79.1 + rollup-plugin-import-assets: 1.1.1_rollup@2.79.1 + shx: 0.3.4 + tslib: 2.4.1 + typescript: 4.9.4 + +packages: + + /@jridgewell/gen-mapping/0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping': 0.3.17 + dev: true + + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map/0.3.2: + resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + dependencies: + '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 + dev: true + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@rollup/plugin-commonjs/21.1.0_rollup@2.79.1: + resolution: {integrity: sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^2.38.3 + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 7.2.3 + is-reference: 1.2.1 + magic-string: 0.25.9 + resolve: 1.22.1 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-json/4.1.0_rollup@2.79.1: + resolution: {integrity: sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-node-resolve/13.3.0_rollup@2.79.1: + resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^2.42.0 + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + '@types/resolve': 1.17.1 + deepmerge: 4.2.2 + is-builtin-module: 3.2.0 + is-module: 1.0.0 + resolve: 1.22.1 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-replace/4.0.0_rollup@2.79.1: + resolution: {integrity: sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + magic-string: 0.25.9 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-typescript/8.5.0_sbiskyiysxhldmns7rmnvoiszu: + resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + rollup: ^2.14.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + tslib: + optional: true + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + resolve: 1.22.1 + rollup: 2.79.1 + tslib: 2.4.1 + typescript: 4.9.4 + dev: true + + /@rollup/pluginutils/3.1.0_rollup@2.79.1: + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.1 + dev: true + + /@types/eslint-scope/3.7.4: + resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} + dependencies: + '@types/eslint': 8.4.10 + '@types/estree': 0.0.51 + dev: true + + /@types/eslint/8.4.10: + resolution: {integrity: sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==} + dependencies: + '@types/estree': 0.0.51 + '@types/json-schema': 7.0.11 + dev: true + + /@types/estree/0.0.39: + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + dev: true + + /@types/estree/0.0.51: + resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + dev: true + + /@types/estree/1.0.0: + resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + dev: true + + /@types/json-schema/7.0.11: + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + dev: true + + /@types/node/18.11.18: + resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + dev: true + + /@types/prop-types/15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + dev: true + + /@types/react/16.14.0: + resolution: {integrity: sha512-jJjHo1uOe+NENRIBvF46tJimUvPnmbQ41Ax0pEm7pRvhPg+wuj8VMOHHiMvaGmZRzRrCtm7KnL5OOE/6kHPK8w==} + dependencies: + '@types/prop-types': 15.7.5 + csstype: 3.1.1 + dev: true + + /@types/resolve/1.17.1: + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + dependencies: + '@types/node': 18.11.18 + dev: true + + /@types/webpack/5.28.0: + resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==} + dependencies: + '@types/node': 18.11.18 + tapable: 2.2.1 + webpack: 5.75.0 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + - webpack-cli + dev: true + + /@webassemblyjs/ast/1.11.1: + resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + dev: true + + /@webassemblyjs/floating-point-hex-parser/1.11.1: + resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} + dev: true + + /@webassemblyjs/helper-api-error/1.11.1: + resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} + dev: true + + /@webassemblyjs/helper-buffer/1.11.1: + resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} + dev: true + + /@webassemblyjs/helper-numbers/1.11.1: + resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode/1.11.1: + resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} + dev: true + + /@webassemblyjs/helper-wasm-section/1.11.1: + resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + dev: true + + /@webassemblyjs/ieee754/1.11.1: + resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128/1.11.1: + resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8/1.11.1: + resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} + dev: true + + /@webassemblyjs/wasm-edit/1.11.1: + resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/helper-wasm-section': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-opt': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + '@webassemblyjs/wast-printer': 1.11.1 + dev: true + + /@webassemblyjs/wasm-gen/1.11.1: + resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wasm-opt/1.11.1: + resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + dev: true + + /@webassemblyjs/wasm-parser/1.11.1: + resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wast-printer/1.11.1: + resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@xtuc/ieee754/1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long/4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /acorn-import-assertions/1.8.0_acorn@8.8.1: + resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.8.1 + dev: true + + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv-keywords/3.5.2_ajv@6.12.6: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001442 + electron-to-chromium: 1.4.284 + node-releases: 2.0.8 + update-browserslist-db: 1.0.10_browserslist@4.21.4 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /builtin-modules/3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite/1.0.30001442: + resolution: {integrity: sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==} + dev: true + + /chrome-trace-event/1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /commander/2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commondir/1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /csstype/3.1.1: + resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + dev: true + + /decky-frontend-lib/3.18.5: + resolution: {integrity: sha512-CTIJs61La17spws5IzAbLbZ/Bqe+gYgnO6xOrolK1QZh7ZbZeoQ67dtnI0zqRMMC10J8H7jPdqmQnwGN10/bzw==} + dev: false + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: true + + /electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + dev: true + + /enhanced-resolve/5.12.0: + resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.10 + tapable: 2.2.1 + dev: true + + /es-module-lexer/0.9.3: + resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker/0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: true + + /estree-walker/1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /events/3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /glob-to-regexp/0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /interpret/1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true + + /is-builtin-module/3.2.0: + resolution: {integrity: sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: true + + /is-module/1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + + /is-reference/1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.0 + dev: true + + /jest-worker/27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 18.11.18 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /loader-runner/4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + dev: true + + /neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /node-releases/2.0.8: + resolution: {integrity: sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==} + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /randombytes/2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /react-icons/4.7.1: + resolution: {integrity: sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==} + peerDependencies: + react: '*' + dev: false + + /rechoir/0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.22.1 + dev: true + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /rollup-plugin-import-assets/1.1.1_rollup@2.79.1: + resolution: {integrity: sha512-u5zJwOjguTf2N+wETq2weNKGvNkuVc1UX/fPgg215p5xPvGOaI6/BTc024E9brvFjSQTfIYqgvwogQdipknu1g==} + peerDependencies: + rollup: '>=1.9.0' + dependencies: + rollup: 2.79.1 + rollup-pluginutils: 2.8.2 + url-join: 4.0.1 + dev: true + + /rollup-pluginutils/2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + dependencies: + estree-walker: 0.6.1 + dev: true + + /rollup/2.79.1: + resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /schema-utils/3.1.1: + resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.11 + ajv: 6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + dev: true + + /serialize-javascript/6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + dependencies: + randombytes: 2.1.0 + dev: true + + /shelljs/0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: true + + /shx/0.3.4: + resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==} + engines: {node: '>=6'} + hasBin: true + dependencies: + minimist: 1.2.7 + shelljs: 0.8.5 + dev: true + + /source-map-support/0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: true + + /supports-color/8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /tapable/2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /terser-webpack-plugin/5.3.6_webpack@5.75.0: + resolution: {integrity: sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.17 + jest-worker: 27.5.1 + schema-utils: 3.1.1 + serialize-javascript: 6.0.0 + terser: 5.16.1 + webpack: 5.75.0 + dev: true + + /terser/5.16.1: + resolution: {integrity: sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.2 + acorn: 8.8.1 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /typescript/4.9.4: + resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /update-browserslist-db/1.0.10_browserslist@4.21.4: + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.4 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /url-join/4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + dev: true + + /watchpack/2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.10 + dev: true + + /webpack-sources/3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack/5.75.0: + resolution: {integrity: sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.4 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + acorn: 8.8.1 + acorn-import-assertions: 1.8.0_acorn@8.8.1 + browserslist: 4.21.4 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.12.0 + es-module-lexer: 0.9.3 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.10 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.1.1 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.6_webpack@5.75.0 + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + file:src/usdpl_front: + resolution: {directory: src/usdpl_front, type: directory} + name: usdpl-front + version: 0.7.0 + dev: false From 8bc9c7b2d82dbd2841c5472c0de7f68398edf87d Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Tue, 10 Jan 2023 20:54:33 -0500 Subject: [PATCH 28/44] Add support for user-translated strings in the UI --- backend/Cargo.lock | 83 +++++++- backend/Cargo.toml | 8 +- backend/src/main.rs | 2 + backend/src/settings/generic/battery.rs | 10 +- backend/src/settings/generic/cpu.rs | 7 +- backend/src/settings/steam_deck/battery.rs | 40 +--- backend/src/settings/steam_deck/cpu.rs | 9 +- package.json | 16 +- pnpm-lock.yaml | 24 +-- src/backend.ts | 10 +- src/components/battery.tsx | 23 ++- src/components/cpus.tsx | 39 ++-- src/components/debug.tsx | 9 +- src/components/gpu.tsx | 23 ++- src/index.tsx | 11 +- src/usdpl_front/package.json | 2 +- src/usdpl_front/usdpl_front.d.ts | 22 ++ src/usdpl_front/usdpl_front.js | 78 +++++-- src/usdpl_front/usdpl_front_bg.wasm | Bin 84394 -> 92157 bytes src/usdpl_front/usdpl_front_bg.wasm.d.ts | 3 + translations/pt.pot | 229 +++++++++++++++++++++ translations/test.mo | Bin 0 -> 2116 bytes translations/test.po | 229 +++++++++++++++++++++ 23 files changed, 726 insertions(+), 151 deletions(-) create mode 100644 translations/pt.pot create mode 100644 translations/test.mo create mode 100644 translations/test.po diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 01c9e77..53a7aa6 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -265,6 +265,70 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -371,6 +435,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "gettext-ng" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2c86be871deb255ef65fc8395048a2505912c595f1eddc4da03aeb6fda5cf34" +dependencies = [ + "byteorder", + "encoding", +] + [[package]] name = "glob" version = "0.3.0" @@ -1301,13 +1375,14 @@ dependencies = [ [[package]] name = "usdpl-back" -version = "0.7.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58928ed65332c30b9b9be5140fcdab97e45db679a5845d829aa26492765272e5" +checksum = "32af4c47bfeca1d75de693be983edc2ecfee10e71f138933c959ea5f97ca1a64" dependencies = [ "async-recursion", "async-trait", "bytes", + "gettext-ng", "hex", "log", "obfstr", @@ -1318,9 +1393,9 @@ dependencies = [ [[package]] name = "usdpl-core" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862153581fac266458521f49e5906a71c1eee1665cb4c7d71e9586bd34b45394" +checksum = "f3904ca38aca189c68a6bc876cf73de7cc60003476b4e118012ae7eb783c1700" dependencies = [ "aes-gcm-siv", "base64", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index c289281..8bbfa40 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -2,11 +2,17 @@ name = "powertools-rs" version = "1.1.0" edition = "2021" +authors = ["NGnius (Graham) "] +description = "Backend (superuser) functionality for PowerTools" +license = "GPL-3.0-only" +repository = "https://github.com/NGnius/PowerTools" +keywords = ["utility", "power-management", "root", "decky"] +readme = "../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -usdpl-back = { version = "0.7.2", features = ["blocking"]} +usdpl-back = { version = "0.9.0", features = ["blocking"] }#, path = "../../usdpl-rs/usdpl-back"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/backend/src/main.rs b/backend/src/main.rs index d8b4397..43e9696 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -52,6 +52,8 @@ fn main() -> Result<(), ()> { println!("Logging to: {:?}", log_filepath); log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); + log::info!("Current dir `{}`", std::env::current_dir().unwrap().display()); + println!("Current dir `{}`", std::env::current_dir().unwrap().display()); let _limits_handle = crate::settings::limits_worker_spawn(); log::info!("Detected device automatically, starting with driver: {:?} (This can be overriden)", crate::settings::auto_detect_provider()); diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index 1ca4cc6..1555f4a 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -26,18 +26,10 @@ impl Battery { fn read_f64>(path: P) -> Result { let path = path.as_ref(); match usdpl_back::api::files::read_single::<_, f64, _>(path) { - Err((Some(e), None)) => Err(SettingError { + Err(e) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::Battery, }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", path.display(), e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - path.display() - ), // this value is in uA, while it's set in mA // so convert this to mA for consistency Ok(val) => Ok(val / 1000.0), diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index b4bba83..0ae3c25 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -273,15 +273,10 @@ impl Cpu { // NOTE: this eats errors let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { Ok(s) => s, - Err((Some(e), None)) => { + Err(e) => { log::warn!("Error getting available CPU governors: {}", e); return vec![]; }, - Err((None, Some(e))) => { - log::warn!("Error getting available CPU governors: {}", e); - return vec![]; - }, - Err(_) => return vec![], }; gov_str.split(' ').map(|s| s.to_owned()).collect() } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index c2fdb60..5a7f745 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -113,18 +113,10 @@ impl Battery { pub fn read_current_now() -> Result { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) { - Err((Some(e), None)) => Err(SettingError { + Err(e) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), setting: crate::settings::SettingVariant::Battery, }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CURRENT_NOW_PATH - ), // this value is in uA, while it's set in mA // so convert this to mA for consistency Ok(val) => Ok(val / 1000), @@ -133,18 +125,10 @@ impl Battery { pub fn read_charge_now() -> Result { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { + Err(e) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), setting: crate::settings::SettingVariant::Battery, }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), // convert to Wh Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), } @@ -152,18 +136,10 @@ impl Battery { pub fn read_charge_full() -> Result { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) { - Err((Some(e), None)) => Err(SettingError { + Err(e) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), setting: crate::settings::SettingVariant::Battery, }), - Err((None, Some(e))) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), // convert to Wh Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), } @@ -171,18 +147,10 @@ impl Battery { pub fn read_charge_design() -> Result { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { - Err((Some(e), None)) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }), - Err((None, Some(e))) => Err(SettingError { + Err(e) => Err(SettingError { msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), setting: crate::settings::SettingVariant::Battery, }), - Err(_) => panic!( - "Invalid error while reading from `{}`", - BATTERY_CHARGE_NOW_PATH - ), // convert to Wh Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE), } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 83a1909..2c3544a 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -355,15 +355,10 @@ impl Cpu { // NOTE: this eats errors let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { Ok(s) => s, - Err((Some(e), None)) => { + Err(e) => { log::warn!("Error getting available CPU governors: {}", e); return vec![]; - }, - Err((None, Some(e))) => { - log::warn!("Error getting available CPU governors: {}", e); - return vec![]; - }, - Err(_) => return vec![], + } }; gov_str.split(' ').map(|s| s.to_owned()).collect() } diff --git a/package.json b/package.json index e811299..acca2f6 100644 --- a/package.json +++ b/package.json @@ -27,20 +27,20 @@ "devDependencies": { "@rollup/plugin-commonjs": "^21.1.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.2.1", + "@rollup/plugin-node-resolve": "^13.3.0", "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-typescript": "^8.3.2", + "@rollup/plugin-typescript": "^8.5.0", "@types/react": "16.14.0", "@types/webpack": "^5.28.0", - "rollup": "^2.70.2", + "rollup": "^2.79.1", "rollup-plugin-import-assets": "^1.1.1", "shx": "^0.3.4", - "tslib": "^2.4.0", - "typescript": "^4.6.4" + "tslib": "^2.4.1", + "typescript": "^4.9.4" }, "dependencies": { - "decky-frontend-lib": "3.*", - "react-icons": "^4.4.0", - "usdpl-front": "file:./src/usdpl_front" + "decky-frontend-lib": "~3.18.5", + "react-icons": "^4.7.1", + "usdpl-front": "file:src/usdpl_front" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b5caf79..e88971e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,19 +3,19 @@ lockfileVersion: 5.4 specifiers: '@rollup/plugin-commonjs': ^21.1.0 '@rollup/plugin-json': ^4.1.0 - '@rollup/plugin-node-resolve': ^13.2.1 + '@rollup/plugin-node-resolve': ^13.3.0 '@rollup/plugin-replace': ^4.0.0 - '@rollup/plugin-typescript': ^8.3.2 + '@rollup/plugin-typescript': ^8.5.0 '@types/react': 16.14.0 '@types/webpack': ^5.28.0 - decky-frontend-lib: 3.* - react-icons: ^4.4.0 - rollup: ^2.70.2 + decky-frontend-lib: ~3.18.5 + react-icons: ^4.7.1 + rollup: ^2.79.1 rollup-plugin-import-assets: ^1.1.1 shx: ^0.3.4 - tslib: ^2.4.0 - typescript: ^4.6.4 - usdpl-front: file:./src/usdpl_front + tslib: ^2.4.1 + typescript: ^4.9.4 + usdpl-front: file:src/usdpl_front dependencies: decky-frontend-lib: 3.18.5 @@ -672,8 +672,8 @@ packages: engines: {node: '>=8.6'} dev: true - /punycode/2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + /punycode/2.2.0: + resolution: {integrity: sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==} engines: {node: '>=6'} dev: true @@ -860,7 +860,7 @@ packages: /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.1.1 + punycode: 2.2.0 dev: true /url-join/4.0.1: @@ -927,5 +927,5 @@ packages: file:src/usdpl_front: resolution: {directory: src/usdpl_front, type: directory} name: usdpl-front - version: 0.7.0 + version: 0.9.0 dev: false diff --git a/src/backend.ts b/src/backend.ts index 70f1fee..26d88f4 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -1,4 +1,4 @@ -import {init_usdpl, target_usdpl, init_embedded, call_backend} from "usdpl-front"; +import {init_usdpl, target_usdpl, init_embedded, call_backend, init_tr} from "usdpl-front"; const USDPL_PORT: number = 44443; @@ -22,6 +22,14 @@ export async function initBackend() { await init_embedded(); init_usdpl(USDPL_PORT); console.log("USDPL started for framework: " + target_usdpl()); + const user_locale = + navigator.languages && navigator.languages.length + ? navigator.languages[0] + : navigator.language; + console.log("POWERTOOLS: locale", user_locale); + let mo_path = "../plugins/PowerTools/translations/" + user_locale.toString() + ".mo"; + await init_tr(mo_path); + //await init_tr("../plugins/PowerTools/translations/test.mo"); //setReady(true); } diff --git a/src/components/battery.tsx b/src/components/battery.tsx index b35cac2..7008156 100644 --- a/src/components/battery.tsx +++ b/src/components/battery.tsx @@ -10,6 +10,7 @@ import { staticClasses, } from "decky-frontend-lib"; import * as backend from "../backend"; +import { tr } from "usdpl-front"; import { LIMITS_INFO, CHARGE_DESIGN_BATT, @@ -38,25 +39,25 @@ export class Battery extends Component<{}> { return ( {/* Battery */}
- Battery + {tr("Battery")}
{get_value(CHARGE_NOW_BATT) != null && get_value(CHARGE_FULL_BATT) != null && + label={tr("Now (Charge)")}> {get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%) } {get_value(CHARGE_FULL_BATT) != null && get_value(CHARGE_DESIGN_BATT) != null && + label={tr("Max (Design)")}> {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) } {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_current != null && { if (value) { set_value(CHARGE_RATE_BATT, 2500); @@ -70,7 +71,7 @@ export class Battery extends Component<{}> { }} /> { get_value(CHARGE_RATE_BATT) != null && { {chargeModeOptions.length != 0 && { if (value) { set_value(CHARGE_MODE_BATT, chargeModeOptions[0].data as string); @@ -108,10 +109,10 @@ export class Battery extends Component<{}> { }} /> {get_value(CHARGE_MODE_BATT) != null && { return val.data == get_value(CHARGE_MODE_BATT); @@ -129,7 +130,7 @@ export class Battery extends Component<{}> { } + label={tr("Current")}> {get_value(CURRENT_BATT)} mA diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx index 1c97d87..cbb14a5 100644 --- a/src/components/cpus.tsx +++ b/src/components/cpus.tsx @@ -10,6 +10,7 @@ import { staticClasses, } from "decky-frontend-lib"; import * as backend from "../backend"; +import { tr } from "usdpl-front"; import { LIMITS_INFO, SMT_CPU, @@ -61,13 +62,13 @@ export class Cpus extends Component<{}, CpuState> { return ( {/* CPU */}
- CPU + {tr("CPU")}
{ //advancedMode = advanced; this.setState((state) => { @@ -84,8 +85,8 @@ export class Cpus extends Component<{}, CpuState> { {!advancedMode && smtAllowed && { backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); //const cpus = get_value(ONLINE_CPUS); @@ -102,7 +103,7 @@ export class Cpus extends Component<{}, CpuState> { } {!advancedMode && { {!advancedMode && { if (value) { if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { @@ -161,7 +162,7 @@ export class Cpus extends Component<{}, CpuState> { } {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null && {get_value(CLOCK_MIN_CPU) != null && { } {!advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null && {get_value(CLOCK_MAX_CPU) != null && { {/* CPU advanced mode */} {advancedMode && { {advancedMode && { backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); if (!get_value(SMT_CPU)) { @@ -262,8 +263,8 @@ export class Cpus extends Component<{}, CpuState> { {advancedMode && { if (value) { const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; @@ -290,7 +291,7 @@ export class Cpus extends Component<{}, CpuState> { } {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_min_limits != null && {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].min != null && { } {advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].clock_max_limits != null && {get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex].max != null && { } {advancedMode && governorOptions.length != 0 && { backend.log(backend.LogLevel.Debug, "POWERTOOLS: array item " + val.toString()); diff --git a/src/components/debug.tsx b/src/components/debug.tsx index 05b254c..d942200 100644 --- a/src/components/debug.tsx +++ b/src/components/debug.tsx @@ -8,6 +8,7 @@ import { Router, } from "decky-frontend-lib"; import * as backend from "../backend"; +import { tr } from "usdpl-front"; import { BACKEND_INFO, DRIVER_INFO, @@ -25,11 +26,11 @@ export class Debug extends Component<{}> { function buildDebug() { return ({/* Version Info */}
- {eggCount % 10 == 9 ? "Ha! Nerd" : "Debug"} + {eggCount % 10 == 9 ? "Ha! Nerd" : tr("Debug")}
{ if (eggCount % 10 == 9) { // you know you're bored and/or conceited when you spend time adding an easter egg @@ -43,14 +44,14 @@ function buildDebug() { eggCount++}> {eggCount % 10 == 9 ? "<3 <3 <3" : target_usdpl()} eggCount++}> {eggCount % 10 == 9 ? "Tracy Chapman" : get_value(DRIVER_INFO)} diff --git a/src/components/gpu.tsx b/src/components/gpu.tsx index 0dd41d3..bcd9121 100644 --- a/src/components/gpu.tsx +++ b/src/components/gpu.tsx @@ -7,6 +7,7 @@ import { staticClasses, } from "decky-frontend-lib"; import * as backend from "../backend"; +import { tr } from "usdpl-front"; import { LIMITS_INFO, SLOW_PPT_GPU, @@ -30,13 +31,13 @@ export class Gpu extends Component<{}> { return ( {/* GPU */}
- GPU + {tr("GPU")}
{ ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.fast_ppt_limits != null ||(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) && { if (value) { if ((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.slow_ppt_limits != null) { @@ -59,7 +60,7 @@ export class Gpu extends Component<{}> { } { get_value(SLOW_PPT_GPU) != null && { {get_value(FAST_PPT_GPU) != null && { {((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits != null || (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_max_limits != null) && { if (value) { let clock_min_limits = (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.clock_min_limits; @@ -133,7 +134,7 @@ export class Gpu extends Component<{}> { } { get_value(CLOCK_MIN_GPU) != null && { {get_value(CLOCK_MAX_GPU) != null && { {(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control_capable && { backend.resolve(backend.setGpuSlowMemory(value), (val: boolean) => { set_value(SLOW_MEMORY_GPU, val); diff --git a/src/index.tsx b/src/index.tsx index 45e58c2..4ad0757 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -24,6 +24,7 @@ import { GiDrill } from "react-icons/gi"; //import * as python from "./python"; import * as backend from "./backend"; +import { tr } from "usdpl-front"; import { BACKEND_INFO, DRIVER_INFO, @@ -217,13 +218,13 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { {/* Persistence */}
- Miscellaneous + {tr("Miscellaneous")}
{ backend.log(backend.LogLevel.Debug, "Persist is now " + persist.toString()); backend.resolve( @@ -235,7 +236,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { + label={tr("Profile")}> {get_value(NAME_GEN)} @@ -278,7 +279,7 @@ export default definePlugin((serverApi: ServerAPI) => { lifetimeHook!.unregister(); startHook!.unregister(); serverApi.routerHook.removeRoute("/decky-plugin-test"); - backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, goodbye."); + backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, so long and thanks for all the fish."); }, }; }); diff --git a/src/usdpl_front/package.json b/src/usdpl_front/package.json index a769587..1bfd686 100644 --- a/src/usdpl_front/package.json +++ b/src/usdpl_front/package.json @@ -4,7 +4,7 @@ "NGnius (Graham) " ], "description": "Universal Steam Deck Plugin Library front-end designed for WASM", - "version": "0.7.0", + "version": "0.9.0", "license": "GPL-3.0-only", "repository": { "type": "git", diff --git a/src/usdpl_front/usdpl_front.d.ts b/src/usdpl_front/usdpl_front.d.ts index 8e30d2a..9477118 100644 --- a/src/usdpl_front/usdpl_front.d.ts +++ b/src/usdpl_front/usdpl_front.d.ts @@ -36,6 +36,25 @@ export function get_value(key: string): any; * @returns {Promise} */ export function call_backend(name: string, parameters: any[]): Promise; +/** +* Initialize translation strings for the front-end +* @param {string} locale +* @returns {Promise} +*/ +export function init_tr(locale: string): Promise; +/** +* Translate a phrase, equivalent to tr_n(msg_id, 0) +* @param {string} msg_id +* @returns {string} +*/ +export function tr(msg_id: string): string; +/** +* Translate a phrase, retrieving the plural form for `n` items +* @param {string} msg_id +* @param {number} n +* @returns {string} +*/ +export function tr_n(msg_id: string, n: number): string; export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; @@ -47,6 +66,9 @@ export interface InitOutput { readonly set_value: (a: number, b: number, c: number) => number; readonly get_value: (a: number, b: number) => number; readonly call_backend: (a: number, b: number, c: number, d: number) => number; + readonly init_tr: (a: number, b: number) => number; + readonly tr: (a: number, b: number, c: number) => void; + readonly tr_n: (a: number, b: number, c: number, d: number) => void; readonly __wbindgen_export_0: (a: number) => number; readonly __wbindgen_export_1: (a: number, b: number, c: number) => number; readonly __wbindgen_export_2: WebAssembly.Table; diff --git a/src/usdpl_front/usdpl_front.js b/src/usdpl_front/usdpl_front.js index be37538..943d2e7 100644 --- a/src/usdpl_front/usdpl_front.js +++ b/src/usdpl_front/usdpl_front.js @@ -253,6 +253,59 @@ export function call_backend(name, parameters) { return takeObject(ret); } +/** +* Initialize translation strings for the front-end +* @param {string} locale +* @returns {Promise} +*/ +export function init_tr(locale) { + const ptr0 = passStringToWasm0(locale, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.init_tr(ptr0, len0); + return takeObject(ret); +} + +/** +* Translate a phrase, equivalent to tr_n(msg_id, 0) +* @param {string} msg_id +* @returns {string} +*/ +export function tr(msg_id) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(msg_id, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + wasm.tr(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + return getStringFromWasm0(r0, r1); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_export_4(r0, r1); + } +} + +/** +* Translate a phrase, retrieving the plural form for `n` items +* @param {string} msg_id +* @param {number} n +* @returns {string} +*/ +export function tr_n(msg_id, n) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(msg_id, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + wasm.tr_n(retptr, ptr0, len0, n); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + return getStringFromWasm0(r0, r1); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_export_4(r0, r1); + } +} + function handleError(f, args) { try { return f.apply(this, args); @@ -260,7 +313,7 @@ function handleError(f, args) { wasm.__wbindgen_export_5(addHeapObject(e)); } } -function __wbg_adapter_57(arg0, arg1, arg2, arg3) { +function __wbg_adapter_58(arg0, arg1, arg2, arg3) { wasm.__wbindgen_export_6(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); } @@ -305,10 +358,6 @@ function getImports() { const ret = getStringFromWasm0(arg0, arg1); return addHeapObject(ret); }; - imports.wbg.__wbindgen_object_clone_ref = function(arg0) { - const ret = getObject(arg0); - return addHeapObject(ret); - }; imports.wbg.__wbindgen_string_get = function(arg0, arg1) { const obj = getObject(arg1); const ret = typeof(obj) === 'string' ? obj : undefined; @@ -317,6 +366,10 @@ function getImports() { getInt32Memory0()[arg0 / 4 + 1] = len0; getInt32Memory0()[arg0 / 4 + 0] = ptr0; }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; imports.wbg.__wbindgen_number_new = function(arg0) { const ret = arg0; return addHeapObject(ret); @@ -364,13 +417,6 @@ function getImports() { const ret = result; return ret; }; - imports.wbg.__wbg_url_74285ddf2747cb3d = function(arg0, arg1) { - const ret = getObject(arg1).url; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; imports.wbg.__wbg_text_1169d752cc697903 = function() { return handleError(function (arg0) { const ret = getObject(arg0).text(); return addHeapObject(ret); @@ -438,7 +484,7 @@ function getImports() { const a = state0.a; state0.a = 0; try { - return __wbg_adapter_57(a, state0.b, arg0, arg1); + return __wbg_adapter_58(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -476,8 +522,8 @@ function getImports() { imports.wbg.__wbindgen_throw = function(arg0, arg1) { throw new Error(getStringFromWasm0(arg0, arg1)); }; - imports.wbg.__wbindgen_closure_wrapper330 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 65, __wbg_adapter_26); + imports.wbg.__wbindgen_closure_wrapper385 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 71, __wbg_adapter_26); return addHeapObject(ret); }; @@ -536,7 +582,7 @@ export default init; // USDPL customization -const encoded = "AGFzbQEAAAABsAEaYAJ/fwF/YAJ/fwBgAX8AYAN/f38Bf2ADf39/AGAEf39/fwBgAX8Bf2AFf39/f38AYAABf2AEf39/fwF/YAAAYAV/f39/fwF/YAF/AX5gBn9/f39/fwF/YAZ/f39/f38AYAV/f35/fwBgBX9/fX9/AGAFf398f38AYAR/fn9/AGAEf31/fwBgBH98f38AYAJ+fwBgB39/f39/f38Bf2ADfn9/AX9gAXwBf2ACf38BfgLLCSQDd2JnGl9fd2JpbmRnZW5fb2JqZWN0X2Ryb3BfcmVmAAIDd2JnFV9fd2JpbmRnZW5fc3RyaW5nX25ldwAAA3diZxtfX3diaW5kZ2VuX29iamVjdF9jbG9uZV9yZWYABgN3YmcVX193YmluZGdlbl9zdHJpbmdfZ2V0AAEDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX25ldwAYA3diZxZfX3diaW5kZ2VuX2Jvb2xlYW5fZ2V0AAYDd2JnFV9fd2JpbmRnZW5fbnVtYmVyX2dldAABA3diZxJfX3diaW5kZ2VuX2lzX251bGwABgN3YmcXX193YmluZGdlbl9pc191bmRlZmluZWQABgN3YmcoX193YmdfaW5zdGFuY2VvZl9XaW5kb3dfYWNjOTdmZjlmNWQyYzdiNAAGA3diZxxfX3diZ19mZXRjaF8wZmUwNDkwNWNjY2ZjMmFhAAADd2JnKl9fd2JnX2luc3RhbmNlb2ZfUmVzcG9uc2VfZWFhNDI2MjIwODQ4YTM5ZQAGA3diZxpfX3diZ191cmxfNzQyODVkZGYyNzQ3Y2IzZAABA3diZxtfX3diZ190ZXh0XzExNjlkNzUyY2M2OTc5MDMABgN3YmcoX193YmdfbmV3d2l0aHN0cmFuZGluaXRfMDVkNzE4MDc4ODQyMGM0MAADA3diZxJfX3diaW5kZ2VuX2NiX2Ryb3AABgN3YmcgX193YmdfbmV3bm9hcmdzX2I1YjA2M2ZjNmMyZjAzNzYAAAN3YmcbX193YmdfY2FsbF85N2FlOWQ4NjQ1ZGMzODhiAAADd2JnGl9fd2JnX25ld18wYjliZmRkOTc1ODMyODRlAAgDd2JnFF9fd2JpbmRnZW5faXNfc3RyaW5nAAYDd2JnG19fd2JnX3NlbGZfNmQ0Nzk1MDZmNzJjNmE3MQAIA3diZx1fX3di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AklyDQAgAEGBCEkEQCACIAdBCGogAGpBgAggAGsQ0AEgAGohAAwBCyAAQYAIQcCGwAAQ6QIACyAAQYEITw0CIAshBCADIAdBCGogABDOAUUNAQsLIAdBoAhqJAAgEA8LIABBgAhB0IbAABDqAgALQY+FwABBKyAHQZgIakG8hcAAQfiIwAAQrgEAC+sMAgV/AX4jAEGgAmsiAyQAIAACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAS0AYEEBaw4EAQADBgILAAtB4JDAAEEjQbiawAAQ/wEACyABIAEpAwA3AzAgA0HQAGogAUEIakEoEIUDGiABIAEvAVw7AV4gARASNgI4IAFBOGoiBRCrASAFEK0BIANBrAFqQR82AgAgA0GkAWpBHjYCACADIAFB3gBqNgKoASADQZSbwAA2AqABIANBIDYCnAEgAyABQTBqNgKYASADQQM2AtwBIANCBDcCzAEgA0HomsAANgLIASADIANBmAFqNgLYASADQZACaiADQcgBahA/IAFBxABqIANBmAJqKAIANgIAIAEgAykDkAI3AjwgA0HIAWogA0HQAGpBKBCFAxogA0GYAWogA0HIAWoQdCADKAKYASIERQ0BIAMoApwBIQYgAUHQAGogAygCoAEiBzYCACABQcwAaiAGNgIAIAEgBDYCSCADQZgBaiAEIAcQNSADQdABaiIEIANBoAFqKAIANgIAIAMgAykDmAE3A8gBIANB+ABqIANByAFqEKkBIAQgA0GAAWooAgA2AgAgAyADKQN4NwPIASADIANByAFqEPMBNgKYASAFIANBmAFqEJ0BIAMoApgBIgRBJE8EQCAEEAALIANByABqIAEoAjwgAUHEAGooAgAgBRDhASADKAJMIQUgAygCSA0KIAEgBTYCVCADQUBrENsBIAMoAkBFDQYgASADKAJENgJYIAEgAUHYAGooAgAgAUHUAGooAgAQChBDNgJoCyADQThqIAFB6ABqIgQgAhCBAUEDIQUgAygCOCIGQQJGDQYgAygCPCEFIAQQmAEgBg0IIANBMGogBRDfASADKAI0IQUgAygCMEUNAQwICyADKAKcASEFDAkLIAEgBTYCaCADQShqIAQQ5AEgAygCKCEEIAFB8ABqIAMoAiwiBTYCACABIAQ2AmwgBA0BIAEgBRBDNgJ0CyAD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IANBIGogBCgCABBBIAEoArABIgUgASgCrAFGBEAgBiAFEOcBIAEoArABIQULIARBBGohBCABKAKoASAFQQR0aiIFIAMpAyA3AwAgBUEIaiADQShqKQMANwMAIAEgASgCsAFBAWo2ArABIAhBfGoiCA0ACyADIAc2AhgLIANBEGoQsgFB8O3AAC8BACEEIANBEGogAUGQAWoQxAEgASAJNwMQIAFBADYCCCABIAk3AwAgAUEAOgBgIAEgBDsBXCABIAMpAxA3AxggAUEgaiADQRhqKAIANgIAIAEgBikCADcCJCABQSxqIAZBCGooAgA2AgALIANBIGogASACECcgAygCIEUEQCADQSxqKAIAIQIgA0EoaigCACEFIAMoAiQhBCABEJwBIARFDQIgAyACEBg2AgwgAyAEIAJBBHRqIgY2AhwgAyAENgIYIAMgBTYCFCADIAQ2AhAgAkUNBEEAIQUgA0EgakEBciICQQdqIQgDQCAELQAAIgdBCkYEQCAEQRBqIQYMBQsgAiAEKQABNwAAIAggBEEIaikAADcAACADIAc6ACAgA0EgahBVIQcgA0EMaigCACAFIAcQGSAFQQFqIQUgBEEQaiIEIAZHDQALDAMLIAFBAzoAtAFBAAwFC0HgkMAAQSNByJzAABD/AQALQSEhBCAFQSRJDQIgBRAADAILIAMgBjYCGAsgA0EQahCnASADKAIMIQQLIAFBkAFqEK4CIAFBAToAtAFBAQshASAAIAQ2AgQgACABRTYCACADQTBqJAALkgUBB38CQAJAAn8CQCAAIAFrIAJJBEAgASACaiEFIAAgAmohAyACQQ9LDQEgAAwCCyACQQ9NBEAgACEDDAMLIABBACAAa0EDcSIFaiEEIAUEQCAAIQMgASEAA0AgAyAALQAAOgAAIABBAWohACADQQFqIgMgBEkNAAsLIAQgAiAFayICQXxxIgZqIQMCQCABIAVqIgVBA3EiAARAIAZBAUgNASAFQXxxIgdBBGohAUEAIABBA3QiCGtBGHEhCSAHKAIAIQADQCAEIAAgCHYgASgCACIAIAl0cjYCACABQQRqIQEgBEEEaiIEIANJDQALDAELIAZBAUgNACAFIQEDQCAEIAEoAgA2AgAgAUEEaiEBIARBBGoiBCADSQ0ACwsgAkEDcSECIAUgBmohAQwCCyADQXxxIQBBACAD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QCAEQQRqEIUCCyAEQRBqIQQgBUFwaiIFDQALCyADQRhqEK4CDAILIABBADYCACAAIA03AgQMAQsgACADKQMYNwIAIAAgBjYCDCAAQQhqIANBIGooAgA2AgALIANBQGskAAumBAIFfwF+IwBB0ABrIgMkACADQf8BOgAPIANBKGogASADQQ9qQQEgAigCIBEFAAJAAkACQAJAAkACQAJAIAMtAChBBEcEQCADKQMoIghC/wGDQgZSDQELQQIhBAJAAkACQAJAAkACQAJAAkAgAy0AD0F/ag4IBwYMAAUBAgQDC0EDIQQMCwtBBSEEDAoLIABBBToABAwKCyAAQQU6AAQMCQsgA0EoaiABIAIQPCADKAIoIgZFDQQgAygCNCEFIAMpAiwhCEEHIQQMBwsgA0EoaiABIAIQRSADKAIoIgYEQCADKAI0IQUgAykCLCEIQQQhBAwHCyAAIAMpAiw3AgQMBwsgA0EoaiABIAIQhgEgAykDKCEIIAMoAjAiBw0EDAMLIANBKGogASACEGIgAykDKCEIIAMoAjAiB0UNAiADQSBqIANBxABqKAIANgIAIANBGGogA0E8aikCADcDACADIAMpAjQ3AxAgAygCSCEFQQAhBAwECyAAQQg2AgAgACAINwIEDAULIAAgAykCLDcCBAwDCyAAIAg3AgQMAgsgA0EYaiADQTxqKAIANgIAIAMgAykCNDcDECADKAJAIQVBASEECyAAIAMpAxA3AhQgACAHNgIQIAAgCDcCCCAAIAY2AgQgACAENgIAIAAgBUEBajYCKCAAQSRqIANBIGooAgA2AgAgAEEcaiADQRhqKQMANwIADAELIABBCDYCAAsgA0HQAGokAAvpAwEGfyMAQTBrIgUkAAJAAkACQAJAAkAgASgCBCIDBEAgASgCACEHIANBf2pB/////wFxIgNBAWoiBkEHcSEEAn8gA0EHSQRAQQAhAyAHDAELIAdBPGohAiAGQfj///8DcSEGQQAhAwNAIAIoAgAgAkF4aigCACACQXBqKAIAIAJBaGooAgAgAkFgaigCACACQVhqKAIAIAJBUGooAgAgAkFIaigCACADampqampqamohAyACQUBrIQIgBkF4aiIGDQALIAJBRGoLIQIgBARAIAJBBGohAgNAIAIoAgAgA2ohAyACQQhqIQIgBEF/aiIEDQALCyABQRRq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QQBHC+cBAQJ/IwBBMGsiAiQAAn8CQAJAAkAgAC0AAEF8akH/AXEiA0ECIANBAkkbQQFrDgIBAgALIAJBJGpBADYCACACQeicwAA2AiAgAkIBNwIUIAJB9J3AADYCECABIAJBEGoQuQEMAgsgAkEkakEANgIAIAJB6JzAADYCICACQgE3AhQgAkHQncAANgIQIAEgAkEQahC5AQwBCyACIAA2AgwgAkEkakEBNgIAIAJCAjcCFCACQaidwAA2AhAgAkE4NgIsIAIgAkEoajYCICACIAJBDGo2AiggASACQRBqELkBCyACQTBqJAAL5wEBAn8jAEEwayICJAACfwJAAkACQCAALQAAQXxqQf8BcSIDQQIgA0ECSRtBAWsOAgECAAsgAkEkakEANgIAIAJB6JzAADYCICACQgE3AhQgAkHYnsAANgIQIAEgAkEQahC5AQwCCyACQSRqQQA2AgAgAkHonMAANgIgIAJCATcCFCACQbSewAA2AhAgASACQRBqELkBDAELIAIgADYCDCACQSRqQQE2AgAgAkICNwIUIAJBjJ7AADYCECACQTg2AiwgAiACQShqNgIgIAIgAkEMajYCKCABIAJBEGoQuQELIAJBMGokAAvPAQECfyMAQSBrIgMkAAJAAkAgASACaiICIAFJDQAgAEEEaigCACIBQQF0IgQgAiAEIAJLGyICQQggAkEISxsiAkF/c0EfdiEEAkAgAQRAIANBATYCGCADIAE2AhQgAyAAKAIANgIQDAELIANBADYCGAsgAyACIAQgA0EQahCJASADKAIEIQEgAygCAEUEQCAAIAE2AgAgAEEEaiACNgIADAILIANBCGooAgAiAEGBgICAeEYNASAARQ0AIAEgABD+AgALEI4CAAsgA0EgaiQAC88BAQJ/IwBBIGsiAyQAAkACQCABIAJqIgIgAUkNACAAQQRqKAIAIgFBAXQiBCACIAQgAksbIgJBCCACQQhLGyICQX9zQR92IQQCQCABBEAgA0EBNgIYIAMgATYCFCADIAAoAgA2AhAMAQsgA0EANgIYCyADIAIgBCADQRBqEIMBIAMoAgQhASADKAIARQRAIAAgATYCACAAQQRqIAI2AgAMAgsgA0EIaigCACIAQYGAgIB4Rg0BIABFDQAgASAAEP4CAAsQjgIACyADQSBqJAALzQEBA38jAEEgayIC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CyABRQ0CCyABIAIQ2wIMAgsgACABNgIEIABBCGpBADYCAAwCCyACCyIDBEAgACADNgIEIABBCGogATYCAEEADAILIAAgATYCBCAAQQhqIAI2AgALQQELNgIAC8oBAQJ/IwBB0AFrIgMkACAAKAIAIgAtAMgBIQQgAEEEOgDIAQJAIARBBEcEQCADQQhqIABByAEQhQMaIAMgAEHMAWooAAA2AAMgAyAAKADJATYCAEGwA0EIENsCIgBFDQEgACADQQhqQcgBEIUDIgAgBDoAyAEgAEEAOgCoAyAAIAI2AqQDIAAgATYCoAMgACADKAIANgDJASAAQcwBaiADKAADNgAAIAAQlQEgA0HQAWokAA8LQdSPwABBFRD5AgALQbADQQgQ/gIAC60BAQF/AkAgAgRAAn8CQAJAAkAgAUEATgRAIAMoAghFDQIgAygCBCIEDQEgAQ0DIAIMBAsgAEEIakEANgIADAULIAMoAgAgBCACIAEQzQIMAgsgAQ0AIAIMAQsgASACENsCCyIDBEAgACADNgIEIABBCGogATYCACAAQQA2AgAPCyAAIAE2AgQgAEEIaiACNgIADAELIAAgATYCBCAAQQhqQQA2AgALIABBATYCAAunAQEFfyAAQQhqIABBDGoiASgCACICIAIQ0wEgASgCACIFIAJBAXRGBEAgACgCACIDIAAoAgQiAUsEQCABIAIgA2siBE8EQCAAKAIIIgIgBSAEayIBQQJ0aiACIANBAnRqIARBAnQQhQMaIAAgATYCAA8LIAAoAggiAyACQQJ0aiADIAFBAnQQhQMaIAAgASACajYCBAsPC0GutcAAQStB3LXAABD/AQALrAEBA38jAEEwayICJAAgAUEEaiEDIAEoAgRFBEAgASgCACEBIAJBEGoiBEEANgIAIAJCATcDCCACIAJBCGo2AhQgAkEoaiABQRBqKQIANwMAIAJBIGogAUEIaikCADcDACACIAEpAgA3AxggAkEUakG4wMAAIAJBGGoQNxogA0EIaiAEKAIANgIAIAMgAikDCDcCAAsgAEG8yMAANgIEIAAgAzYCACACQTBqJAALmgEBAX8jAEEwayIDJAAgA0GACBDNASADQQA2AhAgAyADKQMANwMIIANBGGogASACIANBCGoQJAJAIAMtABhBA0YEQCADQShqIANBEGooAgA2AgAgAyAD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ABCkASAAQQRqIQAgAkF8aiICDQALCyABQRBqJAALkQEBAX8gACgCACIAIAAoAgBBf2oiATYCAAJAIAENAAJAIABBDGooAgBBAkYNACAAQRBqKAIAIgFBJEkNACABEAALIABBGGooAgAiAQRAIABBFGooAgAgASgCDBECAAsgAEEgaigCAARAIABBHGoQwwIgAEEoahDDAgsgACAAKAIEQX9qIgE2AgQgAQ0AIAAQKwsLlAEBBH8jAEEgayIBJAAgARCSASABQQA6ABwgAUEANgIQIAFCADcDCCABIAEpAwA3AhQgAUEIahDxASECIAFBIDYCCCABQQhqKAIAEBwhAyACIAIoAgBBAWoiBDYCACAEBEAgAEEIaiACEIYCIAAgAzYCBCAAIAI2AgAgASgCCCIAQSRPBEAgABAACyABQSBqJAAPCwALsAEBA38jAEEQayIBJAAgACgCACICQRRqKAIAIQMCQAJ/AkACQCACKAIEDgIAAQMLIAMNAkEAIQJB0MDAAAwBCyADDQEgAigCACIDKAIEIQIgAygCAAshAyABIAI2AgQgASADNgIAIAFB8MjAACAAKAIEIgEoAgggACgCCCABLQAQEH8ACyABQQA2AgQgASACNgIAIAFB3MjAACAAKAIEIgEoAgggACgCCCABLQAQEH8AC5cBAQJ/IwBBEGsiASQAIAAoAgBFBEAgAEF/NgIAIAACf0EAIAAoAgQiAkUNABogAEEAOgAUIAEgAEEMajYCBCACIAFBBGogAEEIaigCACgCDBEAAEUEQCAAQQRqIgIQ9gEgAkEANgIACyAAKAIAQQFqCzYCACABQRBqJAAPC0HsuMAAQRAgAUEIakH8uMAAQai9wAAQrgEAC5ABAQF/AkACQAJAAkACQCAALQBgDgUDBAQAAQQLIABB6ABqEJgBDAELIABB9ABqEJgBIAAoAmgiAUEkSQ0AIAEQAAsgACgCWCIBQSRPBEAgARAACyAAKAJUIgFBJE8EQCABEAALIABByABqEK4CIABBPGoQrgIgACgCOCIAQSRJDQEgABAADwsgAEEIahDJAQsLhAEBAX8jAEEQayICJAAgAkHoscAAQQQQATYCCCACIAEEfyABKAIAEAIFQSALNgIMIAIgACACQQhqIAJBDGoQ0QEgAigCDCIAQSRPBEAgABAACyACKAIIIgBBJE8EQCAA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DAELIABBATYCACAAIAQ3AgQLIANBEGokAAt+AQF/IwBBEGsiASQAIAFB7LHAAEEGEAE2AgggAUHImsAAQQQQATYCDCABIAAgAUEIaiABQQxqENEBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALhwECAX8BfiMAQRBrIgEkAEHw7sAAKQMAUARAQYDvwAACfgJAIABFDQAgACkDACAAQgA3AwBCAVINACAAKQMIIQIgACkDEAwBCyABQgI3AwggAUIBNwMAIAEpAwAhAiABKQMICzcDAEH47sAAIAI3AwBB8O7AAEIBNwMACyABQRBqJABB+O7AAAt+AQF/IwBBEGsiASQAIAFB8rHAAEEEEAE2AgggAUGIssAAQQQQATYCDCABIAAgAUEIaiABQQxqENEBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALgAEBAX8jAEFAaiIFJAAgBSABNgIMIAUgADYCCCAFIAM2AhQgBSACNgIQIAVBLGpBAjYCACAFQTxqQfoANgIAIAVCAjcCHCAFQazRwAA2AhggBUH5ADYCNCAFIAVBMGo2AiggBSAFQRBqNgI4IAUgBUEIajYCMCAFQRhqIAQQjwIAC2wBAX8jAEEwayIDJAAgAyABNgIoIAMgATYCJCADIAA2AiAgA0EIaiADQSBqEJUCIANBEGogAygCCCADKAIMEMsCIANBKGogA0EYaigCADYCACADIAMpAxA3AyAgA0EgaiACELUBIANBMGokAAt8AQF/IAAtAAQhASAALQAFBEAgAUH/AXEhASAAAn9BASABDQAaIAAoAgAiAS0AAEEEcUUEQCABKAIYQePRwABBAiABQRxqKAIAKAIMEQMADAELIAEoAhhB4tHAAEEBIAFBHGooAgAoAgwRAwALIgE6AAQLIAFB/wFxQQBHC2kBAX8jAEEwayICJAAgAiABNgIoIAIgATYCJCACIAA2AiAgAkEIaiACQSBqEJUCIAJBEGogAigCCCACKAIMEMsCIAJBKGogAkEYaigCADYCACACIAIpAxA3AyAgAkEgahBbIAJBMGokAAtpAQR/IwBBEGsiAyQAIAAoAgwiASAAKAIIIgJHBEAgASACa0ECdkECdCEBA0AgAigCACIEQSRPBEAgBBAACyACQQRqIQIgAUF8aiIBDQALCyADIAApAgA3AwggA0EIahCEAiADQRBqJAALdwEBfwJAAkAgAEUNACAAKAIAIQEgAEEANgIAIAAoAgQhAAJAIAEOAgECAAsgAEEkSQ0AIAAQAAsQTyEAC0G07sAAKAIAIQFBtO7AACAANgIAQbDuwAAoAgBBsO7AAEEBNgIARSABQSRJckUEQCABEAALQbTuwAALfAEDfyAAIAAQiwMiAEEIEMwCIABrIgIQiQMhAEGc8sAAIAEgAmsiATYCAEGk8sAAIAA2AgAgACABQQFyNgIEQQhBCBDMAiECQRRBCBDMAiEDQRBBCBDMAiEEIAAgARCJAyAEIAMgAkEIa2pqNgIEQcDywABBgICAATYCAAtpAQF/IwBBIGsiAiQAQYzuwAAoAgBFBEBB5ITAAEErQaSJwAAQ/wEACyACQRhqIABBCGooAgA2AgAgAiAAKQIANwMQIAJBCGogAkEQaiABEE0gAigCCCEAIAIoAgwgAkEgaiQAQSEgABsLbAEEfyMAQSBrIgIkAEEBIQMCQCAAIAEQUw0AIAFBHGooAgAhBCABKAIYIAJBADYCHCACQfzPwAA2AhggAkIBNwIMIAJBrNDAADYCCCAEIAJBCGoQNw0AIABBBGogARBTIQMLIAJBIGokACADC2sBAn8jAEEgayICJAAgAkEIaiABKAIAEAMCQCACKAIIIgMEQCACKAIMIQEgAiADNgIQIAIgATYCGCACIAE2AhQgAiACQRBqEJUCIAAgAigCACACKAIEEMsCDAELIABBADYCAAsgAkEgaiQAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHlADYCACADQgI3AgwgA0GA0cAANgIIIANB5QA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACEI8CAAtWAQJ/IwBBIGsiAiQAIABBHGooAgAhAyAAKAIYIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAMgAkEIahA3IAJBIGokAAtvAQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EcakECNgIAIANBLGpB5QA2AgAgA0ICNwIMIANBsNXAADYCCCADQeUANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANBCGogAhCPAgALbwEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBHGpBAjYCACADQSxqQeUANgIAIANCAjcCDCADQdDVwAA2AgggA0HlADYCJCADIANBIGo2AhggAyADQQRqNgIoIAMgAzYCICADQQhqIAIQjwIAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHlADYCACADQgI3AgwgA0GE1sAANgIIIANB5QA2AiQgAyADQSBqNgIYIAMgA0EEajYCKCADIAM2AiAgA0EIaiACEI8CAAtuAQF/AkACQAJAAkAgAC0AqAMOBAECAgACCyAAQdABahBeIAAoAqADIgFBJE8EQCABEAALIAAoAqQDIgBBI00NAQwCCyAAEF4gACgCoAMiAUEkTwRAIAEQAAsgACgCpAMiAEEjSw0BCw8LIAAQAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQcyEwAAgAkEIahA3IAJBIGokAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQbSEwAAgAkEIahA3IAJBIGokAAthAQN/IAAgARCvAiAAKAIAIgQgACgCCCICaiEDAkACQCABQQJPBEAgA0EAIAFBf2oiARCEAxogBCABIAJqIgJqIQMMAQsgAUUNAQsgA0EAOgAAIAJBAWohAgsgACACNgIIC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBuMDAACACQQhqEDcgAkEgaiQAC2kAIwBBMGsiASQAQZjuwAAtAAAEQCABQRxqQQE2AgAgAUICNwIMIAFByMfAADYCCCABQeUANgIkIAEgADYCLCABIAFBIGo2AhggASABQSxqNgIgIAFBCGpB8MfAABCPAgALIAFBMGokAAtZAQF/IwBBIGsiAiQAIAIgACgC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IAEgAhCIAiABKAIIBSACCzYCBCAAIAEoAgA2AgALLgEBfyABKAIEIgIEQCAAQQE2AgggACACNgIEIAAgASgCADYCAA8LIABBADYCCAsjAQF/An9BASABEAlFDQAaQQALIQIgACABNgIEIAAgAjYCAAsqAQF/IAAoAgAEQCAAEPUBIAAoAgQiAUEkTwRAIAEQAAsgAEEIahDDAgsLLgEBfyAAKAIAIAAoAgQoAgARAgAgACgCBCIBKAIEBEAgASgCCBogACgCABArCwswAQF/IAFBeGoiAiACKAIAQQFqIgI2AgAgAkUEQAALIABBmL3AADYCBCAAIAE2AgALLQEBfyMAQRBrIgEkACABQQhqIABBCGooAgA2AgAgASAAKQIANwMAIAEQmgEACzQAIABBAzoAICAAQoCAgICABDcCACAAIAE2AhggAEEANgIQIABBADYCCCAAQRxqIAI2AgALNQEBfyABKAIYQfvAwABBCyABQRxqKAIAKAIMEQMAIQIgAEEAOgAFIAAgAjoABCAAIAE2AgALIwAgACgCAEFwaiIAEK4CIABBDGooAgAiAEEkTwRAIAAQAAsLMQEBf0EEQQQQ2wIiAkUEQEEEQQQQ/gIACyACIAE2AgAgAEHEucAANgIEIAAgAjYCAAsxAQF/QQRBBBDbAiICRQRAQQRBBBD+AgALIAIgATYCACAAQbC5wAA2AgQgACACNgIACycAIAAgACgCBEEBcSABckECcjYCBCAAIAFqIgAgACgCBEEBcjYCBAsmAAJAIABFDQAgACABKAIAEQIAIAEoAgRFDQAgASgCCBogABArCwsmAQF/IwBBEGsiASQAIAEgAEF4ajYCDCABQQxqEKQBIAFBEGokAAs6AQJ/QdDuwAAtAAAhAUHQ7sAAQQA6AABB1O7AACgCACECQdTuwABBADYCACAAIAI2AgQgACABNgIACyABAX8CQCAAKAIEIgFFDQAgAEEIaigCAEUNACABECsLCyYBAX8jAEEQayIDJAAgAyABNgIMIAMgADYCCCADQQhqIAIQgAIACxMAIAAgASkAADcAASAAQQA6AAALJgEBfyAAQQdqIgEgAEkEQEGosMAAQTNBtLHAABDtAgALIAFBA3YLIwACQCABQfz///8HTQRAIAAgAUEEIAIQzQIiAA0BCwALIAALIwAgAiACKAIEQX5xNgIEIAAgAUEBcjYCBCAAIAFqIAE2AgALHgAgACgCACIArUIAIACsfSAAQX9KIgAbIAAgARBSCyUAIABFBEBBx73AAEEwEPkCAAsgACACIAMgBCAFIAEoAhARCwALEQAgACgCBARAIAAoAgAQKwsLIAEBfyAAKAIEIAAoAggiAmsgAUkEQCAAIAIgARDqAQsLIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARBQALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARCQALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhAREwALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhAREgALIwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgAyAEIAEoAhARFAALFwAgASADRgR/IAAgAiABEOYBRQVBAAsLHgAgACABQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIECyEAIABFBEBBx73AAEEwEPkCAAsgACACIAMgASgCEBEEAAsUACAAQQRqKAIABEAgACgCABArCwsdACABKAIARQRAAAsgAEHYscAANgIEIAAgATYCAAsfACAARQRAQcSzwABBMBD5AgALIAAgAiABKAIQEQEACx8AIABFBEBBhLfAAEEwEPkCAAsgACACIAEoAhARAQALHwAgAEUEQEHHvcAAQTAQ+QIACyAAIAIgASgCEBEAAAsXACAAKAIEBEAgABDDAiAAQQxqEMMCCwsVAQF/IAAoAgAgACgCCBABIAAQrgILHgEBf0G07sAAIQFBsO7AACgCAAR/IAEFIAAQswELCxkBAX8gACgCECIBBH8gAQUgAEEUaigCAAsLFQAgAC0ABEEERwRAIABBBGoQ8gELCxkAIAEgAiADEIICIABBBDoAACAAIAM2AgQLFAAgACgCABAPBEAgAEEEahCaAgsLEgBBAEEZIABBAXZrIABBH0YbCxYAIAAgAUEBcjYCBCAAIAFqIAE2AgALGQAgACABQQhqKAIANgIEIAAgASgCADYCAAscACABKAIYQbTQwABBCyABQRxqKAIAKAIMEQMACxwAIAEoAhhBv9DAAEEOIAFBHGooAgAoAgwRAwALHAAgASgCGEHI5sAAQQUgAUEcaigCACgCDBEDAAsXAEGc7sAAKAIARQRAIAAQaQtBnO7AAAsXACAAIAI2AgggACACNgIEIAAgATYCAAsQACAAIAFqQX9qQQAgAWtxCwwAIAAgASACIAMQLwsLACABBEAgABArCwsUACAAKAIAIABBCGooAgAgARD/AgsPACAAQQF0IgBBACAAa3ILEwAgACgCACAAQQhqKAIAIAEQLQsTACAAKAIAKAIAIAEgAhCCAkEACxIAIAEgAiADEIICIABBBDoAAAsKACAAQQhqEK4CCw8AIAAoAgAEQCAAEJgBCwsUACAAKAIAIAEgACgCBCgCDBEAAAsPACAAIAEgAiADIAQQKQALDgAgACgCACABEGoaQQALEAAgACgCACABIAIQggJBAAsRACAAKAIAIAAoAgggARD/AgsIACAAIAEQRgsRACAAKAIAIAAoAgQgARD/AgsQACAAIAI2AgQgACABNgIACxYAQdTuwAAgADYCAEHQ7sAAQQE6AAALEwAgAEHMyMAANgIEIAAgATYCAAsNACAALQAEQQJxQQF2CxAAIAEgACgCACAAKAIEECwLDQAgACABIAIQggJBAAsKAEEAIABrIABxCwsAIAAtAARBA3FFCwwAIAAgAUEDcjYCBAsNACAAKAIAIAAoAgRqCw0AIAAoAgAgARBQQQALDgAgACgCABoDQAwACwALDAAgACABIAIQugEACwwAIAAgASACELsBAAsMACAAIAEgAhC8AQALDQAgADUCAEEBIAEQUgsMACAAIAEgAhCnAgALDQAgACgCACABIAIQQgsNACAAKQMAQQEgARBSCw0AIAAzAQBBASABEFILDgAgACgCAC0AACABEFYLCwAgACMAaiQAIwALBwAgABCuAgsKACAAIAEgAhA4CwsAIAAgAiABEJMBCw0AIAFBvJLAAEECECwLCwAgACgCACABEEsLCwAgACABQcgAECMLCQAgACABECIACwoAIAAoAgRBeHELCgAgACgCBEEBcQsKACAAKAIMQQFxCwoAIAAoAgxBAXYLGgAgACABQdjuwAAoAgAiAEHmACAAGxEBAAALCgAgAiAAIAEQLAsMACAAIAEpAgA3AwALDAAgACABKQIINwMACw0AIAFByNTAAEECECwLCwAgACgCACABEFMLCwAgACABIAIQhQELCgAgACABIAIQUQsHACAAEKwBCwkAIABBBDoAAAsJACAAQQA2AgALBwAgACAB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aW8gc2xpY2VzIGJleW9uZCB0aGVpciBsZW5ndGgAhAYQACcAAAAYBhAASQAAACYFAAANAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9zdGQvc3JjL2lvL3JlYWRidWYucnMAAADEBhAATQAAACEBAAArAAAAIgAAAAwAAAAEAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAAC9ob21lL25nbml1cy9Eb2N1bWVudHMvZ2l0LXJlcG9zL3VzZHBsLXJzL3VzZHBsLWNvcmUvc3JjL3NlcmRlcy90cmFpdHMucnMAAABMBxAASQAAAHYAAAAcAAAAKgAAABgAAAAIAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAAMQAAADIAAABgdW53cmFwX3Rocm93YCBmYWlsZWQvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnPpBxAAYwAAANoAAAAgAAAAAAAAAGBhc3luYyBmbmAgcmVzdW1lZCBhZnRlciBjb21wbGV0aW9uY2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAADMAAAAAAAAAAQAAADQAAAAvcnVzdGMvZWRmMDE4MjIxM2E5ZTMwOTgyZWIzNGYzOTI1ZGRjNGNmNWVkMzQ3MS9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzANwIEABPAAAApgEAAAkAAAAoKQAAIgAAAAwAAAAEAAAANQAAADYAAAARAAAAYSBEaXNwbGF5IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yIHVuZXhwZWN0ZWRseQAzAAAAAAAAAAEAAAASAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9hbGxvYy9zcmMvc3RyaW5nLnJzAKAJEABLAAAA6AkAAAkAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlADMAAAAAAAAAAQAAADcAAABpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlOiAAADgKEAAqAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5yc2wKEABYAAAA0gEAAB8AAABsChAAWAAAANgBAAAfAAAAbAoQAFgAAADhAQAAHwAAAGwKEABYAAAA6gEAAB8AAABsChAAWAAAAPMBAAAfAAAAbAoQAFgAAAD8AQAAHwAAAGwKEABYAAAABQIAAB8AAABsChAAWAAAAA4CAAAfAAAAbAoQAFgAAAADAQAAJAAAAGwKEABYAAAABAEAACkAAABsChAAWAAAACoBAAAWAAAAbAoQAFgAAAAtAQAAGgAAAGwKEABYAAAAQQEAAA4AAABsChAAWAAAAEQBAAASAAAAbAoQAFgAAABYAQAAEwAAAEltcG9zc2libGU6IG11c3Qgb25seSBoYXZlIDAgdG8gOCBpbnB1dCBieXRlcyBpbiBsYXN0IGNodW5rLCB3aXRoIG5vIGludmFsaWQgbGVuZ3Roc7QLEABUAAAAbAoQAFgAAACdAQAADgAAAGwKEABYAAAAsQEAAAkAAABPdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIG91dHB1dCBidWZmZXIgbGVuZ3RoAABsChAAWAAAAJYAAAAKAAAAbAoQAFgAAACbAAAAIQAAAFdyaXRpbmcgdG8gYSBTdHJpbmcgc2hvdWxkbid0IGZhaWwvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzAACiDBAAWAAAAFMAAAAOAAAAAAAAAP//////////dXNkcGwtZnJvbnQvc3JjL2Nvbm5lY3Rpb24ucnMAAAAYDRAAHQAAABkAAAAmAAAAUE9TVGh0dHA6Ly91c2RwbC46L3VzZHBsL2NhbGwAAABMDRAADAAAAFgNEAABAAAAWQ0QAAEAAABaDRAACwAAAGxvY2FsaG9zdAAAAIgNEAAJAAAAGA0QAB0AAAAsAAAAJAAAABgNEAAdAAAAMwAAACcAAABFeHBlY3RlZCBjYWxsIHJlc3BvbnNlIG1lc3NhZ2UgZnJvbSAsIGdvdCBzb21ldGhpbmcgZWxzZbwNEAAkAAAA4A0QABQAAAB1c2RwbC1mcm9udC9zcmMvY29udmVydC5ycwAABA4QABoAAAAgAAAAJwAAAHVzZHBsLWZyb250L3NyYy9saWIucnMAADAOEAAWAAAAbwAAAE4AAAAwDhAAFgAAAG4AAAABAAAAY3JhbmtzaGFmdAAAaA4QAAoAAABkZWNreQAAAHwOEAAFAAAAYW55AIwOEAADAAAATG9hZEVycm9yOiBJbygpAJgOEAAOAAAApg4QAAEAAABMb2FkRXJyb3I6IEludmFsaWREYXRhAAC4DhAAFgAAAExvYWRFcnJvcjogVG9vU21hbGxCdWZmZXIAAADYDhAAGQAAAER1bXBFcnJvcjogSW8oAAD8DhAADgAAAKYOEAABAAAARHVtcEVycm9yOiBVbnN1cHBvcnRlZAAAHA8QABYAAABEdW1wRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAPA8QABkAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzYA8QAFgAAAA7AQAACQAAACEiIyQlJicoKSorLC0wMTIzNDU2Nzg5QEFCQ0RFRkdISUpLTE1OUFFSU1RVVlhZWltgYWJjZGVoaWprbG1wcXJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSssLi9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL////////////////////////////////////////////wABAgMEBQYHCAkKCwz//w0ODxAREhMUFRb///////8XGBkaGxwdHh8gISIjJCX/JicoKSorLP8tLi8w/////zEyMzQ1Nv//Nzg5Ojs8//89Pj//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pj////80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABNjc4OTo7PD0+P/////////8CAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG////////xwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wgREADIEBAAiBAQAEgQEAAIEBAAyA8QAEgWEABIFRAASBQQAEgTEABIEhAASBEQAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAOQAAAAgAAAAEAAAAOgAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAAC0FxAAYQAAAGgAAAAwAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBudW1iZXIgb2YgY2h1bmtzIGluIGlucHV0L2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5ycwBbGBAAWAAAALwAAAAKAAAAOwAAAAgAAAAEAAAAPAAAAD0AAAA7AAAACAAAAAQAAAA+AAAAYm9keW1ldGhvZG1vZGVzYW1lLW9yaWdpbm5vLWNvcnNjb3JzbmF2aWdhdGVhdHRlbXB0ZWQgdG8gY29udmVydCBpbnZhbGlkIFJlcXVlc3RNb2RlIGludG8gSlNWYWx1ZS9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93ZWItc3lzLTAuMy42MC9zcmMvZmVhdHVyZXMvZ2VuX1JlcXVlc3RNb2RlLnJzSRkQAGsAAAADAAAAAQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeUIAAAAEAAAABAAAAEMAAABEAAAAYWxyZWFkeSBib3Jyb3dlZEUAAAAAAAAAAQAAAEYAAABhbHJlYWR5IG11dGFibHkgYm9ycm93ZWRFAAAAAAAAAAEAAABHAAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9hbGxvYy9zcmMvY29sbGVjdGlvbnMvdmVjX2RlcXVlL21vZC5yc2Fzc2VydGlvbiBmYWlsZWQ6IHNlbGYuY2FwKCkgPT0gb2xkX2NhcCAqIDIAAABQGhAAXgAAAOMIAAAJAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvcXVldWUucnMAAADsGhAAZQAAABoAAAAuAAAA7BoQAGUAAAAdAAAAKQAAAOwaEABlAAAAMgAAABoAAABjbG9zdXJlIGludm9rZWQgcmVjdXJzaXZlbHkgb3IgZGVzdHJveWVkIGFscmVhZHljYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAABJAAAAAAAAAAEAAAA0AAAAL3J1c3RjL2VkZjAxODIyMTNhOWUzMDk4MmViMzRmMzkyNWRkYzRjZjVlZDM0NzEvbGlicmFyeS9zdGQvc3JjL3RocmVhZC9sb2NhbC5ycwAMHBAATwAAAKYBAAAJAAAAYWxyZWFkeSBib3Jyb3dlZEkAAAAAAAAAAQAAAEYAAABhc3NlcnRpb24gZmFpbGVkOiBtaWQgPD0gc2VsZi5sZW4oKQBKAAAABAAAAAQAAABLAAAATAAAAEoAAAAEAAAABAAAAE0AAABOAAAARm5PbmNlIGNhbGxlZCBtb3JlIHRoYW4gb25jZS9ydXN0Yy9lZGYwMTgyMjEzYTllMzA5ODJlYjM0ZjM5MjVkZGM0Y2Y1ZWQzNDcxL2xpYnJhcnkvYWxsb2Mvc3JjL2NvbGxlY3Rpb25zL3ZlY19kZXF1ZS9yaW5nX3NsaWNlcy5ycwAA9BwQAGYAAAAgAAAADgAAAPQcEABmAAAAIwAAABEAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnMAfB0QAGMAAAClAAAADwAAAHwdEABjAAAAhQAAACcAAAB8HRAAYwAAAK8AAAAkAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvdGFzay9zaW5nbGV0aHJlYWQucnMAAAAQHhAAcQAAACEAAAAVAAAATwAAAFAAAABRAAAAUgAAAFMAAAAQHhAAcQAAAFUAAAAlAAAAVAAAAHJldHVybiB0aGlzY2xvc3VyZSBpbnZva2VkIHJlY3Vyc2l2ZWx5IG9yIGRlc3Ryb3llZCBhbHJlYWR5Y2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAAGEAAAAAAAAAAQAAADQAAAAvcnVzdGMvZWRmMDE4MjIxM2E5ZTMwOTgyZWIzNGYzOTI1ZGRjNGNmNWVkMzQ3MS9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAFAfEABPAAAApgEAAAkAAABUcmllZCB0byBzaHJpbmsgdG8gYSBsYXJnZXIgY2FwYWNpdHmwHxAAJAAAAC9ydXN0Yy9lZGYwMTgyMjEzYTllMzA5ODJlYjM0ZjM5MjVkZGM0Y2Y1ZWQzNDcxL2xpYnJhcnkvYWxsb2Mvc3JjL3Jhd192ZWMucnPcHxAATAAAAKoBAAAJAAAAZwAAAAQAAAAEAAAAaAAAAGkAAABqAAAAY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZUFjY2Vzc0Vycm9yAABQIBAAAAAAAHVuY2F0ZWdvcml6ZWQgZXJyb3JvdGhlciBlcnJvcm91dCBvZiBtZW1vcnl1bmV4cGVjdGVkIGVuZCBvZiBmaWxldW5zdXBwb3J0ZWRvcGVyYXRpb24gaW50ZXJydXB0ZWRhcmd1bWVudCBsaXN0IHRvbyBsb25naW52YWxpZCBmaWxlbmFtZXRvbyBtYW55IGxpbmtzY3Jvc3MtZGV2aWNlIGxpbmsgb3IgcmVuYW1lZGVhZGxvY2tleGVjdXRhYmxlIGZpbGUgYnVzeXJlc291cmNlIGJ1c3lmaWxlIHRvbyBsYXJnZWZpbGVzeXN0ZW0gcXVvdGEgZXhjZWVkZWRzZWVrIG9uIHVuc2Vla2FibGUgZmlsZW5vIHN0b3JhZ2Ugc3BhY2V3cml0ZSB6ZXJvdGltZWQgb3V0aW52YWxpZCBkYXRhaW52YWxpZCBpbnB1dCBwYXJhbWV0ZXJzdGFsZSBuZXR3b3JrIGZpbGUgaGFuZGxlZmlsZXN5c3RlbSBsb29wIG9yIGluZGlyZWN0aW9uIGxpbWl0IChlLmcuIHN5bWxpbmsgbG9vcClyZWFkLW9ubHkgZmlsZXN5c3RlbSBvciBzdG9yYWdlIG1lZGl1bWRpcmVjdG9yeSBub3QgZW1wdHlpcyBhIGRpcmVjdG9yeW5vdCBhIGRpcmVjdG9yeW9wZXJhdGlvbiB3b3VsZCBibG9ja2VudGl0eSBhbHJlYWR5IGV4aXN0c2Jyb2tlbiBwaXBlbmV0d29yayBkb3duYWRkcmVzcyBub3QgYXZhaWxhYmxlYWRkcmVzcyBpbiB1c2Vub3QgY29ubmVjdGVkY29ubmVjdGlvbiBhYm9ydGVkbmV0d29yayB1bnJlYWNoYWJsZWhvc3QgdW5yZWFjaGFibGVjb25uZWN0aW9uIHJlc2V0Y29ubmVjdGlvbiByZWZ1c2VkcGVybWlzc2lvbiBkZW5pZWRlbnRpdHkgbm90IGZvdW5kIChvcyBlcnJvciApAAAAUCAQAAAAAAB9IxAACwAAAIgjEAABAAAAbWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAoApCMQABUAAAC5IxAADgAAAGxpYnJhcnkvc3RkL3NyYy9hbGxvYy5yc9gjEAAYAAAAVQEAAAkAAABsaWJyYXJ5L3N0ZC9zcmMvcGFuaWNraW5nLnJzACQQABwAAAA+AgAADwAAAAAkEAAcAAAAPQIAAA8AAABrAAAADAAAAAQAAABsAAAAZwAAAAgAAAAEAAAAbQAAAG4AAAAQAAAABAAAAG8AAABwAAAAZwAAAAgAAAAEAAAAcQAAAHIAAABnAAAAAAAAAAEAAABzAAAAb3BlcmF0aW9uIHN1Y2Nlc3NmdWwOAAAAEAAAABYAAAAVAAAACwAAABYAAAANAAAACwAAABMAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAARAAAAEgAAABAAAAAQAAAAEwAAABIAAAANAAAADgAAABUAAAAMAAAACwAAABUAAAAVAAAADwAAAA4AAAATAAAAJgAAADgAAAAZAAAAFwAAAAwAAAAJAAAACgAAABAAAAAXAAAAGQAAAA4AAAANAAAAFAAAAAgAAAAbAAAAFyEQAAchEADxIBAA3CAQANEgEAC7IBAAriAQAKMgEACQIBAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAbSMQAG0jEABtIxAAXCMQAEojEAA6IxAAKiMQABcjEAAFIxAA+CIQAOoiEADVIhAAySIQAL4iEACpIhAAlCIQAIUiEAB3IhAAZCIQAD4iEAAGIhAA7SEQANYhEADKIRAAwSEQALchEACnIRAAkCEQAHchEABpIRAAXCEQAEghEABAIRAAJSEQAEhhc2ggdGFibGUgY2FwYWNpdHkgb3ZlcmZsb3eoJhAAHAAAAC9jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2hhc2hicm93bi0wLjEyLjMvc3JjL3Jhdy9tb2QucnMAzCYQAE8AAABaAAAAKAAAAHQAAAAEAAAABAAAAHUAAAB2AAAAdwAAAGxpYnJhcnkvYWxsb2Mvc3JjL3Jhd192ZWMucnNjYXBhY2l0eSBvdmVyZmxvdwAAAGAnEAARAAAARCcQABwAAAAGAgAABQAAAGEgZm9ybWF0dGluZyB0cmFpdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvcgB0AAAAAAAAAAEAAAASAAAAbGlicmFyeS9hbGxvYy9zcmMvZm10LnJz0CcQABgAAABkAgAACQAAAO+/vQBjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlKS4uAAAoKBAAAgAAAEJvcnJvd0Vycm9yQm9ycm93TXV0RXJyb3IAaW5kZXggb3V0IG9mIGJvdW5kczogdGhlIGxlbiBpcyAgYnV0IHRoZSBpbmRleCBpcyBOKBAAIAAAAG4oEAASAAAAfQAAAAAAAAABAAAAfgAAAPwnEAAAAAAAYDogAPwnEAAAAAAAqSgQAAIAAAB9AAAADAAAAAQAAAB/AAAAgAAAAIEAAAAgICAgIHsKLAosICB7IH0gfSgKKCwAAAB9AAAABAAAAAQAAACCAAAAbGlicmFyeS9jb3JlL3NyYy9mbXQvbnVtLnJzAPwoEAAbAAAAZQAAABQAAAAweDAwMDEwMjAzMDQwNTA2MDcwODA5MTAxMTEyMTMxNDE1MTYxNzE4MTkyMDIxMjIyMzI0MjUyNjI3MjgyOTMwMzEzMjMzMzQzNTM2MzczODM5NDA0MTQyNDM0NDQ1NDY0NzQ4NDk1MDUxNTI1MzU0NTU1NjU3NTg1OTYwNjE2MjYzNjQ2NTY2Njc2ODY5NzA3MTcyNzM3NDc1NzY3Nzc4Nzk4MDgxODI4Mzg0ODU4Njg3ODg4OTkwOTE5MjkzOTQ5NTk2OTc5ODk5AAB9AAAABAAAAAQAAACDAAAAhAAAAIUAAABsaWJyYXJ5L2NvcmUvc3JjL2ZtdC9tb2QucnMADCoQABsAAAB7CQAAHgAAAAwqEAAbAAAAggkAABYAAAAoKWxpYnJhcnkvY29yZS9zcmMvc2xpY2UvbWVtY2hyLnJzAABKKhAAIAAAAGgAAAAnAAAAcmFuZ2Ugc3RhcnQgaW5kZXggIG91dCBvZiByYW5nZSBmb3Igc2xpY2Ugb2YgbGVuZ3RoIHwqEAASAAAAjioQACIAAAByYW5nZSBlbmQgaW5kZXggwCoQABAAAACOKhAAIgAAAHNsaWNlIGluZGV4IHN0YXJ0cyBhdCAgYnV0IGVuZHMgYXQgAOAqEAAWAAAA9ioQAA0AAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB1tfAAAszAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwMDAwMDAwMDAwMDAwMDAwQEBAQEAEGU2MAAC9EVWy4uLl1ieXRlIGluZGV4ICBpcyBvdXQgb2YgYm91bmRzIG9mIGAAABksEAALAAAAJCwQABYAAACoKBAAAQAAAGJlZ2luIDw9IGVuZCAoIDw9ICkgd2hlbiBzbGljaW5nIGAAAFQsEAAOAAAAYiwQAAQAAABmLBAAEAAAAKgoEAABAAAAIGlzIG5vdCBhIGNoYXIgYm91bmRhcnk7IGl0IGlzIGluc2lkZSAgKGJ5dGVzICkgb2YgYBksEAALAAAAmCwQACYAAAC+LBAACAAAAMYsEAAGAAAAqCgQAAEAAABsaWJyYXJ5L2NvcmUvc3JjL3N0ci9tb2QucnMA9CwQABsAAAAHAQAAHQAAAGxpYnJhcnkvY29yZS9zcmMvdW5pY29kZS9wcmludGFibGUucnMAAAAgLRAAJQAAAAoAAAAcAAAAIC0QACUAAAAaAAAAKAAAAAABAwUFBgYCBwYIBwkRChwLGQwaDRAODA8EEAMSEhMJFgEXBBgBGQMaBxsBHAIfFiADKwMtCy4BMAMxAjIBpwKpAqoEqwj6AvsF/QL+A/8JrXh5i42iMFdYi4yQHN0OD0tM+/wuLz9cXV/ihI2OkZKpsbq7xcbJyt7k5f8ABBESKTE0Nzo7PUlKXYSOkqmxtLq7xsrOz+TlAAQNDhESKTE0OjtFRklKXmRlhJGbncnOzw0RKTo7RUlXW1xeX2RljZGptLq7xcnf5OXwDRFFSWRlgISyvL6/1dfw8YOFi6Smvr/Fx8/a20iYvc3Gzs9JTk9XWV5fiY6Psba3v8HGx9cRFhdbXPb3/v+AbXHe3w4fbm8cHV99fq6vf7u8FhceH0ZHTk9YWlxefn+1xdTV3PDx9XJzj3R1liYuL6evt7/Hz9ffmkCXmDCPH9LUzv9OT1pbBwgPECcv7u9ubzc9P0JFkJFTZ3XIydDR2Nnn/v8AIF8igt8EgkQIGwQGEYGsDoCrBR8JgRsDGQgBBC8ENAQHAwEHBgcRClAPEgdVBwMEHAoJAwgDBwMCAwMDDAQFAwsGAQ4VBU4HGwdXBwIGFwxQBEMDLQMBBBEGDww6BB0lXyBtBGolgMgFgrADGgaC/QNZBxYJGAkUDBQMagYKBhoGWQcrBUYKLAQMBAEDMQssBBoGCwOArAYKBi8xTQOApAg8Aw8DPAc4CCsFgv8RGAgvES0DIQ8hD4CMBIKXGQsViJQFLwU7BwIOGAmAviJ0DIDWGgwFgP8FgN8M8p0DNwmBXBSAuAiAywUKGDsDCgY4CEYIDAZ0Cx4DWgRZCYCDGBwKFglMBICKBqukDBcEMaEEgdomBwwFBYCmEIH1BwEgKgZMBICNBIC+AxsDDw0ABgEBAwEEAgUHBwIICAkCCgULAg4EEAERAhIFExEUARUCFwIZDRwFHQgfASQBagRrAq8DsQK8As8C0QLUDNUJ1gLXAtoB4AXhAucE6ALuIPAE+AL6A/sBDCc7Pk5Pj56en3uLk5aisrqGsQYHCTY9Plbz0NEEFBg2N1ZXf6qur7014BKHiY6eBA0OERIpMTQ6RUZJSk5PZGVctrcbHAcICgsUFzY5Oqip2NkJN5CRqAcKOz5maY+SEW9fv+7vWmL0/P9TVJqbLi8nKFWdoKGjpKeorbq8xAYLDBUdOj9FUaanzM2gBxkaIiU+P+fs7//FxgQgIyUmKDM4OkhKTFBTVVZYWlxeYGNlZmtzeH1/iqSqr7DA0K6vbm++k14iewUDBC0DZgMBLy6Agh0DMQ8cBCQJHgUrBUQEDiqAqgYkBCQEKAg0C05DgTcJFgoIGDtFOQNjCAkwFgUhAxsFAUA4BEsFLwQKBwkHQCAnBAwJNgM6BRoHBAwHUEk3Mw0zBy4ICoEmUksrCCoWGiYcFBcJTgQkCUQNGQcKBkgIJwl1C0I+KgY7BQoGUQYBBRADBYCLYh5ICAqApl4iRQsKBg0TOgYKNiwEF4C5PGRTDEgJCkZFG0gIUw1JBwqA9kYKHQNHSTcDDggKBjkHCoE2GQc7AxxWAQ8yDYObZnULgMSKTGMNhDAQFo+qgkehuYI5ByoEXAYmCkYKKAUTgrBbZUsEOQcRQAULAg6X+AiE1ioJoueBMw8BHQYOBAiBjIkEawUNAwkHEJJgRwl0PID2CnMIcBVGehQMFAxXCRmAh4FHA4VCDxWEUB8GBoDVKwU+IQFwLQMaBAKBQB8ROgUBgdAqguaA9ylMBAoEAoMRREw9gMI8BgEEVQUbNAKBDiwEZAxWCoCuOB0NLAQJBwIOBoCag9gEEQMNA3cEXwYMBAEPDAQ4CAoGKAgiToFUDB0DCQc2CA4ECQcJB4DLJQqEBmxpYnJhcnkvY29yZS9zcmMvdW5pY29kZS91bmljb2RlX2RhdGEucnN9AAAABAAAAAQAAACGAAAAVHJ5RnJvbVNsaWNlRXJyb3JTb21lTm9uZQAAAH0AAAAEAAAABAAAAIcAAABFcnJvclV0ZjhFcnJvcnZhbGlkX3VwX3RvZXJyb3JfbGVuAAB9AAAABAAAAAQAAACIAAAAAAMAAIMEIACRBWAAXROgABIXIB8MIGAf7yygKyowICxvpuAsAqhgLR77YC4A/iA2nv9gNv0B4TYBCiE3JA3hN6sOYTkvGKE5MBxhSPMeoUxANGFQ8GqhUU9vIVKdvKFSAM9hU2XRoVMA2iFUAODhVa7iYVfs5CFZ0OihWSAA7lnwAX9aAHAABwAtAQEBAgECAQFICzAVEAFlBwIGAgIBBCMBHhtbCzoJCQEYBAEJAQMBBSsDPAgqGAEgNwEBAQQIBAEDBwoCHQE6AQEBAgQIAQkBCgIaAQICOQEEAgQCAgMDAR4CAwELAjkBBAUBAgQBFAIWBgEBOgEBAgEECAEHAwoCHgE7AQEBDAEJASgBAwE3AQEDBQMBBAcCCwIdAToBAgECAQMBBQIHAgsCHAI5AgEBAgQIAQkBCgIdAUgBBAECAwEBCAFRAQIHDAhiAQIJCwdJAhsBAQEBATcOAQUBAgULASQJAWYEAQYBAgICGQIEAxAEDQECAgYBDwEAAwADHQIeAh4CQAIBBwgBAgsJAS0DAQF1AiIBdgMEAgkBBgPbAgIBOgEBBwEBAQECCAYKAgEwHzEEMAcBAQUBKAkMAiAEAgIBAzgBAQIDAQEDOggCApgDAQ0BBwQBBgEDAsZAAAHDIQADjQFgIAAGaQIABAEKIAJQAgABAwEEARkCBQGXAhoSDQEmCBkLLgMwAQIEAgInAUMGAgICAgwBCAEvATMBAQMCAgUCAQEqAggB7gECAQQBAAEAEBAQAAIAAeIBlQUAAwECBQQoAwQBpQIABAACUANGCzEEewE2DykBAgIKAzEEAgIHAT0DJAUBCD4BDAI0CQoEAgFfAwIBAQIGAQIBnQEDCBUCOQIBAQEBFgEOBwMFwwgCAwEBFwFRAQIGAQECAQECAQLrAQIEBgIBAhsCVQgCAQECagEBAQIGAQFlAwIEAQUACQEC9QEKAgEBBAGQBAICBAEgCigGAgQIAQkGAgMuDQECAAcBBgEBUhYCBwECAQJ6BgMBAQIBBwEBSAIDAQEBAAILAjQFBQEBAQABBg8ABTsHAAE/BFEBAAIALgIXAAEBAwQFCAgCBx4ElAMANwQyCAEOARYFAQ8ABwERAgcBAgEFZAGgBwABPQQABAAHbQcAYIDwAADkMhAAKAAAAD8BAAAJAEHo7cAACwoBAAAAAAAAAGl6ADsJcHJvZHVjZXJzAQxwcm9jZXNzZWQtYnkCBndhbHJ1cwYwLjE5LjAMd2FzbS1iaW5kZ2VuBjAuMi44Mw=="; +const encoded = "AGFzbQEAAAABtwEbYAJ/fwBgAn9/AX9gAX8AYAN/f38AYAR/f39/AGADf39/AX9gAX8Bf2AAAGAAAX9gBX9/f39/AGAEf39/fwF/YAV/f39/fwF/YAF/AX5gA39/fwF+YAR/fn9/AGAGf39/f39/AX9gBn9/f39/fwBgBX9/fn9/AGAFf399f38AYAV/f3x/fwBgBH99f38AYAR/fH9/AGACfn8AYAd/f39/f39/AX9gA35/fwF/YAF8AX9gAn9/AX4CqgkjA3diZxpfX3diaW5kZ2VuX29iamVjdF9kcm9wX3JlZgACA3diZxVfX3diaW5kZ2VuX3N0cmluZ19uZXcAAQN3YmcVX193YmluZGdlbl9zdHJpbmdfZ2V0AAADd2JnG19fd2JpbmRnZW5fb2JqZWN0X2Nsb25lX3JlZgAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9uZXcAGQN3YmcWX193YmluZGdlbl9ib29sZWFuX2dldAAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9nZXQAAAN3YmcSX193YmluZGdlbl9pc19udWxsAAYDd2JnF19fd2JpbmRnZW5faXNfdW5kZWZpbmVkAAYDd2JnKF9fd2JnX2luc3RhbmNlb2ZfV2luZG93X2FjYzk3ZmY5ZjVkMmM3YjQABgN3YmccX193YmdfZmV0Y2hfMGZlMDQ5MDVjY2NmYzJhYQABA3diZypfX3diZ19pbnN0YW5jZW9mX1Jlc3BvbnNlX2VhYTQyNjIyMDg0OGEzOWUABgN3YmcbX193YmdfdGV4dF8xMTY5ZDc1MmNjNjk3OTAzAAYDd2JnKF9fd2JnX25ld3dpdGhzdHJhbmRpbml0XzA1ZDcxODA3ODg0MjBjNDAABQN3YmcSX193YmluZGdlbl9jYl9kcm9wAAYDd2JnIF9fd2JnX25ld25vYXJnc19iNWIwNjNmYzZjMmYwMzc2AAEDd2JnG19fd2JnX2NhbGxfOTdhZTlkODY0NWRjMzg4YgABA3diZxpfX3diZ19uZXdfMGI5YmZkZDk3NTgzMjg0ZQAIA3diZxRfX3diaW5kZ2VuX2lzX3N0cmluZwAGA3diZxtfX3diZ19zZWxmXzZkNDc5NTA2ZjcyYzZhNzEACAN3YmcdX193Ymdfd2luZG93X2YyNTU3Y2M3ODQ5MGFjZWIA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QZiHwAAQwwEACyAHQQhqIARqIAUgBmotAAA6AAAgACAIaiEACwJAIA9FIAsgAklyDQAgAEGBCEkEQCACIAdBCGogAGpBgAggAGsQ4QEgAGohAAwBCyAAQYAIQZCFwAAQhgMACyAAQYEITw0CIAshBCADIAdBCGogABDfAUUNAQsLIAdBoAhqJAAgEA8LIABBgAhBoIXAABCHAwALQeCDwABBKyAHQZgIakGMhMAAQciHwAAQtAEAC80NAgd/AX4jAEHgAmsiAiQAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAALQCYBEEBaw4DCQIBAAsgACAAQYgCakGIAhChAxoLAkACQAJAAkAgAC0AgAJBAWsOAw0EAAELIABB7AFqIQYgAC0A7AFBAWsOAwcDAgELIAAoAvABIQMgAiAAQfQBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEgaiACQThqELICIAJBKGogAigCICACKAIkEOUCIAAoAvgBIQMgAiAAQfwBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEYaiACQThqELECIAIoAhghBSACKAIcIQQgAkGUAmogAkEwaigCADYCACACIAIpAyg3AowCIAAgAkE4akHgARChAyIDIAQ2AugBIAMgBTYC5AEgAyAENgLgASADQQA6AOwBIANB7AFqIQYLIAAgACkC1AE3ArABIAAgACkC4AE3ArwBIABBuAFqIABB3AFqKAIANgIAIABBxAFqIgMgAEHoAWooAgAiBDYCAEHo6cAAQejpwAApAwAiCUIBfDcDACACQRBqIAQQngEgAigCECEEIABB0AFqQQA2AgAgAEHMAWogAigCFDYCACAAIAQ2AsgBIAMoAgAhBSAAKAK8ASEEIAIgAEHAAWooAgAiAzYCpAIgAiADIAVBAnRqNgKgAiACIAM2ApwCIAIgBDYCmAIgAEHIAWohBCAFBEADQCACIANBBGo2ApwCIAJBOGogAygCABBCIAAoAtABIgMgACgCyAFGBEAgBCADEPwBIAAoAtABIQMLIAAoAswBIANBBHRqIgMgAikDODcDACADQQhqIAJBQGspAwA3AwAgACAAKALQAUEBajYC0AEgAigCnAIiAyACKAKgAkcNAAsLIAJBmAJqEMcBQfDpwAAvAQAhAyACQThqIABBsAFqENEBIABBmAFqIAJBQGsoAgA2AgAgACACKQM4NwOQASAAIAQpAgA3ApwBIABBpAFqIARBCGooAgA2AgAgAEEAOgCqASAAIAM7AagBIAAgCTcDiAEgAEEANgKAASAAIAk3AwAgAEGqAWohBAwDCyAAQaoBaiEEIAAtAKoBQQFrDgMIAAMBCwALIAAvAagBIQMgACkDACEJCyACQUBrIABBgAFqQSgQoQMaIABBEGogAkE4akEwEKEDGiAAQegAakEAOgAAIABB5ABqIAM7AQAgACAJNwMICyACQThqIABBCGoiBSABECcgAigCOCIBQQtGDQIgAkHIAmogAkHIAGopAwA3AwAgAkHQAmoiAyACQdAAaikDADcDACACQdgCaiIGIAJB2ABqKQMANwMAIAIgAikDQDcDwAIgAigCPCEEIAUQrgEgAUEKRwRAIAJBuAJqIAYpAwA3AwAgAkGwAmogAykDADcDACACQagCaiACQcgCaikDADcDACACIAIpA8ACNwOgAiACIAQ2ApwCIAIgATYCmAIgAUEBRg0CQbSZwABBMhABIQQgAkGYAmoQuQELIABBAToAqgEgABDHAgwHC0GwjsAAQSNBzJrAABD3AQALIAJBsAJqKAIAIQEgAkGsAmooAgAhAyACQagCaigCACEEIABBAToAqgEgABDHAiADRQ0FIAIgARAXNgLAAiACIAM2AqQCIAIgAyABQQR0IgVqNgKgAiACIAM2ApwCIAIgBDYCmAIgAUUNBEEAIQQgAkE4akEBciIGQQdqIQcDQCACIANBEGoiATYCnAIgAy0AACIIQQpGDQUgBiADKQABNwAAIAcgA0EIaikAADcAACACIAg6ADggAkE4ahBeIQMgAkHAAmooAgAgBCADEBggBEEBaiEEIAEhAyAFQXBqIgUNAAsMBAsgBkEDOgAAIARBAzoAAEEBDAYLQbCOwABBI0GcjsAAEPcBAAtBsI7AAEEjQaSZwAAQ9wEAC0GwjsAAQSNB3JrAABD3AQALIAJBmAJqELIBIAIoAsACIQUMAQtBISEFIARBJEkNACAEEAALIABBsAFqEJoCIABBAToA7AFBAAsiAQRAQQMhBCAAQQM6AIACDAELIAAQlgIgAEEBOgCAAiACIAU2AiggAkEgNgI4IAJBCGogAEGQBGoiAyACQThqIAJBKGoQhAIgAigCCEUEQCACKAIMIgRBI0sEQCAEEAALIAIoAjgiBEEkTwRAIAQQAAsgAigCKCIEQSRPBEAgBBAACyADKAIAIgNBJE8EQCADEAALQQEhBCAAKAKUBCIDQSRJDQEgAxAADAELQbiAwABBFRCWAwALIAAgBDoAmAQgAkHgAmokACABQQBHC5IMAQV/IwBBkAJrIgMkACABAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCABLQBgQQFrDgQHAAIDAQsACyABIAEpAwA3AwggA0HIAGogAUEQakEoEKEDGiABIAEvAVw7AV4gARARNgI4IAFBOGoiBBC/ASAEEMIBIANBpAFqQRc2AgAgA0GcAWpBGDYCACADIAFB3gBqNgKgASADQfyYwAA2ApgBIANBGTYClAEgAyABQQhqNgKQASADQQM2AswBIANBBDYCxAEgA0HQmMAANgLAASADQQA2ArgBIAMgA0GQAWo2AsgBIANBgAFqIANBuAFqEEEgAUHEAGogA0GIAWooAgA2AgAgASADKQOAATcCPCADQbgBaiADQcgAakEoEKEDGiADQZABaiADQbgBahCBASADKAKQASEFIAMoApQBIgZFDQsgAUHQAGogAygCmAEiBzYCACABQcwAaiAGNgIAIAEgBTYCSCADQZABaiAGIAcQNyADQcABaiIFIANBmAFqKQMANwMAIAMgAykDkAE3A7gBIANB8ABqIANBuAFqELwBIAUgA0H4AGooAgA2AgAgAyADKQNwNwO4ASADIANBuAFqEI0CNgKQASAEIANBkAFqELABIAMoApABIgVBJE8EQCAFEAALIANBQGsgAUFAaygCACABQcQAaigCACAEEPMBIAMoAkQhBSADKAJADQogASAFNgJUIANBOGoQ7QEgAygCOEUNBiABIAMoAjw2AlggASABQdgAaigCACABQdQAaigCABAKEEg2AmgLIANBMGogAUHoAGoiBCACEI0BIAMoAjAiBkECRg0GIAMoAjQhBSAEEK8BIAYNCCADQShqIAUQ8QEgAygCLCEFIAMoAigNCCABIAU2AmggA0EgaiAEEPYBIAMoAiAhBCABQfQAaiADKAIkIgU2AgAgASAENgJwIAQNASABIAUQSDYCbAsgA0EYaiABQewAaiIEIAIQjQEgAygCGCICQQJGDQEgAygCHCEFIAQQrwEgAg0AIANBEGogBRDyASADKAIUIQQgAygCEEUNAiAEIQULIAEoAmgiAkEkSQ0GIAIQAAwGCyAAQQs2AgBBBAwKCyADQQhqIAQQAiADKAIIIgVFBEAgA0EANgK8AQwECyADKAIMIQIgAyAFNgK8ASADIAI2AsABIAMgAjYCuAEgAyADQbgBahCyAiADQbgBaiADKAIAIAMoAgQQ5QIgAygCvAFFDQMgA0GIAWogA0HAAWoiBigCACICNgIAIAMgAykDuAE3A4ABIANBuAFqIAMoAoQBIAIQmwEgAygCuAEiAkEKRwRAIAMoArwBIQUgA0GQAWogBkEoEKEDGiADQfABaiADQZgBaikDADcDACADQfgBaiADQaABaikDADcDACADQYACaiADQagBaikDADcDACADIAMpA5ABNwPoASADQYABahCaAiAEQSRPBEAgBBAACyABKAJoIgRBJE8EQCAEEAALIAEoAlgiBEEkTwRAIAQQAAsgASgCVCIEQSRPBEAgBBAACyABQcgAahCaAiABQTxqEJoCIAEoAjgiAUEkSQ0JIAEQAAwJCyADIAMpArwBNwOIAiADQYgCahCpASEFIANBgAFqEJoCIARBJE8EQCAEEAALIAEoAmgiAkEkTwRAIAIQAAsgASgCWCICQSRPBEAgAhAACyABKAJUIgJBJE8EQCACEAALIAFByABqEJoCIAFBPGoQmgIgASgCOCIBQSRJDQcgARAADAcLQbCOwABBI0GgmMAAEPcBAAtB6JHAAEErQYSZwAAQ9wEACyAAQQs2AgBBAwwGC0HokcAAQStBlJnAABD3AQALIAEoAlgiAkEkTwRAIAIQAAsgASgCVCICQSRJDQAgAhAACyABQcgAahCaAgsgAUE8ahCaAiABKAI4IgFBJEkNACABEAALQQohAgsgACAFNgIEIAAgAjYCACAAIAMpA+gBNwMIIABBEGogA0HwAWopAwA3AwAgAEEYaiADQfgBaikDADcDACAAQSBqIANBgAJqKQMANwMAQQELOgBgIANBkAJqJAAL4gsCCn8CfiMAQeACayICJAACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAC0A2AJBAWsOAwcCAQALIAAgAEGoAWpBqAEQoQMaCwJAIAAtAKABQQFrDgMFAQACCyAAQQhqIQUgAEGYAWotAABBAWsOAwcAAwILAAsgACgCACEDIAIgACgCBCIENgJQIAIgAzYCTCACIAQ2AkggAkEwaiACQcgAahCyAiACQThqIAIoAjAgAigCNBDlAiACQdQBaiACQUBrKAIANgIAIAIgAikDODcCzAEgAEEIaiIFIAJByABqQZABEKEDGiAAQZgBakEAOgAACyAAQYgBaiAAQZQBaigCADYCACAAQYABaiIDIABBjAFqKQIANwIAQejpwABB6OnAACkDACIMQgF8NwMAIAJBhAJqIAMQ0QEgAEEYakEJNgIAIAAgDDcDCCAAQegAakEAOgAAIABBHGogAikChAI3AgAgAEEkaiACQYwCaigCADYCACAAQeQAakHw6cAALwEAOwEACyACQcgAaiAFIAEQJyACKAJIQQtGDQIgAkHYAWogAkHIAGpBKBChAxogBRCuAQJAAkAgAigC2AEiB0F4ag4DAQYABgsgAigC3AEhAUG06sAAKAIABEAQ4wILQbTqwABBADYCACABQSRJDQggARAADAgLIAJB4AFqKAIAIQEgAkHkAWooAgAhAyACKALcASEGIAJBIGoQ5wEgAikDICEMIAIpAyghDSACQcgAaiADEGsgAkGoAmoiCCACQdAAaiIJKQMANwMAIAIgAikDSDcDoAIgAiANNwOYAiACIAw3A5ACIAIgATYCVCACIAEgA0EYbCIEajYCUCACIAE2AkwgAiAGNgJIIANFDQUgAkHYAmohBgNAIAIgAUEYaiIDNgJMIAEoAgQiCkUNBiABKAIAIQsgAiABKAIINgLIAiACIAo2AsQCIAIgCzYCwAIgBiABQRRqKAIANgIAIAIgASkCDDcD0AIgAkGwAmogAkGQAmogAkHAAmogAkHQAmoQSyACKAK0AgRAIAJBsAJqEKYCIAJBsAJqEMoCCyADIQEgBEFoaiIEDQALDAULQbCOwABBI0H8msAAEPcBAAtBsI7AAEEjQZyOwAAQ9wEAC0EDIQQgAEEDOgCgASAAQQM6AJgBQQEhAQwFC0GwjsAAQSNB7JrAABD3AQALQbTqwAAoAgAEQBDjAgtBtOrAAEEANgIAQQEhAQwBCyACQcgAahC7ASACQeAAaiAIKQMANwMAIAJB2ABqIgMgAkGgAmopAwA3AwAgCSACQZgCaikDADcDACACIAIpA5ACNwNIQQAhAUG06sAAKAIABEAQ4wIL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AUUNAQsgA0EANgJAIAMgATYCPCADIAI2AjggBCACSwR/IANBOGpBACAEEIUBIAMoAkAhBSADKAI8BSABCyAFaiAGIAQQoQMaIAMgBCAFaiICNgJAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEQfTLwAAvAAAiBTsAACAEQQJqQfbLwAAtAAAiBjoAACADIAJBA2oiAjYCQCADIAMpAzA3A0ggA0HQAGogA0HIAGoQPiADKAJQBEADQCADQegAaiADQdgAaikDADcDACADIAMpA1A3A2AgA0EQaiADQeAAahCdAyADKAIQIQcgAygCOCACayADKAIUIgRJBEAgA0E4aiACIAQQhQEgAygCQCECIAMoAjwhAQsgASACaiAHIAQQoQMaIAMgAiAEaiICNgJAIANBCGogA0HgAGoQngMgAygCDARAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEIAU7AAAgBEECaiAGOgAAIAMgAkEDaiICNgJACyADQdAAaiADQcgAahA+IAMoAlANAAsLIAAgAykDODcCBCAAQQE2AgAgAEEMaiADQUBrKAIANgIADAMLIAJBARCbAwALEJgCAAsgAEHAysAANgIEIABBADYCACAAQQhqQQA2AgALIANB8ABqJAAL0AQCBH8GfiAAIAAoAjggAmo2AjgCQCAAAn8CQAJAAkAgACgCPCIFRQRADAELAn4gAkEIIAVrIgQgAiAESRsiBkEDTQRAQgAMAQtBBCEDIAE1AAALIQcgACAAKQMwIANBAXIgBkkEQCABIANqMwAAIANBA3SthiAHhCEHIANBAnIhAwsgAyAGSQR+IAEgA2oxAAAgA0EDdK2GIAeEBSAHCyAFQQN0QThxrYaEIgc3AzAgBCACSw0BIAAgACkDGCAHhSIIIAApAwh8IgkgACkDECIKQg2JIAogACkDAHwiCoUiC3wiDCALQhGJhTcDECAAIAxCIIk3AwggACAJIAhCEImFIghCFYkgCCAKQiCJfCIIhTcDGCAAIAcgCIU3AwALIAIgBGsiAkEHcSEDIAQgAkF4cSICSQRAIAApAwghCCAAKQMQIQcgACkDACEJIAApAxghCgNAIAggASAEaikAACILIAqFIgh8IgogByAJfCIJIAdC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ACACQSRqQQA2AgAgAkH4nMAANgIYIAJBrJvAADYCICACQQA2AhAgASACQRBqENgBDAELIAIgADYCDCACQRxqQQI2AgAgAkEkakEBNgIAIAJB0JzAADYCGCACQQA2AhAgAkE+NgIsIAIgAkEoajYCICACIAJBDGo2AiggASACQRBqENgBCyACQTBqJAAL6QECAn8BfiMAQSBrIgMkACAAKAIARQRAIABBfzYCACADQRhqIABBHGopAgA3AwAgA0EQaiAAQRRqKQIANwMAIABBDGoiBCkCACEFIARBADYCACADIAU3AwggA0EIahDaAgJAIABBJGooAgBBAkYNACAAQShqKAIAIgRBJEkNACAEEAALIAAgATYCJCAAQShqIAI2AgAgAEEIaiICKAIAIQEgAkEANgIAIAAgACgCAEEBajYCACABBEAgACgCBCABKAIEEQIACyADQSBqJAAPC0GstMAAQRAgA0EIakG8tMAAQYS2wAAQtAEAC+kBAgN/An4jAEEgayIDJAAgA0EQaiABIAIQRQJAAkAgAygCFCIEBEAgAygCECEFIAMgAykDGCIHPgIIIAMgBDYCBCADIAU2AgAgA0EQaiABIAIQUyADKAIUIgFFDQEgAygCECECIAMpAxghBiAAIAMpAwA3AgAgACAGPgIUIAAgATYCECAAIAI2AgwgAEEIaiADQQhqKAIANgIAIAAgBkIgiKcgB0IgiKdqNgIYDAILIAMpAxghBiAAQQA2AgQgACAGNwIIDAELIAMpAxghBiAAQQA2AgQgACAGNwIIIAMQmgILIANBIGokAAvQAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEMbCEEIAVBq9Wq1QBJQQJ0IQYCQCACBEAgASgCBCEHIANBBDYCGCADIAJBDGw2AhQgAyAHNgIQDAELIANBADYCGAsgAyAEIAYgA0EQahCXASADKAIEIQQgAygCAARAIANBCGooAgAMAQsgASAFNgIAIAEgBDYCBEGBgICAeAs2AgQgACAENgIAIANBIGokAAvQAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEEdCEEIAVBgICAwABJQQN0IQYCQCACBEAgASgCBCEHIANBCDYCGCADIAJBBHQ2AhQgAyAHNgIQDAELIANBADYCGAsgAyAEIAYgA0EQahCXASADKAIEIQQgAygCAARAIANBCGooAgAMAQsgASAFNgIAIAEgBDYCBEGBgICAeAs2AgQgACAENgIAIANBIGokAAvPAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEobCEEIAVBtObMGUlBA3QhBgJAIAIEQCABKAIEIQcgA0EINgIYIAMgAkEobDYCFCADIAc2AhAMAQsgA0EANgIYCyADIAQgBiADQRBqEJcBIAMoAgQhBCADKAIABEAgA0EIaigCAAwBCyABIAU2AgAgASAENgIEQYGAgIB4CzYCBCAAIAQ2AgAgA0EgaiQAC88BAQV/IwBBIGsiAyQAIAACf0EAIAJBAWoiBCACSQ0AGiABKAIAIgJBAXQiBSAEIAUgBEsbIgRBBCAEQQRLGyIFQRhsIQQgBUHWqtUqSUECdCEGAkAgAgRAIAEoAgQhByADQQQ2AhggAyACQRhsNgIUIAMgBzYCEAwBCyADQQA2AhgLIAMgBCAGIANBEGoQlwEgAygCBCEEIAMoAgAEQCADQQhqKAIADAELIAEgBTYCACABIAQ2AgRBgYCAgHgLNgIEIAAgBDYCACADQSBqJAAL0AEBBX8jAEEgayIDJAAgAAJ/QQAgAkEBaiIEIAJJDQAaIAEoAgAiAkEBdCIFIAQgBSAESxsiBEEEIARBBEsbIgVBAnQhBCAFQYCAgIACSUECdCEGAkAgAgRAIAEoAgQhByADQQQ2AhggAyACQQJ0NgIUIAMgBzYCEAwBCyADQQA2AhgLIAMgBCAGIANBEGoQlwEgAygCBCEEIAMoAgAEQCADQQhqKAIADAELIAEgBTYCACABIAQ2AgRBgYCAgHgLNgIEIAAgBDYCACADQSBqJAALyQEBBX8jAEEwayICJAAgAkEIakGACBDeASACQQA2AhggAiACKQMINwMQIAJBIGogASACQRBqEIMBAkAgAi0AIEEGRgRAIAIoAiQhBSACKAIUIQQgAiACKAIYIgMQ3gEgAigCACEGIAIoAgQgBCADEKEDIQQgACAFNgIMIAAgAzYCCCAAIAQ2AgQgACAGNgIADAELIAIgAikDIDcDKCACQShqEKoBIQMgAEEANgIEIAAgAzYCAAsgAkEQahCaAiABELkBIAJBMGokAAvgAQECfyMAQSBrIgIkACACIAA2AgwgAiABKAIAQZjiwABBESABKAIEKAIMEQUAOgAYIAIgATYCFCACQQA6ABkgAkEANgIQIAJBEGogAkEMakGI4sAAEF8hAAJ/IAItABgiASAAKAIAIgNFDQAaIAFB/wFxIQBBASAADQAaIAIoAhQhAAJAIANBAUcNACACLQAZRQ0AIAAtABhBBHENAEEBIAAoAgBB5M3AAEEBIAAoAgQoAgwRBQANARoLIAAoAgBBo8zAAEEBIAAoAgQoAgwRBQALIAJBIGokAEH/AXFBAEcLvQECAn8BfiMAQSBrIgMkACADQYAIEN4BIANBADYCECADIAMpAwA3AwggA0EYaiABIANBCGpBqIvAABBWAkACQAJAAn8gAy0AGEEGRgRAIAMoAhwMAQsgAykDGCIFQv8Bg0IGUg0BIAVCIIinCyEBIAMoAhAiBCABSQ0CIAMoAgwgASACEOoBIABBBjoAACAAIAE2AgQMAQsgACAFNwIACyADQQhqEJoCIANBIGokAA8LIAEgBEGcjMAAEIcDAAvMAQECfyMAQSBrIgMkAAJAAkAgASACaiICIAFJDQAgACgCACIBQQF0IgQgAiAEIAJLGyICQQggAkEISxsiAkF/c0EfdiEEAkAgAQRAIANBATYCGCADIAE2AhQgAyAAQQRqKAIANgIQDAELIANBADYCGAsgAyACIAQgA0EQahCYASADKAIEIQEgAygCAEUEQCAAIAI2AgAgACABNgIEDAILIANBCGooAgAiAEGBgICAeEYNASAARQ0AIAEgABCbAwALEJgCAAsgA0EgaiQAC8wBAQJ/IwBBIGsiAyQAAkACQCABIAJqIgIgAUkNACAAKAIAIgFBAXQiBCACIAQgAksbIgJBCCACQQhLGyICQX9zQR92IQQCQCABBEAgA0EBNgIYIAMgATYCFCADIABBBGooAgA2AhAMAQsgA0EANgIYCyADIAIgBCADQRBqEJIBIAMoAgQhASADKAIARQRAIAAgAjYCACAAIAE2AgQMAgsgA0EIaigCACIAQYGAgIB4Rg0BIABFDQAgASAAEJsDAAsQmAIACyADQSBqJAALywECA38BfiMA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hgMAC6YBAQF/IwBBMGsiAyQAIANBBDoACCADIAE2AhAgA0EoaiACQRBqKQIANwMAIANBIGogAkEIaikCADcDACADIAIpAgA3AxgCQCADQQhqQZyJwAAgA0EYahA6BEAgAy0ACEEERgRAIABBxInAADYCBCAAQQI2AgAMAgsgACADKQMINwIADAELIABBBDoAACADLQAIQQRGDQAgA0EIahCHAgsgA0EwaiQAC6kBAQN/IwBBMGsiAiQAIAEoAgRFBEAgASgCDCEDIAJBEGoiBEEANgIAIAJCgICAgBA3AwggAiACQQhqNgIUIAJBKGogA0EQaikCADcDACACQSBqIANBCGopAgA3AwAgAiADKQIANwMYIAJBFGpBtLzAACACQRhqEDoaIAFBCGogBCgCADYCACABIAIpAwg3AgALIABBuMTAADYCBCAAIAE2AgAgAkEwaiQAC50BAQF/IwBBQGoiBCQAIAQgAjYCOCAEIAE2AjQgBCACNgIwIARBCGogBEEwahCyAiAEQSBqIAQoAgggBCgCDBDlAiAEQThqIgEgBEEoaigCADYCACAEIAQpAyA3AzAgBEEQaiAEQTBqIAMQUCABIARBGGooAgA2AgAgBCAEKQMQNwMwIAQgBEEwahCyAiAAIAQpAwA3AwAgBEFAayQAC6wBAQN/IwBBIGsiAyQAIANCADcDCCADQQE6ABwgA0EIahCGAiICIAIoAgBBAWoiBDYCAAJAIAQEQCACKAIIDQEgAkF/NgIIIAJBDGoiBBCJAiACQRhqQay3wAA2AgAgAkEUaiACQQhqNgIAIAJBEGogATYCACAEIAA2AgAgAkEANgIIIAIQ9AEgA0EgaiQADwsAC0GstMAAQRAgA0EIakG8tMAAQZi3wAAQtAEAC5sBAQF/IwBBQGoiAyQAIAMgAjYCOCADIAE2AjQgAyACNgIwIANBCGogA0EwahCyAiADQSBqIAMoAgggAygCDBDlAiADQThqIgEgA0EoaigCADYCACADIAMpAyA3AzAgA0EQaiADQTBqEFIgASADQRhqKAIANgIAIAMgAykDEDcDMCADIANBMGoQsgIgACADKQMANwMAIANBQGskAAuzAQECfyAAKAIIIgIEQCAAKAIEIQAgAkEobCECA0ACQAJAAkACQAJAAkACQCAAKAIADgkBAgYGAwYGBAUACyAAQQRq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CyAAQoKAgIDAl4AINwIACyAEQRBqJAALhwECAX8BfiMAQRBrIgEkAEGQ68AAKQMAUARAQaDrwAACfgJAIABFDQAgACkDACAAQgA3AwBCAVINACAAKQMIIQIgACkDEAwBCyABQgI3AwggAUIBNwMAIAEpAwAhAiABKQMICzcDAEGY68AAIAI3AwBBkOvAAEIBNwMACyABQRBqJABBmOvAAAt+AQF/IwBBEGsiASQAIAFBtrDAAEEEEAE2AgggAUHMsMAAQQQQATYCDCABIAAgAUEIaiABQQxqEOIBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHsADYCACADQfzMwAA2AhAgA0EANgIIIANB7AA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACEKgCAAt5AQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EUakECNgIAIANBHGpBAjYCACADQSxqQewANgIAIANBrNHAADYCECADQQA2AgggA0HsADYCJCADIANBIGo2AhggAyADQQRqNgIoIAMgAzYCICADQQhqIAIQqAIAC3kBAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRRqQQI2AgAgA0EcakECNgIAIANBLGpB7AA2AgAgA0HM0cAANgIQIANBADYCCCADQewANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANBCGogAhCoAgALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHsADYCACADQYDSwAA2AhAgA0EANgIIIANB7AA2AiQgAyADQSBqNgIYIAMgA0EEajYCKCADIAM2AiAgA0EIaiACEKgCAAtzAQR/IwBBEGsiASQAIAAoAggiAiAAKAIEIgNHBEAgAiADa0ECdkECdCECA0AgAygCACIEQSRPBEAgBBAACyADQQRqIQMgAkF8aiICDQALCyABIAAoAgw2AgwgASAAKAIANgIIIAFBCGoQmQIgAUEQaiQAC2wBAX8jAEEwayIDJAAgAyABNgIoIAMgADYCJCADIAE2AiAgA0EIaiADQSBqELICIANBEGogAygCCCADKAIMEOUCIANBKGogA0EYaigCADYCACADIAMpAxA3AyAgA0EgaiACEM8BIANBMGokAAtpAQF/IwBBMGsiAiQAIAIgATYCKCACIAA2AiQgAiABNgIgIAJBCGogAkEgahCyAiACQRBqIAIoAgggAigCDBDlAiACQShqIAJBGGooAgA2AgAgAiACKQMQNwMgIAJBIGoQaCACQTBqJAALcgEDfyMAQSBrIgIkAAJ/QQEgACABEFsNABogASgCBCEDIAEoAgAhBCACQQA2AhwgAkH4y8AANgIYIAJBATYCFCACQajMwAA2AhAgAkEANgIIQQEgBCADIAJBCGoQOg0AGiAAQQRqIAEQWwsgAkEgaiQAC3cBAX8CQAJAIABFDQAgACgCACEBIABBADYCACAAKAIEIQACQCABDgIBAgALIABBJEkNACAAEAALEFchAAtB1OrAACgCACEBQdTqwAAgADYCAEHQ6sAAKAIAQdDqwABBATYCAEUgAUEkSXJFBEAgARAAC0HU6sAAC3wBA38gACAAEKoDIgBBCBDmAiAAayICEKgDIQBBzO7AACABIAJrIgE2AgBB1O7AACAANgIAIAAgAUEBcjYCBEEIQQgQ5gIhAkEUQQgQ5gIhA0EQQQgQ5gIhBCAAIAEQqAMgBCADIAJBCGtqajYCBEHg7sAAQYCAgAE2AgALcwAjAEEwayIBJABBuOrAAC0AAARAIAFBFGpBAjYCACABQRxqQQE2AgAgAUHEw8AANgIQIAFBADYCCCABQewANgIkIAEgADYCLCABIAFBIGo2AhggASABQSxqNgIgIAFBCGpB7MPAABCoAgALIAFBMGokAAt2AQF/IAAtAAQhASAALQAFBEAgAUH/AXEhASAAAn9BASABDQAaIAAoAgAiAS0AGEEEcUUEQCABKAIAQd/NwABBAiABKAIEKAIMEQUADAELIAEoAgBB3s3AAEEBIAEoAgQoAgwRBQALIgE6AAQLIAFB/wFxQQBHC2kBAX8jAEEgayICJABBlOrAACgCAEUEQEHokcAAQStBrJrAABD3AQALIAJBGGogAEEIaigCADYCACACIAApAgA3AxAgAkEIaiACQRBqIAEQVSACKAIIIQAgAigCDCACQSBqJABBISAAGwtrAQJ/IwBBIGsiAiQAIAJBCGogASgCABACAkAgAigCCCIDBEAgAigCDCEBIAIgAzYCFCACIAE2AhggAiABNgIQIAIgAkEQahCyAiAAIAIoAgAgAigCBBDlAgwBCyAAQQA2AgQLIAJBIGokAAtrAQJ/IAFBBGooAgAhAwJAAkACQCABQQhqKAIAIgFFBEBBASECDAELIAFBf0wNASABQQEQ9wIiAkUNAgsgAiADIAEQoQMhAiAAIAE2AgggACACNgIEIAAgATYCAA8LEJgCAAsgAUEBEJsDAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQZCLwAAgAkEIahA6IAJBIGokAAthAQN/IAAgARDLAiAAKAIEIgQgACgCCCICaiEDAkACQCABQQJPBEAgA0EAIAFBf2oiARCiAxogBCABIAJqIgJqIQMMAQsgAUUNAQsgA0EAOgAAIAJBAWohAgsgACACNgIIC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0JHAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBtLzAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBqMrAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB8M/AACACQQhqEDogAkEgaiQAC1MBAn8jAEEgayICJAAgACgCBCEDIAAoAgAgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAyACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBkIvAACACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0JHAACACQQhqEDogAkEgaiQAC44BAgF/An4jAEEQayIBJABB8OnAACAAOwEAQejpwABCATcDACABEOcBIAEpAwghAiABKQMAIQNBlOrAACgCAARAQYjqwAAoAgAEQBCcARCrAgsLQZTqwABB+JfAADYCAEGI6sAAQgA3AwBB+OnAACADNwMAQYDqwAAgAjcDAEGQ6sAAQQA2AgAgAUEQaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB8M/AACACQQhqEDogAkEgaiQAC2EBAX8jAEFAaiIBJAAgAUEBOgAPIABBADYCCCAAQoCAgIAQNwIAIAFBEGogABC+AiABQQ9qIAFBEGoQkwEEQEGskMAAQTcgAUE4akHkkMAAQcCRwAAQtAEACyABQUBrJAALSAECfwJAIAFFBEBBASECDAELIAFBAE4EQCABIAFBf3NBH3YiAxD3AiICDQEgASADEJsDAAsQmAIACyAAIAI2AgQgACABNgIAC2IBAX8jAEEgayIDJAAgACgCACADQQhqIAEgAhAwIAMoAggEQCADIAMpAgw3AxhBvK3AAEErIANBGGpB6K3AAEHcrsAAELQBAAsgAygCDCADQRBqKAIAEJcCIANBIGokAEEAC2kBA38jAEEQayIBJAACQEEAQai3wAAoAgARBgAiAgRAIAAoAgAoAgAiACAAKAIAQQFqIgM2AgAgA0UNASACIAAQtgEgAUEQaiQADwtB/LfAAEHGACABQQhqQcS4wABBpLnAABC0AQALAAtWAQJ/AkAgAEEDcEEDc0EDcCIERQRADAELQQAhAANAIAAgAkcEQCAAIAFqQT06AAAgAEEBaiEDQQEhACADIARJDQEMAgsLIAIgAkH8ncAAEMMBAAsgAwtaAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAECAhASAEQQhqEL0CIAACfyAEKAIIRQRAIAAgAUEARzoAAUEADAELIAAgBCgCDDYCBEEBCzoAACAEQRBqJAALVAEBfyMAQTBrIgEkACABQRBqQZCawABBBRCFAiABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC1kBAn8gACgCDCICIAAoAgAiA0YEQCAAEKsBIAAoAgwhAiAAKAIAIQMLIAAoAgQgACgCCCACaiICQQAgAyACIANJG2tBAnRqIAE2AgAgACAAKAIMQQFqNgIMC0cBAn8CQCAAKAIAIgJFDQAgAiAAQRRqKAIAIgEgADUCECACQQFqrX6nakF/akEAIAFrcSIBakEJakUNACAAKAIMIAFrECsLC2ABAn8jAEEQayIBJAAgAUGMgcAAQRUQhQJBDEEEEPcCIgJFBEBBDEEEEJsDAAsgAiABKQMANwIAIAJBCGogAUEIaigCADYCACAAQeCAwAA2AgQgACACNgIAIAFBEGokAAtkAgJ/AX4jAEEQayICJABBAEHUjsAAKAIAEQYAIgEEQCABIAEpAwAiA0IBfDcDACAAIAEpAwg3AwggACADNwMAIAJBEGokAA8LQdiOwABBxgAgAkEIakGgj8AAQYCQwAAQtAEAC0oBAX8jAEEgayIAJAAgAEEUakEBNgIAIABBHGpBADYCACAAQcDJwAA2AhAgAEGkycAANgIYIABBADYCCCAAQQhqQZjKwAAQqAIAC00BAX8jAEEwayIBJAAgAUEQahDdASABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC2cBAX8jAEEgayIDJAAgAyACNgIMIANBEGoiAkGAAjsBBCACQQZqQQA6AAAgAkH9BTYCACADQRBqIAAgASADQQxqECUEQEHslsAAQSIgA0EYakGUksAAQeiXwAAQtAEACyADQSBqJAALTAECfyAAKAIIIgEEQCAAKAIEIQAgAUEEdCEBA0AgAC0AACICQX5qQQdJIAJFckUEQCAAQQRqEJoCCyAAQRBqIQAgAUFwaiIBDQALCwtWAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBD3AiIBRQ0BIAEgAzYCBCABIAI2AgAgAEGcsMAANgIEIAAgATYCAA8LAAtBCEEEEJsDAAtRAQN/IwBBEGsiASQAIAFBCGoQjwIQtAIgASgCDCECAkAgASgCCEUEQEEBIQMMAQsgAkEkSQ0AIAIQAAsgACACNgIEIAAgAzYCACABQRBqJAALSwECfyMAQRBrIgEkACABIABBeGo2AgggAC0AFCAAQQE6ABQgASABQQhqNgIMQQFxRQRAIAFBDGoQ4AELIAFBCGoQtQEgAUEQaiQAC18BA38jAEEQayIBJAACQCAAKAIMIgIEQCAAKAIIIgNFDQEgASACNgIIIAEgADYCBCABIAM2AgAgARC2AgALQcy8wABBK0GoxMAAEPcBAAtBzLzAAEErQZjEwAAQ9wEAC1ACAn8CfiABQRBqKAIAIgIgASkDACIEIAKtIgUgBCAFVBunIgNJBEAgAyACQfCCwAAQhgMACyAAIAIgA2s2AgQgACABQQxqKAIAIANqNgIAC0gBA38jAEEQayICJAAgAiABNgIMQQEhASACQQxqKAIAEAtBAEcgAigCDCEDBEBBACEBCyAAIAM2AgQgACABNgIAIAJBEGokAAtIAQN/IwBBEGsiAiQAIAIgATYCDEEBIQEgAkEMaigCABASQQFGIAIoAgwhAwRAQQAhAQsgACADNgIEIAAgATYCACACQRBqJAALSgEBfyMAQRBrIgQkACABIAIgAygCABANIQEgBEEIahC9AiAAAn8gASAEKAIIIgFFDQAaIAQoAgwLNgIEIAAgATYCACAEQRBqJAALWAECfyMAQRBrIgEkACABIAA2AgRBAEGot8AAKAIAEQYAIgIEQCACIAAQtgEgAUEQaiQADwsgAUEEahC1AUH8t8AAQcYAIAFBCGpBxLjAAEGkucAAELQBAAtYAQF/IwBBIGsiACQAIABBDGpBATYCACAAQRRqQQE2AgAgAEHQksAANgIIIABBADYCACAAQRg2AhwgAEH0lcAANgIYIAAgAEEYajYCECAAQfyVwAAQqAIAC0YBAX8jAEEQayICJAAgASgCABAMIQEgAkEIahC9AiAAAn8gASACKAIIIgFFDQAaIAIoAgwLNgIEIAAgATYCACACQRBqJAALUgEBfyMAQSBrIgMkACADQQxqQQE2AgAgA0EUakEANgIAIANB+MvAADYCECADQQA2AgAgAyABNgIcIAMgADYCGCADIANBGGo2AgggAyACEKgCAAtTAQF/IwBBIGsiAiQAIAJBDGpBATYCACACQRRqQQE2AgAgAkGczcAANgIIIAJBADYCACACQYABNgIcIAIgADYCGCACIAJBGGo2AhAgAiABEKgCAAtDAQN/AkAgAkUNAANAIAAtAAAiBCABLQAAIgVGBEAgAEEBaiEAIAFBAWohASACQX9qIgINAQwCCwsgBCAFayEDCyADC0sBAX8jAEEQayICJAAgAkEIaiAAIAFBARCMAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEH4CQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSAEBfyMAQRBrIgIkACACQQhqIAAgARB9AkAgAigCDCIAQYGAgIB4RwRAIABFDQEgAigCCCAAEJsDAAsgAkEQaiQADwsQmAIAC0gBAX8jAEEQayICJAAgAkEIaiAAIAEQfwJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEHwCQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSwEBfyMAQRBrIgMkACADQQhqIAAgASACEIwBAkAgAygCDCIAQYGAgIB4RwRAIABFDQEgAygCCCAAEJsDAAsgA0EQaiQADwsQmAIAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQfS0wABBHBCWAwALIAIgAzYCDCADQQhqQQAgARB6IAJBDGoQrwEgAkEQaiQAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQfS0wABBHBCWAwALIAIgAzYCDCADQQhqQQEgARB6IAJBDGoQrwEgAkEQaiQAC0MBAn8jAEEQayIBJAAgASAAQXhqNgIIIAAtABQgAEEBOgAUIAEgAUEIajYCDEEBcUUEQCABQQxqEOABCyABQRBqJAALSQEBfyMAQRBrIgIkACACQQhqIAAgARCAAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtOAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAEBkhASAEQQhqEL0CIAQoAgwhAiAAIAQoAggiAzYCACAAIAIgASADGzYCBCAEQRBqJAALSQEDfyMAQRBrIgMkACADQQhqIAIQ3gEgAygCCCEEIAAgAygCDCIFNgIEIAAgBDYCACAFIAEgAhChAxogACACNgIIIANBEGokAAtQAQF/QSBBBBD3AiIBRQRAQSBBBBCbAwALIAFCgYCAgBA3AgAgASAAKQIANwIIIAFBEGogAEEIaikCADcCACABQRhqIABBEGopAgA3AgAgAQtFAQJ/IAAtAABBA0YEQCAAKAIEIgEoAgAgASgCBCgCABECACABKAIEIgIoAgQEQCACKAIIGiABKAIAECsLIAAoAgQQKwsLSgEBfyMAQbABayIBJAAgASAAQagBEKEDIgAgADYCrAEgAEGsAWpBkI3AABCnAyAALQCgAUEDRgRAIABBCGoQrAILIABBsAFqJAALSAEBfyAAKAIAIgEEQCABIAAoAgQoAgARAgAgACgCBCIBKAIEBEAgASgCCBogACgCABArCyAAKAIIIABBDGooAgAoAgwRAgALC0gBAX8gACgCACIAKAIAIAAoAggiA2sgAkkEQCAAIAMgAhCEASAAKAIIIQMLIAAoAgQgA2ogASACEKEDGiAAIAIgA2o2AghBAAtIAQF/IAAoAgAiACgCACAAKAIIIgNrIAJJBEAgACADIAIQhQEgACgCCCEDCyAAKAIEIANqIAEgAhChAxogACACIANqNgIIQQALQAECfyAAKAIIIgEEQCAAKAIEIQAgAUECdCEBA0AgACgCACICQSRPBEAgAhAACyAAQQRqIQAgAUF8aiIBDQALCws+AQJ/IwBBEGsiASQAIAFBCGogAEEIaigCACICNgIAIAEgACkCADcDACABKAIEIAIQASABEJoCIAFBEGokAAtPAQF/IAAoAgAiACAAKAIAQX9qIgE2AgACQCABDQAgAEEMaiIBEJUBIAEoAgAEQCABKAIEECsLIAAgACgCBEF/aiIBNgIEIAENACAAECsLC0kBAn8jAEEQayIBJABBAEG0ucAAKAIAEQYAIgAEQCAAKAIAEAMgAUEQaiQADwtB87nAAEHGACABQQhqQby6wABBnLvAABC0AQALRwEBfyMAQZACayIBJAAgASAAQYgCEKEDIgAgADYCjAIgAEGMAmpBpI3AABCnAyAALQCAAkEDRgRA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JAAjAEEQayIAJAAgAEEIaiABEL8CIABBCGoQzgEgAEEQaiQACzMBAX9BNEEEEPcCIgFFBEBBNEEEEJsDAAsgAUKBgICAEDcCACABQQhqIABBLBChAxogAQsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ8CIAEoAggFIAILNgIEIAAgASgCBDYCAAsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ4CIAEoAggFIAILNgIEIAAgASgCBDYCAAsuAQF/IAEoAgAiAgRAIABBATYCCCAAIAI2AgQgACABKAIENgIADwsgAEEANgIICyMBAX8Cf0EBIAEQCUUNABpBAAshAiAAIAE2AgQgACACNgIACzABAX8gAUF4aiICIAIoAgBBAWoiAjYCACACRQRAAAsgAEGst8AANgIEIAAgATYCAAstAQF/IwBBEGsiASQAIAFBCGogAEEIaigCADYCACABIAApAgA3AwAgARCsAQALIwAgACgCAEFwaiIAEJoCIABBDGooAgAiAEEkTwRAIAAQAAsLMQEBf0EEQQQQ9wIiAkUEQEEEQQQQmwMACyACIAE2AgAgAEHMtMAANgIEIAAgAjYCAAsxAQF/QQRBBBD3AiICRQRAQQRBBBCbAwALIAIgATYCACAAQeC0wAA2AgQgACACNgIACycAIAAgACgCBEEBcSABckECcjYCBCAAIAFqIgAgACgCBEEBcjYCBAsmAQF/IwBBEGsiASQAIAEgAEF4ajYCDCABQQxqELUBIAFBEGokAAsmAAJAIABFDQAgACABKAIAEQIAIAEoAgRFDQAgASgCCBogABArCws6AQJ/QfDqwAAtAAAhAUHw6sAAQQA6AABB9OrAACgCACECQfTqwABBADYCACAAIAI2AgQgACABNgIACzQAIABBAzoAICAAQoCAgICABDcCGCAAQQA2AhAgAEEANgIIIABBlJDAADYCBCAAIAE2AgALMgEBfyABKAIAQfe8wABBCyABKAIEKAIMEQUAIQIgAEEAOgAFIAAgAjoABCAAIAE2AgALIAEBfwJAIABBBGooAgAiAUUNACAAKAIARQ0AIAEQKwsLJgEBfyMAQRBrIgMkACADIAE2AgwgAyAANgIIIANBCGogAhD4AQALEwAgACABKQAANwABIABBADoAAAsmAQF/IABBB2oiASAASQRAQeyuwABBM0H4r8AAEIoDAAsgAUEDdgsjAAJAIAFB/P///wdNBEAgACABQQQgAhDoAiIADQELAAsgAAsjACACIAIoAgRBfnE2AgQgACABQQFyNgIEIAAgAWogATYCAAseACAAKAIAIgCtQgAgAKx9IABBf0oiABsgACABEFoLKgACQAJAAkAgAC0AqgEOBAACAgECCyAAQYABahC5AQ8LIABBCGoQrgELCyUAIABFBEBBw7nAAEEwEJYDAAsgACACIAMgBCAFIAEoAhARCwALHQAgACgCACgCACABKAIMQQAgAmtBGGxqQWhqEEMLEQAgACgCAARAIAAoAgQQKwsLIAEBfyAAKAIAIAAoAggiAmsgAUkEQCAAIAIgARD/AQsLIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARCgALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARBAALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARDgALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARFAALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARFQALFwAgASADRgR/IAAgAiABEPkBRQVBAAsLHgAgACABQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIECyEAIABFBEBBw7nAAEEwEJYDAAsgACACIAMgASgCEBEDAAsUACAAKAIABEAgAEEEaigCABArCwsaACAAKAIAKAIAIAEoAgwgAkEEdGtBcGoQQwsdACABKAIARQRAAAsgAEGcsMAANgIEIAAgATYCAAsfACAARQRAQYiywABBMBCWAwALIAAgAiABKAIQEQAACx8AIABFBEBBzLfAAEEwEJYDAAsgACACIAEoAhARAAALHwAgAEUEQEHDucAAQTAQlgMACyAAIAIgASgCEBEBAAsXACAAKAIABEAgABCpAiAAQQxqEKkCCwsfAQF/IAAoAgQgACgCCBABIAAoAgAEQCAAKAIEECsLCx4BAX9B1OrAACEBQdDqwAAoAgAEfyABBSAAEMsBCwsZAQF/IAAoAhAiAQR/IAEFIABBFGooAgALCxkAIAEgAiADEJcCIABBBDoAACAAIAM2AgQLFwAgAEEEaigCACAAQQhqKAIAIAEQnAMLEgBBAEEZIABBAXZrIABBH0YbCxYAIAAgAUEBcjYCBCAAIAFqIAE2AgALFgAgAEEEaigCACAAQQhqKAIAIAEQLwsTAEGo6sAAKAIABEAQmQEQpAILCxcAQcDqwAAoAgBFBEAgABBvC0G86sAACxcAIAAgAjYCCCAAIAE2AgQgACACNgIACxAAIAAgAWpBf2pBACABa3ELEgAgAC0AAEEERwRAIAAQhwILCwwAIAAgASACIAMQLgsLACABBEAgABArCwsPACAAQQF0IgBBACAAa3ILGQAgASgCAEGwzMAAQQsgASgCBCgCDBEFAAsZACABKAIAQbvMwABBDiABKAIEKAIMEQUACxkAIAEoAgBBxOLAAEEFIAEoAgQoAgwRBQALEwAgACgCACgCCCABIAIQlwJBAAsSACABIAIgAxCXAiAAQQQ6AAALCgAgAEEIahCaAgsPACAAKAIABEAgABCvAQsLFAAgACgCACABIAAoAgQoAgwRAQALDwAgACABIAIgAyAEECkACw4AIAAoAgAgARBwGkEACxAAIAAoAgggASACEJcCQQALEAAgACgCACABIAIQlwJBAAsIACAAIAEQSQsRACAAKAIAIAAoAgQgARCcAwsQACAAIAI2AgQgACABNgIACxYAQfTqwAAgADYCAEHw6sAAQQE6AAALEwAgAEHIxMAANgIEIAAgATYCAAsNACAALQAEQQJxQQF2Cw8AIAAgAUEEaikCADcDAAsQACABIAAoAgAgACgCBBAsCw0AIAAgASACEJcCQQALCgBBACAAayAAcQsLACAALQAEQQNxRQsMACAAIAFBA3I2AgQLDQAgACgCACAAKAIEagsNACAAKAIAIAEQWEEACw4AIAAoAgAaA0AMAAsACwwAIAAgASACEMQBAAsMACAAIAEgAhDFAQALDAAgACABIAIQxgEACw0AIAA1AgBBASABEFoLDAAgACABIAIQwQIACw0AIAAoAgAgASACEEcLDQAgACkDAEEBIAEQWgsNACAAMwEAQQEgARBaCw4AIAAoAgAtAAAgARBdCwsAIAAjAGokACMACwoAIAAgASACEDsLCwAgACACIAEQoQELBwAgABCaAgsNACABQZCQwABBAhAsCwsAIAAoAgAgARBKCwsAIAAgAUHZABAiCwkAIAAgARAhAAsKACAAKAIEQXhxCwoAIAAoAgRBAXELCgAgACgCDEEB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cy9Eb2N1bWVudHMvZ2l0LXJlcG9zL3VzZHBsLXJzL3VzZHBsLWNvcmUvc3JjL3NlcmRlcy90cmFpdHMucnMAAADQBRAASQAAAHYAAAAcAAAAIgAAABgAAAAIAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAABgdW53cmFwX3Rocm93YCBmYWlsZWQAAAArAAAAYAEAAAgAAAAsAAAALQAAACACAAAIAAAALgAAAC8AAAAEAAAABAAAADAAAAAxAAAALwAAAAQAAAAEAAAAMgAAADMAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnMAuAYQAGMAAADaAAAAFQAAAAAAAABgYXN5bmMgZm5gIHJlc3VtZWQgYWZ0ZXIgY29tcGxldGlvbgA0AAAAY2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAALwAAAAAAAAABAAAANQAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMAsAcQAE8AAACmAQAACQAAACgpAAAaAAAADAAAAAQAAAA2AAAANwAAADgAAABhIERpc3BsYXkgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IgdW5leHBlY3RlZGx5AC8AAAAAAAAAAQAAADkAAAAvcnVzdGMvYmRiMDdhOGVjOGU3N2FhMTBmYjg0ZmFlMWQ0ZmY3MWMyMTE4MGJiNC9saWJyYXJ5L2FsbG9jL3NyYy9zdHJpbmcucnMAdAgQAEsAAADoCQAACQAAAC8AAAAEAAAABAAAADoAAAA7AAAAPAAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUALwAAAAAAAAABAAAAPQAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAAJAkQACoAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzWAkQAFgAAADSAQAAHwAAAFgJEABYAAAA2AEAAB8AAABYCRAAWAAAAOEBAAAfAAAAWAkQAFgAAADqAQAAHwAAAFgJEABYAAAA8wEAAB8AAABYCRAAWAAAAPwBAAAfAAAAWAkQAFgAAAAFAgAAHwAAAFgJEABYAAAADgIAAB8AAABYCRAAWAAAAAMBAAAkAAAAWAkQAFgAAAAEAQAAKQAAAFgJEABYAAAAKgEAABYAAABYCRAAWAAAAC0BAAAaAAAAWAkQAFgAAABBAQAADgAAAFgJEABYAAAARAEAABIAAABYCRAAWAAAAFgBAAATAAAASW1wb3NzaWJsZTogbXVzdCBvbmx5IGhhdmUgMCB0byA4IGlucHV0IGJ5dGVzIGluIGxhc3QgY2h1bmssIHdpdGggbm8gaW52YWxpZCBsZW5ndGhzoAoQAFQAAABYCRAAWAAAAJ0BAAAOAAAAWAkQAFgAAACxAQAACQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgb3V0cHV0IGJ1ZmZlciBsZW5ndGgAAFgJEABYAAAAlgAAAAoAAABYCRAAWAAAAJsAAAAhAAAAV3JpdGluZyB0byBhIFN0cmluZyBzaG91bGRuJ3QgZmFpbC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9lbmNvZGUucnMAAI4LEABYAAAAUwAAAA4AAAD//////////3VzZHBsLWZyb250L3NyYy9jb25uZWN0aW9uLnJzAAAAAAwQAB0AAAAZAAAAJgAAAFBPU1RodHRwOi8vdXNkcGwuOi91c2RwbC9jYWxsAAAANAwQAAwAAABADBAAAQAAAEEMEAABAAAAQgwQAAsAAABsb2NhbGhvc3QAAABwDBAACQAAAAAMEAAdAAAALQAAACQAAAAADBAAHQAAADQAAAAnAAAAAAwQAB0AAABJAAAAJgAAAEV4cGVjdGVkIGNhbGwgcmVzcG9uc2UgbWVzc2FnZSwgZ290IHNvbWV0aGluZyBlbHNldXNkcGwtZnJvbnQvc3JjL2NvbnZlcnQucnPmDBAAGgAAACAAAAAnAAAAMC45LjB1c2RwbC1mcm9udC9zcmMvbGliLnJzABUNEAAWAAAAYgAAABgAAAAVDRAAFgAAAGoAAAAYAAAAFQ0QABYAAABxAAAATgAAABUNEAAWAAAAcAAAAAEAAAAVDRAAFgAAAKAAAAAmAAAAFQ0QABYAAACfAAAAAQAAABUNEAAWAAAAxAAAAEAAAAAVDRAAFgAAANIAAABAAAAAY3JhbmtzaGFmdAAArA0QAAoAAABkZWNreQAAAMANEAAFAAAAYW55ANANEAADAAAATG9hZEVycm9yOiBJbygpANwNEAAOAAAA6g0QAAEAAABMb2FkRXJyb3I6IEludmFsaWREYXRhAAD8DRAAFgAAAExvYWRFcnJvcjogVG9vU21hbGxCdWZmZXIAAAAcDhAAGQAAAER1bXBFcnJvcjogSW8oAABADhAADgAAAOoNEAABAAAARHVtcEVycm9yOiBVbnN1cHBvcnRlZAAAYA4QABYAAABEdW1wRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAgA4QABkAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzpA4QAFgAAAA7AQAACQAAACEiIyQlJicoKSorLC0wMTIzNDU2Nzg5QEFCQ0RFRkdISUpLTE1OUFFSU1RVVlhZWltgYWJjZGVoaWprbG1wcXJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSssLi9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL////////////////////////////////////////////wABAgMEBQYHCAkKCwz//w0ODxAREhMUFRb///////8XGBkaGxwdHh8gISIjJCX/JicoKSorLP8tLi8w/////zEyMzQ1Nv//Nzg5Ojs8//89Pj//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pj////80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABNjc4OTo7PD0+P/////////8CAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG////////xwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0wQEAAMEBAAzA8QAIwPEABMDxAADA8QAIwVEACMFBAAjBMQAIwSEACMERAAjBAQAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAPwAAAAgAAAAEAAAAQAAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAAD4FhAAYQAAAGgAAAAwAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBudW1iZXIgb2YgY2h1bmtzIGluIGlucHV0L2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5ycwCfFxAAWAAAALwAAAAKAAAAQQAAAAgAAAAEAAAAQgAAAEMAAABBAAAACAAAAAQAAABEAAAAYm9keW1ldGhvZG1vZGVzYW1lLW9yaWdpbm5vLWNvcnNjb3JzbmF2aWdhdGVhdHRlbXB0ZWQgdG8gY29udmVydCBpbnZhbGlkIFJlcXVlc3RNb2RlIGludG8gSlNWYWx1ZS9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93ZWItc3lzLTAuMy42MC9zcmMvZmVhdHVyZXMvZ2VuX1JlcXVlc3RNb2RlLnJzjRgQAGsAAAADAAAAAQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeUgAAAAEAAAABAAAAEkAAABKAAAAYWxyZWFkeSBib3Jyb3dlZEsAAAAAAAAAAQAAAEwAAABhbHJlYWR5IG11dGFibHkgYm9ycm93ZWRLAAAAAAAAAAEAAABNAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvcXVldWUucnMAAACUGRAAZQAAABoAAAAuAAAAlBkQAGUAAAAdAAAAKQAAAJQZEABlAAAAMgAAABoAAABhbHJlYWR5IGJvcnJvd2VkTgAAAAAAAAABAAAATAAAAE8AAAAEAAAABAAAAFAAAABRAAAATwAAAAQAAAAEAAAAUgAAAFMAAABGbk9uY2UgY2FsbGVkIG1vcmUgdGhhbiBvbmNlL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvbGliLnJzAJAaEABjAAAApQAAAA8AAACQGhAAYwAAAIUAAAAnAAAAkBoQAGMAAACvAAAAJAAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93YXNtLWJpbmRnZW4tZnV0dXJlcy0wLjQuMzMvc3JjL3Rhc2svc2luZ2xldGhyZWFkLnJzAAAAJBsQAHEAAAAhAAAAFQAAAFQAAABVAAAAVgAAAFcAAABYAAAAJBsQAHEAAABVAAAAJQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeWNhbm5vdCBhY2Nlc3MgYSBUaHJlYWQgTG9jYWwgU3RvcmFnZSB2YWx1ZSBkdXJpbmcgb3IgYWZ0ZXIgZGVzdHJ1Y3Rpb24AAFoAAAAAAAAAAQAAADUAAAAvcnVzdGMvYmRiMDdhOGVjOGU3N2FhMTBmYjg0ZmFlMWQ0ZmY3MWMyMTE4MGJiNC9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAFQcEABPAAAApgEAAAkAAABbAAAAcmV0dXJuIHRoaXNjbG9zdXJlIGludm9rZWQgcmVjdXJzaXZlbHkgb3IgZGVzdHJveWVkIGFscmVhZHljYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAAAAaAAAAAAAAAABAAAANQAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMATB0QAE8AAACmAQAACQAAAFRyaWVkIHRvIHNocmluayB0byBhIGxhcmdlciBjYXBhY2l0eawdEAAkAAAAL3J1c3RjL2JkYjA3YThlYzhlNzdhYTEwZmI4NGZhZTFkNGZmNzFjMjExODBiYjQvbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc9gdEABMAAAAqgEAAAkAAABuAAAABAAAAAQAAABvAAAAcAAAAHEAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlQWNjZXNzRXJyb3IAAEweEAAAAAAAdW5jYXRlZ29yaXplZCBlcnJvcm90aGVyIGVycm9yb3V0IG9mIG1lbW9yeXVuZXhwZWN0ZWQgZW5kIG9mIGZpbGV1bnN1cHBvcnRlZG9wZXJhdGlvbiBpbnRlcnJ1cHRlZGFyZ3VtZW50IGxpc3QgdG9vIGxvbmdpbnZhbGlkIGZpbGVuYW1ldG9vIG1hbnkgbGlua3Njcm9zcy1kZXZpY2UgbGluayBvciByZW5hbWVkZWFkbG9ja2V4ZWN1dGFibGUgZmlsZSBidXN5cmVzb3VyY2UgYnVzeWZpbGUgdG9vIGxhcmdlZmlsZXN5c3RlbSBxdW90YSBleGNlZWRlZHNlZWsgb24gdW5zZWVrYWJsZSBmaWxlbm8gc3RvcmFnZSBzcGFjZXdyaXRlIHplcm90aW1lZCBvdXRpbnZhbGlkIGRhdGFpbnZhbGlkIGlucHV0IHBhcmFtZXRlcnN0YWxlIG5ldHdvcmsgZmlsZSBoYW5kbGVmaWxlc3lzdGVtIGxvb3Agb3IgaW5kaXJlY3Rpb24gbGltaXQgKGUuZy4gc3ltbGluayBsb29wKXJlYWQtb25seSBmaWxlc3lzdGVtIG9yIHN0b3JhZ2UgbWVkaXVtZGlyZWN0b3J5IG5vdCBlbXB0eWlzIGEgZGlyZWN0b3J5bm90IGEgZGlyZWN0b3J5b3BlcmF0aW9uIHdvdWxkIGJsb2NrZW50aXR5IGFscmVhZHkgZXhpc3RzYnJva2VuIHBpcGVuZXR3b3JrIGRvd25hZGRyZXNzIG5vdCBhdmFpbGFibGVhZGRyZXNzIGluIHVzZW5vdCBjb25uZWN0ZWRjb25uZWN0aW9uIGFib3J0ZWRuZXR3b3JrIHVucmVhY2hhYmxlaG9zdCB1bnJlYWNoYWJsZWNvbm5lY3Rpb24gcmVzZXRjb25uZWN0aW9uIHJlZnVzZWRwZXJtaXNzaW9uIGRlbmllZGVudGl0eSBub3QgZm91bmQgKG9zIGVycm9yICkAAABMHhAAAAAAAHkhEAALAAAAhCEQAAEAAABtZW1vcnkgYWxsb2NhdGlvbiBvZiAgYnl0ZXMgZmFpbGVkCgCgIRAAFQAAALUhEAAOAAAAbGlicmFyeS9zdGQvc3JjL2FsbG9jLnJz1CEQABgAAABVAQAACQAAAGxpYnJhcnkvc3RkL3NyYy9wYW5pY2tpbmcucnP8IRAAHAAAAD4CAAAPAAAA/CEQABwAAAA9AgAADwAAAHIAAAAMAAAABAAAAHMAAABuAAAACAAAAAQAAAB0AAAAdQAAABAAAAAEAAAAdgAAAHcAAABuAAAACAAAAAQAAAB4AAAAeQAAAG4AAAAAAAAAAQAAAHoAAABvcGVyYXRpb24gc3VjY2Vzc2Z1bA4AAAAQAAAAFgAAABUAAAALAAAAFgAAAA0AAAALAAAAEwAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABEAAAASAAAAEAAAABAAAAATAAAAEgAAAA0AAAAOAAAAFQAAAAwAAAALAAAAFQAAABUAAAAPAAAADgAAABMAAAAmAAAAOAAAABkAAAAXAAAADAAAAAkAAAAKAAAAEAAAABcAAAAZAAAADgAAAA0AAAAUAAAACAAAABsAAAATHxAAAx8QAO0eEADYHhAAzR4QALceEACqHhAAnx4QAIweEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABYIRAARiEQADYhEAAmIRAAEyEQAAEhEAD0IBAA5iAQANEgEADFIBAAuiAQAKUgEACQIBAAgSAQAHMgEABgIBAAOiAQAAIgEADpHxAA0h8QAMYfEAC9HxAAsx8QAKMfEACMHxAAcx8QAGUfEABYHxAARB8QADwfEAAhHxAASGFzaCB0YWJsZSBjYXBhY2l0eSBvdmVyZmxvd6QkEAAcAAAAL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvaGFzaGJyb3duLTAuMTIuMy9zcmMvcmF3L21vZC5ycwDIJBAATwAAAFoAAAAoAAAAewAAAAQAAAAEAAAAfAAAAH0AAAB+AAAAbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc2NhcGFjaXR5IG92ZXJmbG93AAAAXCUQABEAAABAJRAAHAAAAAYCAAAFAAAAYSBmb3JtYXR0aW5nIHRyYWl0IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yAHsAAAAAAAAAAQAAADkAAABsaWJyYXJ5L2FsbG9jL3NyYy9mbXQucnPMJRAAGAAAAGQCAAAJAAAA77+9AGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUpLi4AACQmEAACAAAAQm9ycm93RXJyb3JCb3Jyb3dNdXRFcnJvcgBpbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIEomEAAgAAAAaiYQABIAAACEAAAAAAAAAAEAAACFAAAA+CUQAAAAAABgOiAA+CUQAAAAAAClJhAAAgAAAIQAAAAMAAAABAAAAIYAAACHAAAAiAAAACAgICAgewosCiwgIHsgfSB9KAooLAAAAIQAAAAEAAAABAAAAIkAAABsaWJyYXJ5L2NvcmUvc3JjL2ZtdC9udW0ucnMA+CYQABsAAABlAAAAFAAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTkAAIQAAAAEAAAABAAAAIoAAACLAAAAjAAAAGxpYnJhcnkvY29yZS9zcmMvZm10L21vZC5ycwAIKBAAGwAAAHoJAAAeAAAACCgQABsAAACBCQAAFgAAACgpbGlicmFyeS9jb3JlL3NyYy9zbGljZS9tZW1jaHIucnMAAEYoEAAgAAAAaAAAACcAAAByYW5nZSBzdGFydCBpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggeCgQABIAAACKKBAAIgAAAHJhbmdlIGVuZCBpbmRleCC8KBAAEAAAAIooEAAiAAAAc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCAA3CgQ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"; function asciiToBinary(str) { if (typeof atob === 'function') { diff --git a/src/usdpl_front/usdpl_front_bg.wasm b/src/usdpl_front/usdpl_front_bg.wasm index 781ff6cdb9ae9b3d59fe69ed63fcc546a8a1b111..7bafdb1dd8cf695fbbe3f42a73c1e8726c1286a7 100644 GIT binary patch literal 92157 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 Eztn&NFaQ7m literal 84394 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 WF5|(tzO_1BRJeQ{*XpWU>i-)X6=6F7 diff --git a/src/usdpl_front/usdpl_front_bg.wasm.d.ts b/src/usdpl_front/usdpl_front_bg.wasm.d.ts index 1e96bc2..959d805 100644 --- a/src/usdpl_front/usdpl_front_bg.wasm.d.ts +++ b/src/usdpl_front/usdpl_front_bg.wasm.d.ts @@ -7,6 +7,9 @@ export function version_usdpl(a: number): void; export function set_value(a: number, b: number, c: number): number; export function get_value(a: number, b: number): number; export function call_backend(a: number, b: number, c: number, d: number): number; +export function init_tr(a: number, b: number): number; +export function tr(a: number, b: number, c: number): void; +export function tr_n(a: number, b: number, c: number, d: number): void; export function __wbindgen_export_0(a: number): number; export function __wbindgen_export_1(a: number, b: number, c: number): number; export const __wbindgen_export_2: WebAssembly.Table; diff --git a/translations/pt.pot b/translations/pt.pot new file mode 100644 index 0000000..ee4e1b4 --- /dev/null +++ b/translations/pt.pot @@ -0,0 +1,229 @@ +# TEMPLATE TITLE. +# Copyright (C) 2023 NGnius +# This file is distributed under the same license as the PowerTools package. +# NGnius (Graham) , 2023. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-09 19:52-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# -- index.tsx -- + +#: index.tsx:226 +# (Section title) +msgid "Miscellaneous" +msgstr "" + +#: index.tsx:226 +# (Profile persistence toggle) +msgid "Persistent" +msgstr "" + +#: index.tsx:227 +# (Profile persistence toggle description) +msgid "Save profile and load it next time" +msgstr "" + +#: index.tsx:239 +# (Profile display) +msgid "Profile" +msgstr "" + +# -- components/battery.tsx -- + +#: components/battery.tsx:42 +# (Battery section title) +msgid "Battery" +msgstr "" + +#: components/battery.tsx:46 +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +msgid "Now (Charge)" +msgstr "" + +#: components/battery.tsx:52 +# (Maximum capacity of battery, with percentage of design capacity in brackets) +msgid "Max (Design)" +msgstr "" + +#: components/battery.tsx:59 +# (Charge current limit override toggle) +msgid "Charge Current Limits" +msgstr "" + +#: components/battery.tsx:60 +# (Charge current limit override toggle description) +msgid "Control battery charge rate when awake" +msgstr "" + +#: components/battery.tsx:74 +# (Battery maximum input current with unit) +msgid "Maximum (mA)" +msgstr "" + +#: components/battery.tsx:97,115 +# (Battery charge mode override toggle) +msgid "Charge Mode" +msgstr "" + +#: components/battery.tsx:98 +# (Battery charge mode override toggle description) +msgid "Force battery charge mode" +msgstr "" + +#: components/battery.tsx:112 +# (Battery charge mode dropdown) +msgid "Mode" +msgstr "" + +#: components/battery.tsx:133 +# (Battery current display) +msgid "Current" +msgstr "" + +# -- components/cpus.tsx -- + +#: components/cpus.tsx:64 +# (CPU section title) +msgid "CPU" +msgstr "" + +#: components/cpus.tsx:70 +# (CPU advanced mode toggle) +msgid "Advanced" +msgstr "" + +#: components/cpus.tsx:71 +# (CPU advanced mode toggle description) +msgid "Enables per-thread configuration" +msgstr "" + +#: components/cpus.tsx:88 +# (CPU Simultaneous MultiThreading toggle) +msgid "SMT" +msgstr "" + +#: components/cpus.tsx:89 +# (CPU SMT toggle description) +msgid "Enables odd-numbered CPUs" +msgstr "" + +#: components/cpus.tsx:106 +# (CPU thread count slider) +msgid "Threads" +msgstr "" + +#: components/cpus.tsx:137 +#: components/gpu.tsx:112 +# (Clock speed override toggle) +msgid "Frequency Limits" +msgstr "" + +#: components/cpus.tsx:138 +#: components/gpu.tsx:113 +# (Clock speed override toggle description) +msgid "Set bounds on clock speed" +msgstr "" + +#: components/cpus.tsx:165 +#: components/gpu.tsx:137 +# (Minimum clock speed with unit) +msgid "Minimum (MHz)" +msgstr "" + +#: components/cpus.tsx:195 +#: components/gpu.tsx:160 +# (Maximum clock speed with unit) +msgid "Maximum (MHz)" +msgstr "" + +# advanced mode + +#: components/cpus.tsx:226 +# (CPU selection slider) +msgid "Selected CPU" +msgstr "" + +#: components/cpus.tsx:246 +# (CPU Online toggle) +msgid "Online" +msgstr "" + +#: components/cpus.tsx:247 +# (CPU Online description) +msgid "Allow the CPU thread to do work" +msgstr "" + +#: components/cpus.tsx:342 +# (CPU scheduling governor dropdown -- governor names are not translated) +msgid "Governor" +msgstr "" + +# -- components/debug.tsx -- + +#: components/debug.tsx:29 +# (Debug section title) +msgid "Debug" +msgstr "" + +#: components/debug.tsx:33 +# (Version display for native back-end of PowerTools) +msgid "Native" +msgstr "" + +#: components/debug.tsx:47 +# (Mode display for framework of USDPL API) +msgid "Framework" +msgstr "" + +#: components/debug.tsx:54 +# (Display for software implementation in PowerTools which applies settings) +msgid "Driver" +msgstr "" + +# -- components/gpu.tsx -- + +#: components/gpu.tsx:34 +# (GPU section title) +msgid "GPU" +msgstr "" + +#: components/gpu.tsx:39 +# (PPT Limits override toggle) +msgid "PowerPlay Limits" +msgstr "" + +#: components/gpu.tsx:40 +# (PPT Limits override toggle description) +msgid "Override APU TDP settings" +msgstr "" + +#: components/gpu.tsx:63 +# (SlowPPT slider with unit) +msgid "SlowPPT (W)" +msgstr "" + +#: components/gpu.tsx:87 +# (FastPPT slider with unit) +msgid "FastPPT (W)" +msgstr "" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle) +msgid "Downclock Memory" +msgstr "" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle description) +msgid "Force RAM into low-power mode" +msgstr "" diff --git a/translations/test.mo b/translations/test.mo new file mode 100644 index 0000000000000000000000000000000000000000..4def730745ac4dfbb3945202a0761a45d5dfc204 GIT binary patch literal 2116 zcmeH`KWrRD6vhW|_;Z*5!2tpW1~6btS>K(Lpy)6N$7h=epMA2A&{#-wyW{oX-I>eG z>|Jb8LPv!{gCYuqs3K87LE(ae0whW#8bp;62?-(5fW$Yu&xu6^J)?W~+qW}s=FR)w z{(NHWLxwR8n}luM#@IRV+U@wm7~H|w-QZ>LDR3XW3;YPgk9~r_li+9Iz2E`(Joqgb z*8K_|1OEUY0RIB-1dop~b_zTRaX%!I0M%;5c{y z-Uoh1{*UC}ApQp8S0)qAKZc}2+&CEgQ((x4gEg=PhVz!daF0u1IQK2^8L$tA`1imN z_W>C4zYd1=UxBZqmS2-Uj+f#61aXo$MLbPBOPnXRiL1mOaf_G`GomNHLwuL`KJhB? z8u3%&b>f%A1L8Nt?}{zCkn_$P4;BH@vZ6DNq1#3|xw;#uN6i1L+v`8fC( zEcDrN7>5Oo!gv<;AT0D|7ziszsWqO0RzasnVUVKCCFmM@CFmB$!xhRtdj!uRk`x+@NLH=k}VqTt;u-5isEq9|RfNEdluTA73_-OZVS zv=OBo8@;X40w*b>*|KoH+wJk`H)q(gv9aVE3mvXBE{5wy12dAA=ON>2_8<9HGgjoX ztiiICmkX)my~8W7pcpF#Icj5BM_l34ZRu31XM&^hBInbc*Y=Ni`2rlJk4`BU%PbRG zn!>TNcx%XgDA^kHn664a!`5}Cv}Efz%c?~31&GvZce#_^E1f#lmDVZep$F@RTXi#W zGtI6w+bWZ6v(sanVkr5bdclQGPzMODJlFDy=U(MlCNmlPs>X0U@0&s=sK4fwJZ>P- zF`KC1VQqV5zaR^1-bQS6F^MjPgp6+SVRN=w+mHieebjNON}>xz>Y|=$@g466u2rw6 z%I_5Y+1TXuwH2)jS1<3-GbVF&, 2023. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-10 20:06-0500\n" +"PO-Revision-Date: 2023-01-10 20:06-0500\n" +"Last-Translator: NGnius \n" +"Language-Team: NGnius \n" +"Language: conlang\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# -- index.tsx -- + +#: index.tsx:226 +# (Section title) +msgid "Miscellaneous" +msgstr "test123" + +#: index.tsx:226 +# (Profile persistence toggle) +msgid "Persistent" +msgstr "test123" + +#: index.tsx:227 +# (Profile persistence toggle description) +msgid "Save profile and load it next time" +msgstr "test123" + +#: index.tsx:239 +# (Profile display) +msgid "Profile" +msgstr "test123" + +# -- components/battery.tsx -- + +#: components/battery.tsx:42 +# (Battery section title) +msgid "Battery" +msgstr "test123" + +#: components/battery.tsx:46 +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +msgid "Now (Charge)" +msgstr "test123" + +#: components/battery.tsx:52 +# (Maximum capacity of battery, with percentage of design capacity in brackets) +msgid "Max (Design)" +msgstr "test123" + +#: components/battery.tsx:59 +# (Charge current limit override toggle) +msgid "Charge Current Limits" +msgstr "test123" + +#: components/battery.tsx:60 +# (Charge current limit override toggle description) +msgid "Control battery charge rate when awake" +msgstr "test123" + +#: components/battery.tsx:74 +# (Battery maximum input current with unit) +msgid "Maximum (mA)" +msgstr "test123" + +#: components/battery.tsx:97,115 +# (Battery charge mode override toggle) +msgid "Charge Mode" +msgstr "test123" + +#: components/battery.tsx:98 +# (Battery charge mode override toggle description) +msgid "Force battery charge mode" +msgstr "test123" + +#: components/battery.tsx:112 +# (Battery charge mode dropdown) +msgid "Mode" +msgstr "test123" + +#: components/battery.tsx:133 +# (Battery current display) +msgid "Current" +msgstr "test123" + +# -- components/cpus.tsx -- + +#: components/cpus.tsx:64 +# (CPU section title) +msgid "CPU" +msgstr "test123" + +#: components/cpus.tsx:70 +# (CPU advanced mode toggle) +msgid "Advanced" +msgstr "test123" + +#: components/cpus.tsx:71 +# (CPU advanced mode toggle description) +msgid "Enables per-thread configuration" +msgstr "test123" + +#: components/cpus.tsx:88 +# (CPU Simultaneous MultiThreading toggle) +msgid "SMT" +msgstr "test123" + +#: components/cpus.tsx:89 +# (CPU SMT toggle description) +msgid "Enables odd-numbered CPUs" +msgstr "test123" + +#: components/cpus.tsx:106 +# (CPU thread count slider) +msgid "Threads" +msgstr "test123" + +#: components/cpus.tsx:137 +#: components/gpu.tsx:112 +# (Clock speed override toggle) +msgid "Frequency Limits" +msgstr "test123" + +#: components/cpus.tsx:138 +#: components/gpu.tsx:113 +# (Clock speed override toggle description) +msgid "Set bounds on clock speed" +msgstr "test123" + +#: components/cpus.tsx:165 +#: components/gpu.tsx:137 +# (Minimum clock speed with unit) +msgid "Minimum (MHz)" +msgstr "test123" + +#: components/cpus.tsx:195 +#: components/gpu.tsx:160 +# (Maximum clock speed with unit) +msgid "Maximum (MHz)" +msgstr "test123" + +# advanced mode + +#: components/cpus.tsx:226 +# (CPU selection slider) +msgid "Selected CPU" +msgstr "test123" + +#: components/cpus.tsx:246 +# (CPU Online toggle) +msgid "Online" +msgstr "test123" + +#: components/cpus.tsx:247 +# (CPU Online description) +msgid "Allow the CPU thread to do work" +msgstr "test123" + +#: components/cpus.tsx:342 +# (CPU scheduling governor dropdown -- governor names are not translated) +msgid "Governor" +msgstr "test123" + +# -- components/debug.tsx -- + +#: components/debug.tsx:29 +# (Debug section title) +msgid "Debug" +msgstr "test123" + +#: components/debug.tsx:33 +# (Version display for native back-end of PowerTools) +msgid "Native" +msgstr "test123" + +#: components/debug.tsx:47 +# (Mode display for framework of USDPL API) +msgid "Framework" +msgstr "test123" + +#: components/debug.tsx:54 +# (Display for software implementation in PowerTools which applies settings) +msgid "Driver" +msgstr "test123" + +# -- components/gpu.tsx -- + +#: components/gpu.tsx:34 +# (GPU section title) +msgid "GPU" +msgstr "test123" + +#: components/gpu.tsx:39 +# (PPT Limits override toggle) +msgid "PowerPlay Limits" +msgstr "test123" + +#: components/gpu.tsx:40 +# (PPT Limits override toggle description) +msgid "Override APU TDP settings" +msgstr "test123" + +#: components/gpu.tsx:63 +# (SlowPPT slider with unit) +msgid "SlowPPT (W)" +msgstr "test123" + +#: components/gpu.tsx:87 +# (FastPPT slider with unit) +msgid "FastPPT (W)" +msgstr "test123" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle) +msgid "Downclock Memory" +msgstr "test123" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle description) +msgid "Force RAM into low-power mode" +msgstr "test123" From ea7f4a32689a3289cc7f2f4647a0275e2015ddea Mon Sep 17 00:00:00 2001 From: James Date: Wed, 11 Jan 2023 12:10:40 -0500 Subject: [PATCH 29/44] Add French translation (#60) Adding french Canadian translation --- translations/fr-CA.mo | Bin 0 -> 2620 bytes translations/fr-CA.po | 220 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 translations/fr-CA.mo create mode 100644 translations/fr-CA.po diff --git a/translations/fr-CA.mo b/translations/fr-CA.mo new file mode 100644 index 0000000000000000000000000000000000000000..caf046af18732111b5fb34f23bd28698dbff11fa GIT binary patch literal 2620 zcmai#%WoS+9LEP}ftpgFv_MON;ngN8o5U%7;Hn5WPSQ$sYht%>s6gZ0@n-1mj5{-H zr@ev1KY&0;h?h73Mo0+CfkO^RJ^=S(L1V07u0$0Jk;Ey2f z`wQF*{tMm5VAg*9vfuz?Ja4Wb9 z-VOdVT3;Qle;@I05T9HblD`>B(YdW4t#^T>4+l$N1tfX%AlY#aB)PAEPk?QZ&c6xL zxwk;l|4Weee+M?<%kM|)9eB7O&-Z|&_X&{hdl4kRp9Qyp7Nl6b4&uYUz!%y74fqha z3X;CRfX{%xj<^MvlKey9EO;E;2WH^?;0GYZ>1&YW{s7YcpF#55)e-*y$*zA!YZ9Kv z3nc&T1Yr`}4L$&J5L?+{@DTU{NdD`CJHR(UsL0+0Nso^}+II!q4*m%S;5Cr+*^k2{ z=P(HO<-T|r+>J^4laDwi$)NEh=6#ryn>0ul8hNZiiWS*Iz9YR!7m6#{OmU+@cF=$d z>_N=OX>r3KUp|dVHjy2VVp5*ogSi)zbSHbp2gQ|qP5yfdGcT!X)Dt?C5vwMN>2tp< z`CQ{HXr+j_H#{=DZ|ntjTzD_-C5E?bZduqE8#8OA_WYDem3M1T>n4(H&S-Bo76l1zwk_fvlQUJ!#pz7VShjZlWmAS=yFX zMx>=%f76vV7^xf@-BED{Ny=!pAe?VBT72TANw#2YDEU&g&XtB?FgNI$zO+0gjf=N8 z=v%z8B9*xh7OcFONgZBVGkFotSTxX48_Viqg-_I^Q?Z_;g-WxOPt;Fb9$TeVER-I9 zrCcbJL}+O;$8zVLhVDJdP9q)@g{vpo8J#FC*%`>PDw4d4Ahl`@?xgoh$Bs3mb;^0f zgEh#iMk3bLY*^D#iDb=si#0`0@^0~f3mw4^2(tRZRPm_Ev$JBXM>YbaE=r*y25+qsd8yac8&Ex-Nh;jj%Tq8TBgF6 zz3;lp^mMHJa@L*-O*(ygQLD^N=QgyAN!+w@E|ad*I1?<%o}xR08uF;ZXJ=*)1T*EJ zT;?-JD$hO_%p9DVDV;*dgO(NACBhq9;dr9sOvEy1Ns*4NE4*W0ovW7WC+qVY>XxTw zN|e6vWYD_Qg&YshOm`EZ^wB(#;qzl>TMNOFjeR7pgCv~Sp@|TW3O~|TzSKyNh)ICl zN?nEPZoYKKW{>jX=dlURpXcStqotRFMX4pSmNae{86hGEre>#RORP#2Ivh}hQ$*WJ zo=A>(@@Su284kjXGMx`U=H7~)P)UN4DXLYW!jPePeWHGlHlcw+C|UZMmt>xCv@8;> zDBR(~N5`2g#@}EDZ;7h7^?9 zs5Ky|hM#3}tQ-7aZ>UlG8*2(3)Yov}keM>2#=G7f<~2G}jQ+4BQzU9(jU#7?boe<^ z#^uc-%Bb=~2@hnJBep70hyWr~G!JCPMzUl`!%-ihvd$YwJxdUKq+SypEb&4kEt?|i z$ynH^aN$~OLEAtA6-kzdgCsAbh7fI|@Na, 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-09 19:52-0500\n" +"PO-Revision-Date: 2023-01-11 08:49-0500\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: fr_CA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.2.2\n" + +# -- index.tsx -- +# (Section title) +#: index.tsx:226 +msgid "Miscellaneous" +msgstr "Divers" + +# (Profile persistence toggle) +#: index.tsx:226 +msgid "Persistent" +msgstr "Persistant" + +# (Profile persistence toggle description) +#: index.tsx:227 +msgid "Save profile and load it next time" +msgstr "Sauvegarder le profile et le charger la prochaine fois" + +# (Profile display) +#: index.tsx:239 +msgid "Profile" +msgstr "Profile" + +# -- components/battery.tsx -- +# (Battery section title) +#: components/battery.tsx:42 +msgid "Battery" +msgstr "Batterie" + +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +#: components/battery.tsx:46 +msgid "Now (Charge)" +msgstr "Présentement (Charge)" + +# (Maximum capacity of battery, with percentage of design capacity in brackets) +#: components/battery.tsx:52 +msgid "Max (Design)" +msgstr "Max (Conçue)" + +# (Charge current limit override toggle) +#: components/battery.tsx:59 +msgid "Charge Current Limits" +msgstr "Limites de courant de charge" + +# (Charge current limit override toggle description) +#: components/battery.tsx:60 +msgid "Control battery charge rate when awake" +msgstr "Contrôler le taux de charge quand actif" + +# (Battery maximum input current with unit) +#: components/battery.tsx:74 +msgid "Maximum (mA)" +msgstr "Maximum (mA)" + +# (Battery charge mode override toggle) +#: components/battery.tsx:97,115 +msgid "Charge Mode" +msgstr "Mode de Charge" + +# (Battery charge mode override toggle description) +#: components/battery.tsx:98 +msgid "Force battery charge mode" +msgstr "Forcer le mode de charge de la batterie" + +# (Battery charge mode dropdown) +#: components/battery.tsx:112 +msgid "Mode" +msgstr "Mode" + +# (Battery current display) +#: components/battery.tsx:133 +msgid "Current" +msgstr "Courant" + +# -- components/cpus.tsx -- +# (CPU section title) +#: components/cpus.tsx:64 +msgid "CPU" +msgstr "CPU" + +# (CPU advanced mode toggle) +#: components/cpus.tsx:70 +msgid "Advanced" +msgstr "Avancé" + +# (CPU advanced mode toggle description) +#: components/cpus.tsx:71 +msgid "Enables per-thread configuration" +msgstr "Permet la configuration par fil d'exécution" + +# (CPU Simultaneous MultiThreading toggle) +#: components/cpus.tsx:88 +msgid "SMT" +msgstr "Multifil Simultané" + +# (CPU SMT toggle description) +#: components/cpus.tsx:89 +msgid "Enables odd-numbered CPUs" +msgstr "Active un nombre impair de fils d'exécution" + +# (CPU thread count slider) +#: components/cpus.tsx:106 +msgid "Threads" +msgstr "Fils" + +# (Clock speed override toggle) +#: components/cpus.tsx:137 components/gpu.tsx:112 +msgid "Frequency Limits" +msgstr "Limites de fréquence" + +# (Clock speed override toggle description) +#: components/cpus.tsx:138 components/gpu.tsx:113 +msgid "Set bounds on clock speed" +msgstr "Fixer les limites sur la fréquence d'horloge" + +# (Minimum clock speed with unit) +#: components/cpus.tsx:165 components/gpu.tsx:137 +msgid "Minimum (MHz)" +msgstr "Minimum (MHz)" + +# (Maximum clock speed with unit) +#: components/cpus.tsx:195 components/gpu.tsx:160 +msgid "Maximum (MHz)" +msgstr "Maximum (MHz)" + +# advanced mode +# (CPU selection slider) +#: components/cpus.tsx:226 +msgid "Selected CPU" +msgstr "CPU Sélectionnée" + +# (CPU Online toggle) +#: components/cpus.tsx:246 +msgid "Online" +msgstr "En Ligne" + +# (CPU Online description) +#: components/cpus.tsx:247 +msgid "Allow the CPU thread to do work" +msgstr "Permettre le fil d'exécution à travailler" + +# (CPU scheduling governor dropdown -- governor names are not translated) +#: components/cpus.tsx:342 +msgid "Governor" +msgstr "Régulateur" + +# -- components/debug.tsx -- +# (Debug section title) +#: components/debug.tsx:29 +msgid "Debug" +msgstr "Déboguer" + +# (Version display for native back-end of PowerTools) +#: components/debug.tsx:33 +msgid "Native" +msgstr "Natif" + +# (Mode display for framework of USDPL API) +#: components/debug.tsx:47 +msgid "Framework" +msgstr "Cadre d'application" + +# (Display for software implementation in PowerTools which applies settings) +#: components/debug.tsx:54 +msgid "Driver" +msgstr "Pilote" + +# -- components/gpu.tsx -- +# (GPU section title) +#: components/gpu.tsx:34 +msgid "GPU" +msgstr "GPU" + +# (PPT Limits override toggle) +#: components/gpu.tsx:39 +msgid "PowerPlay Limits" +msgstr "Limites du PowerPlay" + +# (PPT Limits override toggle description) +#: components/gpu.tsx:40 +msgid "Override APU TDP settings" +msgstr "Remplacer les paramètres TDP du processeur auxiliaire" + +# (SlowPPT slider with unit) +#: components/gpu.tsx:63 +msgid "SlowPPT (W)" +msgstr "SlowPPT (W)" + +# (FastPPT slider with unit) +#: components/gpu.tsx:87 +msgid "FastPPT (W)" +msgstr "FastPPT (W)" + +# (Reduce memory clock speed toggle) +#: components/gpu.tsx:112 +msgid "Downclock Memory" +msgstr "Souscadencer la mémoire" + +# (Reduce memory clock speed toggle description) +#: components/gpu.tsx:112 +msgid "Force RAM into low-power mode" +msgstr "Forcer la mémoire vive en mode basse consommation" From a8fce1e11c5c240bfc562b0b04143289b11682b9 Mon Sep 17 00:00:00 2001 From: danyi <459280185@qq.com> Date: Fri, 13 Jan 2023 01:11:25 +0800 Subject: [PATCH 30/44] Add Simplified Chinese translation (#61) * Create zh_CN.po * Create zh_CN.mo * Delete zh_CN.mo * Update zh_CN.po --- translations/zh_CN.po | 229 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 translations/zh_CN.po diff --git a/translations/zh_CN.po b/translations/zh_CN.po new file mode 100644 index 0000000..6ab791c --- /dev/null +++ b/translations/zh_CN.po @@ -0,0 +1,229 @@ +# TEMPLATE TITLE. +# Copyright (C) 2023 NGnius +# This file is distributed under the same license as the PowerTools package. +# NGnius (Graham) , 2023. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-12 \n" +"PO-Revision-Date: 2023-01-12 \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# -- index.tsx -- + +#: index.tsx:226 +# (Section title) +msgid "Miscellaneou" +msgstr "其他选项" + +#: index.tsx:226 +# (Profile persistence toggle) +msgid "Persistent" +msgstr "持久" + +#: index.tsx:227 +# (Profile persistence toggle description) +msgid "Save profile and load it next time" +msgstr "保存配置并自动加载" + +#: index.tsx:239 +# (Profile display) +msgid "Profile" +msgstr "配置文件" + +# -- components/battery.tsx -- + +#: components/battery.tsx:42 +# (Battery section title) +msgid "Battery" +msgstr "电池" + +#: components/battery.tsx:46 +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +msgid "Now (Charge)" +msgstr "充电中 (Charge)" + +#: components/battery.tsx:52 +# (Maximum capacity of battery, with percentage of design capacity in brackets) +msgid "Max (Design)" +msgstr "最大电量 (Design)" + +#: components/battery.tsx:59 +# (Charge current limit override toggle) +msgid "Charge Current Limits" +msgstr "充电电流限制" + +#: components/battery.tsx:60 +# (Charge current limit override toggle description) +msgid "Control battery charge rate when awake" +msgstr "控制电池充电效率" + +#: components/battery.tsx:74 +# (Battery maximum input current with unit) +msgid "Maximum (mA)" +msgstr "最大 (mA)" + +#: components/battery.tsx:97,115 +# (Battery charge mode override toggle) +msgid "Charge Mode" +msgstr "充电模式" + +#: components/battery.tsx:98 +# (Battery charge mode override toggle description) +msgid "Force battery charge mode" +msgstr "强制电池充电模式" + +#: components/battery.tsx:112 +# (Battery charge mode dropdown) +msgid "Mode" +msgstr "模式" + +#: components/battery.tsx:133 +# (Battery current display) +msgid "Current" +msgstr "当前" + +# -- components/cpus.tsx -- + +#: components/cpus.tsx:64 +# (CPU section title) +msgid "CPU" +msgstr "CPU" + +#: components/cpus.tsx:70 +# (CPU advanced mode toggle) +msgid "Advanced" +msgstr "高级" + +#: components/cpus.tsx:71 +# (CPU advanced mode toggle description) +msgid "Enables per-thread configuration" +msgstr "线程设置" + +#: components/cpus.tsx:88 +# (CPU Simultaneous MultiThreading toggle) +msgid "SMT" +msgstr "超线程" + +#: components/cpus.tsx:89 +# (CPU SMT toggle description) +msgid "Enables odd-numbered CPUs" +msgstr "启用超线程" + +#: components/cpus.tsx:106 +# (CPU thread count slider) +msgid "Threads" +msgstr "线程数" + +#: components/cpus.tsx:137 +#: components/gpu.tsx:112 +# (Clock speed override toggle) +msgid "Frequency Limits" +msgstr "频率限制" + +#: components/cpus.tsx:138 +#: components/gpu.tsx:113 +# (Clock speed override toggle description) +msgid "Set bounds on clock speed" +msgstr "设置频率" + +#: components/cpus.tsx:165 +#: components/gpu.tsx:137 +# (Minimum clock speed with unit) +msgid "Minimum (MHz)" +msgstr "最小 (MHz)" + +#: components/cpus.tsx:195 +#: components/gpu.tsx:160 +# (Maximum clock speed with unit) +msgid "Maximum (MHz)" +msgstr "最大 (MHz)" + +# advanced mode + +#: components/cpus.tsx:226 +# (CPU selection slider) +msgid "Selected CPU" +msgstr "选择 CPU" + +#: components/cpus.tsx:246 +# (CPU Online toggle) +msgid "Online" +msgstr "在线" + +#: components/cpus.tsx:247 +# (CPU Online description) +msgid "Allow the CPU thread to do work" +msgstr "允许 CPU 工作线程" + +#: components/cpus.tsx:342 +# (CPU scheduling governor dropdown -- governor names are not translated) +msgid "Governor" +msgstr "稳压" + +# -- components/debug.tsx -- + +#: components/debug.tsx:29 +# (Debug section title) +msgid "Debug" +msgstr "Debug" + +#: components/debug.tsx:33 +# (Version display for native back-end of PowerTools) +msgid "Native" +msgstr "本地版本" + +#: components/debug.tsx:47 +# (Mode display for framework of USDPL API) +msgid "Framework" +msgstr "API 框架" + +#: components/debug.tsx:54 +# (Display for software implementation in PowerTools which applies settings) +msgid "Driver" +msgstr "驱动程序" + +# -- components/gpu.tsx -- + +#: components/gpu.tsx:34 +# (GPU section title) +msgid "GPU" +msgstr "GPU" + +#: components/gpu.tsx:39 +# (PPT Limits override toggle) +msgid "PowerPlay Limits" +msgstr "PowerPlay 限制" + +#: components/gpu.tsx:40 +# (PPT Limits override toggle description) +msgid "Override APU TDP settings" +msgstr "覆盖 APU TDP 设置" + +#: components/gpu.tsx:63 +# (SlowPPT slider with unit) +msgid "SlowPPT (W)" +msgstr "SlowPPT (W)" + +#: components/gpu.tsx:87 +# (FastPPT slider with unit) +msgid "FastPPT (W)" +msgstr "FastPPT (W)" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle) +msgid "Downclock Memory" +msgstr "降低内存频率" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle description) +msgid "Force RAM into low-power mode" +msgstr "强制内存进入低功耗模式" From 79bb4987fc27a69a1e444daaaa24d4584b860670 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 14 Jan 2023 15:00:30 -0500 Subject: [PATCH 31/44] Update translations template and minor packaging config changes --- .gitignore | 4 ++++ translations/pt.pot | 4 +--- translations/test.po | 2 -- translations/zh_CN.mo | Bin 0 -> 2274 bytes translations/zh_CN.po | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 translations/zh_CN.mo diff --git a/.gitignore b/.gitignore index 22cbe24..5a71389 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,7 @@ yalc.lock /bin /backend/out /**/target + +# packaging +/PowerTools +**.zip diff --git a/translations/pt.pot b/translations/pt.pot index ee4e1b4..44e2e02 100644 --- a/translations/pt.pot +++ b/translations/pt.pot @@ -2,8 +2,6 @@ # Copyright (C) 2023 NGnius # This file is distributed under the same license as the PowerTools package. # NGnius (Graham) , 2023. -# -#, fuzzy msgid "" msgstr "" "Project-Id-Version: v1.1\n" @@ -87,7 +85,7 @@ msgid "Mode" msgstr "" #: components/battery.tsx:133 -# (Battery current display) +# (Battery electrical current display) msgid "Current" msgstr "" diff --git a/translations/test.po b/translations/test.po index c181fc2..8ba4fcb 100644 --- a/translations/test.po +++ b/translations/test.po @@ -2,8 +2,6 @@ # Copyright (C) 2023 NGnius # This file is distributed under the same license as the PowerTools package. # NGnius (Graham) , 2023. -# -#, fuzzy msgid "" msgstr "" "Project-Id-Version: v1.1\n" diff --git a/translations/zh_CN.mo b/translations/zh_CN.mo new file mode 100644 index 0000000000000000000000000000000000000000..76a86760f612d53ac9768cac51b698d8b98e8a8a GIT binary patch literal 2274 zcmZ9LU2IfE6vsydKNbZ=QT$~5088R!DTV~r_)xlhC2ZNyMPD%H?%wJ4%H5geezedB zLlc+sAq65}ffa!$6!{KPXld<>CYtc#gV6`$)874v4ApH2Yehn2I9v~<1-gL1I`3T!G+*2 zAnDx!XMq2L&w&4dkAbtMGxicV7vx|ZB>Ob@8n`*y?*X5Ldi1W)e-|V__ab>Fl1z5< zK+<0j$?t*`&x&Y$JxG4qBiRHge?^e&dqJvWKllnb08(5(MEm0)oqHQ3y+1*uFL;-v zPlNo=!sM7_OXDrfXEEt*(tsIz2a{?|gK8DT4^kd+tspLXD^xccFN6rrr5aKG9v*LF zVFBjzn9pIpj`=bs)nFke#ZLK{I;fv0*OWJU(?LtM7+t!|34^s*mg?qir{JyWO`t7w zgS(0wigzn}3tOqXuCTW=?6THQ-OfYNvuz<=zTPaDt~0TkQifoyO1iePcs8`+xzNJa zUBSCMh2(m-z6ENb2bL6BFVB*yTjng4+rm?#pm0{wHoJt)R!Kc;35P4g(4<$$3R@Ty zrE`C$C~PeXIj3ZYnfGv#sU%yiJ8n9i;Y}YcVyl&%6MSP!iklJ_!*#Wy>J~OHP{iTx zL-B??wq6iH4p!S@t0!b``^1&kAQ@{EVwB2eDSaDnN(#r!%S9xZ1+T!HQfqsrNQD*% zrkuKEIyqrkx)jP|LGIcRdY52rC`VJ6=|yaVv`i`31{`IZhTtuzQ6`z@j&NO5<{g$6 zwqrUj%E8ifskEivk1}nm4$~5>J(XeYdY9nEaDnU6KpIeI)8$fZbGd64pe8JlbHfxv zaCugF(m?tp53A!81s+U05;&3COz>O~g{?k?t+vk4KBRz@Oz^Je#m%veqNr?FOF4Pd z&{leRN6V-L?{wXwlZeOjrrYUd7w1$V-nK@Xo)Zu5kWtEV;-=$x!il9fXd6YBNj|kC zo>77?U9$8&ZAr7%yp+e*qt05!)}>?VuCf!fBJ-Y}7g|Q>g(-4^_jG>J+7?T#ORbs= zvU%~67`<8KPs?mC!n=!n#EX`0%J+lUi%fsuxgFZ_Nj*BQ121ot%qas^Nbu!Z(~Ysl z`GMNVS>~5|>z8f@?d0G1t}<4xjf~d@_p;id>(#3#gGTa8B}lYzy|;1nfWK=9RXVw0*SPKoJjl;WY{e8?I`_kXNFY24d(S4P%et&1lzc|o1eUSDW=dSvD2637{ zvY+_}F4qnX)`vFa1~>yYxVZ_@g5@E_75MKkk, 2023. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: v1.1\n" From 12e75cd2f361c9808fd5ef7a8f55aa199229a9c4 Mon Sep 17 00:00:00 2001 From: danyi <459280185@qq.com> Date: Mon, 16 Jan 2023 03:20:12 +0800 Subject: [PATCH 32/44] Create zh_HK.po (#63) --- translations/zh_HK.po | 229 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 translations/zh_HK.po diff --git a/translations/zh_HK.po b/translations/zh_HK.po new file mode 100644 index 0000000..5c14851 --- /dev/null +++ b/translations/zh_HK.po @@ -0,0 +1,229 @@ +# TEMPLATE TITLE. +# Copyright (C) 2023 NGnius +# This file is distributed under the same license as the PowerTools package. +# NGnius (Graham) , 2023. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-12 \n" +"PO-Revision-Date: 2023-01-12 \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: zh_HK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# -- index.tsx -- + +#: index.tsx:226 +# (Section title) +msgid "Miscellaneou" +msgstr "其他選項" + +#: index.tsx:226 +# (Profile persistence toggle) +msgid "Persistent" +msgstr "持續" + +#: index.tsx:227 +# (Profile persistence toggle description) +msgid "Save profile and load it next time" +msgstr "保存配置並自動載入" + +#: index.tsx:239 +# (Profile display) +msgid "Profile" +msgstr "配置文件" + +# -- components/battery.tsx -- + +#: components/battery.tsx:42 +# (Battery section title) +msgid "Battery" +msgstr "電池" + +#: components/battery.tsx:46 +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +msgid "Now (Charge)" +msgstr "此刻 (正在充電中)" + +#: components/battery.tsx:52 +# (Maximum capacity of battery, with percentage of design capacity in brackets) +msgid "Max (Design)" +msgstr "最大電量 (設計)" + +#: components/battery.tsx:59 +# (Charge current limit override toggle) +msgid "Charge Current Limits" +msgstr "充電電流限制" + +#: components/battery.tsx:60 +# (Charge current limit override toggle description) +msgid "Control battery charge rate when awake" +msgstr "控制電池充電效率" + +#: components/battery.tsx:74 +# (Battery maximum input current with unit) +msgid "Maximum (mA)" +msgstr "最大 (mA)" + +#: components/battery.tsx:97,115 +# (Battery charge mode override toggle) +msgid "Charge Mode" +msgstr "充電模式" + +#: components/battery.tsx:98 +# (Battery charge mode override toggle description) +msgid "Force battery charge mode" +msgstr "強制電池充電模式" + +#: components/battery.tsx:112 +# (Battery charge mode dropdown) +msgid "Mode" +msgstr "模式" + +#: components/battery.tsx:133 +# (Battery current display) +msgid "Current" +msgstr "當前" + +# -- components/cpus.tsx -- + +#: components/cpus.tsx:64 +# (CPU section title) +msgid "CPU" +msgstr "CPU" + +#: components/cpus.tsx:70 +# (CPU advanced mode toggle) +msgid "Advanced" +msgstr "進階" + +#: components/cpus.tsx:71 +# (CPU advanced mode toggle description) +msgid "Enables per-thread configuration" +msgstr "線程設定" + +#: components/cpus.tsx:88 +# (CPU Simultaneous MultiThreading toggle) +msgid "SMT" +msgstr "同步多執行緒" + +#: components/cpus.tsx:89 +# (CPU SMT toggle description) +msgid "Enables odd-numbered CPUs" +msgstr "啟用多執行緒CPU" + +#: components/cpus.tsx:106 +# (CPU thread count slider) +msgid "Threads" +msgstr "線程數" + +#: components/cpus.tsx:137 +#: components/gpu.tsx:112 +# (Clock speed override toggle) +msgid "Frequency Limits" +msgstr "頻率限制" + +#: components/cpus.tsx:138 +#: components/gpu.tsx:113 +# (Clock speed override toggle description) +msgid "Set bounds on clock speed" +msgstr "設定頻率" + +#: components/cpus.tsx:165 +#: components/gpu.tsx:137 +# (Minimum clock speed with unit) +msgid "Minimum (MHz)" +msgstr "最小 (MHz)" + +#: components/cpus.tsx:195 +#: components/gpu.tsx:160 +# (Maximum clock speed with unit) +msgid "Maximum (MHz)" +msgstr "最大 (MHz)" + +# advanced mode + +#: components/cpus.tsx:226 +# (CPU selection slider) +msgid "Selected CPU" +msgstr "選擇 CPU" + +#: components/cpus.tsx:246 +# (CPU Online toggle) +msgid "Online" +msgstr "線上" + +#: components/cpus.tsx:247 +# (CPU Online description) +msgid "Allow the CPU thread to do work" +msgstr "允许CPU工作線程" + +#: components/cpus.tsx:342 +# (CPU scheduling governor dropdown -- governor names are not translated) +msgid "Governor" +msgstr "穩壓" + +# -- components/debug.tsx -- + +#: components/debug.tsx:29 +# (Debug section title) +msgid "Debug" +msgstr "除錯" + +#: components/debug.tsx:33 +# (Version display for native back-end of PowerTools) +msgid "Native" +msgstr "原生版本" + +#: components/debug.tsx:47 +# (Mode display for framework of USDPL API) +msgid "Framework" +msgstr "API 架構" + +#: components/debug.tsx:54 +# (Display for software implementation in PowerTools which applies settings) +msgid "Driver" +msgstr "驅動程式" + +# -- components/gpu.tsx -- + +#: components/gpu.tsx:34 +# (GPU section title) +msgid "GPU" +msgstr "GPU" + +#: components/gpu.tsx:39 +# (PPT Limits override toggle) +msgid "PowerPlay Limits" +msgstr "PowerPlay 限制" + +#: components/gpu.tsx:40 +# (PPT Limits override toggle description) +msgid "Override APU TDP settings" +msgstr "覆蓋 APU TDP 設定" + +#: components/gpu.tsx:63 +# (SlowPPT slider with unit) +msgid "SlowPPT (W)" +msgstr "SlowPPT (W)" + +#: components/gpu.tsx:87 +# (FastPPT slider with unit) +msgid "FastPPT (W)" +msgstr "FastPPT (W)" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle) +msgid "Downclock Memory" +msgstr "降低記憶體頻率" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle description) +msgid "Force RAM into low-power mode" +msgstr "強制記憶體進入低功率消耗模式" From 8332649e45f43c7df8db2336554db4cfdae8ff63 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 16 Jan 2023 18:46:40 -0500 Subject: [PATCH 33/44] Disallow setting max < min and min > max because the kernel now does too --- backend/src/api/cpu.rs | 14 ++++- backend/src/api/gpu.rs | 16 ++++- backend/src/api/handler.rs | 117 ++++++++++++++++++++++++---------- src/components/cpus.tsx | 124 +++++++++++++++++++------------------ src/components/gpu.tsx | 40 ++++++------ 5 files changed, 192 insertions(+), 119 deletions(-) diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index 02e2f1e..1c4d35f 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -159,8 +159,18 @@ pub fn set_clock_limits( if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(min)) = params_in.get(1) { if let Some(&Primitive::F64(max)) = params_in.get(2) { - setter(index as usize, MinMax {min: min as u64, max: max as u64}); - vec![min.into(), max.into()] + let safe_max = if max < min { + min + } else { + max + }; + let safe_min = if min > max { + max + } else { + min + }; + setter(index as usize, MinMax {min: safe_min as u64, max: safe_max as u64}); + vec![safe_min.into(), safe_max.into()] } else { vec!["set_clock_limits missing parameter 2".into()] } diff --git a/backend/src/api/gpu.rs b/backend/src/api/gpu.rs index e23ba85..819eb89 100644 --- a/backend/src/api/gpu.rs +++ b/backend/src/api/gpu.rs @@ -78,11 +78,21 @@ pub fn set_clock_limits( move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(min)) = params_in.get(0) { if let Some(&Primitive::F64(max)) = params_in.get(1) { + let safe_max = if max < min { + min + } else { + max + }; + let safe_min = if min > max { + max + } else { + min + }; setter(MinMax { - min: min as _, - max: max as _, + min: safe_min as _, + max: safe_max as _, }); - vec![(min as u64).into(), (max as u64).into()] + vec![(safe_min as u64).into(), (safe_max as u64).into()] } else { vec!["set_clock_limits missing parameter 1".into()] } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index e7672e6..2b9cd60 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -32,7 +32,8 @@ pub enum BatteryMessage { } impl BatteryMessage { - fn process(self, settings: &mut dyn TBattery) { + fn process(self, settings: &mut dyn TBattery) -> bool { + let dirty = self.is_modify(); match self { Self::SetChargeRate(rate) => settings.charge_rate(rate), Self::GetChargeRate(cb) => cb(settings.get_charge_rate()), @@ -43,6 +44,12 @@ impl BatteryMessage { Self::ReadChargeDesign(cb) => cb(settings.read_charge_design()), Self::ReadCurrentNow(cb) => cb(settings.read_current_now()), } + dirty + } + + /// Message instructs the driver to modify settings + fn is_modify(&self) -> bool { + matches!(self, Self::SetChargeRate(_) | Self::SetChargeMode(_)) } } @@ -59,7 +66,8 @@ pub enum CpuMessage { } impl CpuMessage { - fn process(self, settings: &mut dyn TCpus) { + fn process(self, settings: &mut dyn TCpus) -> bool { + let dirty = self.is_modify(); // NOTE: "cpu" refers to the Linux kernel definition of a CPU, which is actually a hardware thread // not to be confused with a CPU chip, which usually has multiple hardware threads (cpu cores/threads) in the chip match self { @@ -129,6 +137,18 @@ impl CpuMessage { cb(result); } } + dirty + } + + /// Message instructs the driver to modify settings + fn is_modify(&self) -> bool { + matches!(self, + Self::SetCpuOnline(_, _) + | Self::SetCpusOnline(_) + | Self::SetClockLimits(_, _) + | Self::SetCpuGovernor(_, _) + | Self::SetCpusGovernor(_) + ) } } @@ -142,7 +162,8 @@ pub enum GpuMessage { } impl GpuMessage { - fn process(self, settings: &mut dyn TGpu) { + fn process(self, settings: &mut dyn TGpu) -> bool { + let dirty = self.is_modify(); match self { Self::SetPpt(fast, slow) => settings.ppt(fast, slow), Self::GetPpt(cb) => cb(settings.get_ppt()), @@ -151,6 +172,15 @@ impl GpuMessage { Self::SetSlowMemory(val) => *settings.slow_memory() = val, Self::GetSlowMemory(cb) => cb(*settings.slow_memory()), } + dirty + } + + fn is_modify(&self) -> bool { + matches!(self, + Self::SetPpt(_, _) + | Self::SetClockLimits(_) + | Self::SetSlowMemory(_) + ) } } @@ -161,12 +191,18 @@ pub enum GeneralMessage { } impl GeneralMessage { - fn process(self, settings: &mut dyn TGeneral) { + fn process(self, settings: &mut dyn TGeneral) -> bool { + let dirty = self.is_modify(); match self { Self::SetPersistent(val) => *settings.persistent() = val, Self::GetPersistent(cb) => cb(*settings.persistent()), Self::GetCurrentProfileName(cb) => cb(settings.get_name().to_owned()), } + dirty + } + + fn is_modify(&self) -> bool { + matches!(self, Self::SetPersistent(_)) } } @@ -178,43 +214,47 @@ pub struct ApiMessageHandler { impl ApiMessageHandler { pub fn process_forever(&mut self, settings: &mut Settings) { while let Ok(msg) = self.intake.recv() { - self.process(settings, msg); + let mut dirty = self.process(settings, msg); while let Ok(msg) = self.intake.try_recv() { - self.process(settings, msg); - } - // run on_set - if let Err(e) = settings.on_set() { - log::error!("Settings on_set() err: {}", e); - } - // do callbacks - for func in self.on_empty.drain(..) { - func(()); + dirty |= self.process(settings, msg); } - // save - log::debug!("api_worker is saving..."); - let is_persistent = *settings.general.persistent(); - let save_path = crate::utility::settings_dir() - .join(settings.general.get_path().clone()); - if is_persistent { - let settings_clone = settings.json(); - let save_json: SettingsJson = settings_clone.into(); - unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); - log::debug!("Saved settings to {}", save_path.display()); - } else { - if save_path.exists() { - if let Err(e) = std::fs::remove_file(&save_path) { - log::warn!("Failed to delete persistent settings file {}: {}", save_path.display(), e); + if dirty { + // run on_set + if let Err(e) = settings.on_set() { + log::error!("Settings on_set() err: {}", e); + } + // do callbacks + for func in self.on_empty.drain(..) { + func(()); + } + // save + log::debug!("api_worker is saving..."); + let is_persistent = *settings.general.persistent(); + let save_path = crate::utility::settings_dir() + .join(settings.general.get_path().clone()); + if is_persistent { + let settings_clone = settings.json(); + let save_json: SettingsJson = settings_clone.into(); + unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); + log::debug!("Saved settings to {}", save_path.display()); + } else { + if save_path.exists() { + if let Err(e) = std::fs::remove_file(&save_path) { + log::warn!("Failed to delete persistent settings file {}: {}", save_path.display(), e); + } else { + log::debug!("Deleted persistent settings file {}", save_path.display()); + } } else { - log::debug!("Deleted persistent settings file {}", save_path.display()); + log::debug!("Ignored save request for non-persistent settings"); } - } else { - log::debug!("Ignored save request for non-persistent settings"); } + } else { + log::debug!("Skipping callbacks for non-modify handled message(s)"); } } } - pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) { + pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) -> bool { match message { ApiMessage::Battery(x) => x.process(settings.battery.as_mut()), ApiMessage::Cpu(x) => x.process(settings.cpus.as_mut()), @@ -224,13 +264,18 @@ impl ApiMessageHandler { if let Err(e) = settings.on_resume() { log::error!("Settings on_resume() err: {}", e); } + false } - ApiMessage::WaitForEmptyQueue(callback) => self.on_empty.push(callback), + ApiMessage::WaitForEmptyQueue(callback) => { + self.on_empty.push(callback); + false + }, ApiMessage::LoadSettings(path, name) => { match settings.load_file(path.into(), name, false) { Ok(success) => log::info!("Loaded settings file? {}", success), Err(e) => log::warn!("Load file err: {}", e), } + true } ApiMessage::LoadMainSettings => { match settings.load_file( @@ -241,9 +286,11 @@ impl ApiMessageHandler { Ok(success) => log::info!("Loaded main settings file? {}", success), Err(e) => log::warn!("Load file err: {}", e), } + true } ApiMessage::LoadSystemSettings => { settings.load_system_default(); + true }, ApiMessage::GetLimits(cb) => { cb(super::SettingsLimits { @@ -252,6 +299,7 @@ impl ApiMessageHandler { gpu: settings.gpu.limits(), general: settings.general.limits(), }); + false }, ApiMessage::GetProvider(name, cb) => { cb(match &name as &str { @@ -259,7 +307,8 @@ impl ApiMessageHandler { "cpu" | "cpus" => settings.cpus.provider(), "gpu" => settings.gpu.provider(), _ => settings.general.provider(), - }) + }); + false } } } diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx index cbb14a5..586200c 100644 --- a/src/components/cpus.tsx +++ b/src/components/cpus.tsx @@ -138,24 +138,24 @@ export class Cpus extends Component<{}, CpuState> { description={tr("Set bounds on clock speed")} onChange={(value: boolean) => { if (value) { - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { - set_value(CLOCK_MIN_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits!.min); - } - if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null) { - set_value(CLOCK_MAX_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits!.max); - } - syncPlebClockToAdvanced(); - reloadGUI("CPUFreqToggle"); + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits != null) { + set_value(CLOCK_MIN_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_min_limits!.min); + } + if ((get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits != null) { + set_value(CLOCK_MAX_CPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[0].clock_max_limits!.max); + } + syncPlebClockToAdvanced(); + reloadGUI("CPUFreqToggle"); } else { - set_value(CLOCK_MIN_CPU, null); - set_value(CLOCK_MAX_CPU, null); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.unsetCpuClockLimits(i), (_idc: any[]) => {}); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUUnsetFreq"); - }); - syncPlebClockToAdvanced(); + set_value(CLOCK_MIN_CPU, null); + set_value(CLOCK_MAX_CPU, null); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.unsetCpuClockLimits(i), (_idc: any[]) => {}); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUUnsetFreq"); + }); + syncPlebClockToAdvanced(); } }} /> @@ -172,20 +172,21 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Min freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_CPU); - if (freq != freqNow) { - set_value(CLOCK_MIN_CPU, freq); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.setCpuClockLimits(i, freq, get_value(CLOCK_MAX_CPU)), - (limits: number[]) => { - set_value(CLOCK_MIN_CPU, limits[0]); - set_value(CLOCK_MAX_CPU, limits[1]); - syncPlebClockToAdvanced(); + const maxNow = get_value(CLOCK_MAX_CPU); + if (freq != freqNow && ((maxNow != null && freq > maxNow) || maxNow == null)) { + set_value(CLOCK_MIN_CPU, freq); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.setCpuClockLimits(i, freq, get_value(CLOCK_MAX_CPU)), + (limits: number[]) => { + set_value(CLOCK_MIN_CPU, limits[0]); + set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); + }); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUMinFreq"); }); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUMinFreq"); - }); - reloadGUI("CPUMinFreqImmediate"); + reloadGUI("CPUMinFreqImmediate"); } }} />} @@ -202,20 +203,21 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Max freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MAX_CPU); - if (freq != freqNow) { - set_value(CLOCK_MAX_CPU, freq); - for (let i = 0; i < total_cpus; i++) { - backend.resolve(backend.setCpuClockLimits(i, get_value(CLOCK_MIN_CPU), freq), - (limits: number[]) => { - set_value(CLOCK_MIN_CPU, limits[0]); - set_value(CLOCK_MAX_CPU, limits[1]); - syncPlebClockToAdvanced(); + const minNow = get_value(CLOCK_MIN_CPU); + if (freq != freqNow && ((minNow != null && freq > minNow) || minNow == null)) { + set_value(CLOCK_MAX_CPU, freq); + for (let i = 0; i < total_cpus; i++) { + backend.resolve(backend.setCpuClockLimits(i, get_value(CLOCK_MIN_CPU), freq), + (limits: number[]) => { + set_value(CLOCK_MIN_CPU, limits[0]); + set_value(CLOCK_MAX_CPU, limits[1]); + syncPlebClockToAdvanced(); + }); + } + backend.resolve(backend.waitForComplete(), (_: boolean) => { + reloadGUI("CPUMaxFreq"); }); - } - backend.resolve(backend.waitForComplete(), (_: boolean) => { - reloadGUI("CPUMaxFreq"); - }); - reloadGUI("CPUMaxFreqImmediate"); + reloadGUI("CPUMaxFreqImmediate"); } }} />} @@ -301,15 +303,15 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.min) { - backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), - (limits: number[]) => { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = limits[0]; - clocks[advancedCpuIndex].max = limits[1]; - set_value(CLOCK_MIN_MAX_CPU, clocks); - reloadGUI("CPUMinFreq"); - }); + if (freq != freqNow.min && ((freqNow.max != null && freqNow.max > freq) || freqNow.max == null)) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMinFreq"); + }); } }} />} @@ -326,15 +328,15 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.max) { - backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), - (limits: number[]) => { - const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; - clocks[advancedCpuIndex].min = limits[0]; - clocks[advancedCpuIndex].max = limits[1]; - set_value(CLOCK_MIN_MAX_CPU, clocks); - reloadGUI("CPUMaxFreq"); - }); + if (freq != freqNow.max && ((freqNow.min != null && freq > freqNow.min) || freqNow.min == null)) { + backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), + (limits: number[]) => { + const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; + clocks[advancedCpuIndex].min = limits[0]; + clocks[advancedCpuIndex].max = limits[1]; + set_value(CLOCK_MIN_MAX_CPU, clocks); + reloadGUI("CPUMaxFreq"); + }); } }} />} diff --git a/src/components/gpu.tsx b/src/components/gpu.tsx index bcd9121..e101aeb 100644 --- a/src/components/gpu.tsx +++ b/src/components/gpu.tsx @@ -123,11 +123,11 @@ export class Gpu extends Component<{}> { } reloadGUI("GPUFreqToggle"); } else { - set_value(CLOCK_MIN_GPU, null); - set_value(CLOCK_MAX_GPU, null); - backend.resolve(backend.unsetGpuClockLimits(), (_: any[]) => { - reloadGUI("GPUUnsetFreq"); - }); + set_value(CLOCK_MIN_GPU, null); + set_value(CLOCK_MAX_GPU, null); + backend.resolve(backend.unsetGpuClockLimits(), (_: any[]) => { + reloadGUI("GPUUnsetFreq"); + }); } }} /> @@ -144,13 +144,14 @@ export class Gpu extends Component<{}> { onChange={(val: number) => { backend.log(backend.LogLevel.Debug, "GPU Clock Min is now " + val.toString()); const valNow = get_value(CLOCK_MIN_GPU); - if (val != valNow) { - backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), - (limits: number[]) => { - set_value(CLOCK_MIN_GPU, limits[0]); - set_value(CLOCK_MAX_GPU, limits[1]); - reloadGUI("GPUMinClock"); - }); + const maxNow = get_value(CLOCK_MAX_GPU); + if (val != valNow && ((maxNow != null && val < maxNow) || maxNow == null)) { + backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), + (limits: number[]) => { + set_value(CLOCK_MIN_GPU, limits[0]); + set_value(CLOCK_MAX_GPU, limits[1]); + reloadGUI("GPUMinClock"); + }); } }} />} @@ -167,13 +168,14 @@ export class Gpu extends Component<{}> { onChange={(val: number) => { backend.log(backend.LogLevel.Debug, "GPU Clock Max is now " + val.toString()); const valNow = get_value(CLOCK_MAX_GPU); - if (val != valNow) { - backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), - (limits: number[]) => { - set_value(CLOCK_MIN_GPU, limits[0]); - set_value(CLOCK_MAX_GPU, limits[1]); - reloadGUI("GPUMaxClock"); - }); + const minNow = get_value(CLOCK_MIN_GPU); + if (val != valNow && ((minNow != null && val > minNow) || minNow == null)) { + backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), + (limits: number[]) => { + set_value(CLOCK_MIN_GPU, limits[0]); + set_value(CLOCK_MAX_GPU, limits[1]); + reloadGUI("GPUMaxClock"); + }); } }} />} From df69a5a2db61cf2d89101b704b512c33f1902251 Mon Sep 17 00:00:00 2001 From: ZXRRX <97269621+ZXRRX@users.noreply.github.com> Date: Wed, 18 Jan 2023 00:02:42 +0100 Subject: [PATCH 34/44] es-ES translations (#62) * es-ES translations Added European Spanish translation * Update es-ES.po --- translations/es-ES.po | 229 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 translations/es-ES.po diff --git a/translations/es-ES.po b/translations/es-ES.po new file mode 100644 index 0000000..937fffe --- /dev/null +++ b/translations/es-ES.po @@ -0,0 +1,229 @@ +# TEMPLATE TITLE. +# Copyright (C) 2023 NGnius +# This file is distributed under the same license as the PowerTools package. +# NGnius (Graham) , 2023. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: v1.1\n" +"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" +"POT-Creation-Date: 2023-01-09 19:52-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# -- index.tsx -- + +#: index.tsx:226 +# (Section title) +msgid "Miscellaneous" +msgstr "Misceláneo" + +#: index.tsx:226 +# (Profile persistence toggle) +msgid "Persistent" +msgstr "Persistente" + +#: index.tsx:227 +# (Profile persistence toggle description) +msgid "Save profile and load it next time" +msgstr "Guardar perfil y cargarlo la próxima vez" + +#: index.tsx:239 +# (Profile display) +msgid "Profile" +msgstr "Perfil" + +# -- components/battery.tsx -- + +#: components/battery.tsx:42 +# (Battery section title) +msgid "Battery" +msgstr "Batería" + +#: components/battery.tsx:46 +# (Charge of battery at this moment, with percentage of expected full charge in brackets) +msgid "Now (Charge)" +msgstr "Ahora (Charge)" + +#: components/battery.tsx:52 +# (Maximum capacity of battery, with percentage of design capacity in brackets) +msgid "Max (Design)" +msgstr "Max (Design)" + +#: components/battery.tsx:59 +# (Charge current limit override toggle) +msgid "Charge Current Limits" +msgstr "Limite de carga" + +#: components/battery.tsx:60 +# (Charge current limit override toggle description) +msgid "Control battery charge rate when awake" +msgstr "Control de carga de la batería mientras está encendido" + +#: components/battery.tsx:74 +# (Battery maximum input current with unit) +msgid "Maximum (mA)" +msgstr "Máximo (mA)" + +#: components/battery.tsx:97,115 +# (Battery charge mode override toggle) +msgid "Charge Mode" +msgstr "Modo carga" + +#: components/battery.tsx:98 +# (Battery charge mode override toggle description) +msgid "Force battery charge mode" +msgstr "Forzar modo carga de la batería" + +#: components/battery.tsx:112 +# (Battery charge mode dropdown) +msgid "Mode" +msgstr "Modo" + +#: components/battery.tsx:133 +# (Battery current display) +msgid "Current" +msgstr "Corriente" + +# -- components/cpus.tsx -- + +#: components/cpus.tsx:64 +# (CPU section title) +msgid "CPU" +msgstr "CPU" + +#: components/cpus.tsx:70 +# (CPU advanced mode toggle) +msgid "Advanced" +msgstr "Avanzado" + +#: components/cpus.tsx:71 +# (CPU advanced mode toggle description) +msgid "Enables per-thread configuration" +msgstr "Habilita la configuración por subprocesos" + +#: components/cpus.tsx:88 +# (CPU Simultaneous MultiThreading toggle) +msgid "SMT" +msgstr "SMT" + +#: components/cpus.tsx:89 +# (CPU SMT toggle description) +msgid "Enables odd-numbered CPUs" +msgstr "Habilita CPUs impares" + +#: components/cpus.tsx:106 +# (CPU thread count slider) +msgid "Threads" +msgstr "Subprocesos" + +#: components/cpus.tsx:137 +#: components/gpu.tsx:112 +# (Clock speed override toggle) +msgid "Frequency Limits" +msgstr "Límites de frecuencia" + +#: components/cpus.tsx:138 +#: components/gpu.tsx:113 +# (Clock speed override toggle description) +msgid "Set bounds on clock speed" +msgstr "Establecer límites en la velocidad de reloj" + +#: components/cpus.tsx:165 +#: components/gpu.tsx:137 +# (Minimum clock speed with unit) +msgid "Minimum (MHz)" +msgstr "Mínimo (MHz)" + +#: components/cpus.tsx:195 +#: components/gpu.tsx:160 +# (Maximum clock speed with unit) +msgid "Maximum (MHz)" +msgstr "Máximo (MHz)" + +# advanced mode + +#: components/cpus.tsx:226 +# (CPU selection slider) +msgid "Selected CPU" +msgstr "CPU seleccionada" + +#: components/cpus.tsx:246 +# (CPU Online toggle) +msgid "Online" +msgstr "Online" + +#: components/cpus.tsx:247 +# (CPU Online description) +msgid "Allow the CPU thread to do work" +msgstr "Permite que el subproceso de la CPU funcione" + +#: components/cpus.tsx:342 +# (CPU scheduling governor dropdown -- governor names are not translated) +msgid "Governor" +msgstr "Gobernador" + +# -- components/debug.tsx -- + +#: components/debug.tsx:29 +# (Debug section title) +msgid "Debug" +msgstr "Depurar" + +#: components/debug.tsx:33 +# (Version display for native back-end of PowerTools) +msgid "Native" +msgstr "Nativo" + +#: components/debug.tsx:47 +# (Mode display for framework of USDPL API) +msgid "Framework" +msgstr "Framework" + +#: components/debug.tsx:54 +# (Display for software implementation in PowerTools which applies settings) +msgid "Driver" +msgstr "Controlador" + +# -- components/gpu.tsx -- + +#: components/gpu.tsx:34 +# (GPU section title) +msgid "GPU" +msgstr "GPU" + +#: components/gpu.tsx:39 +# (PPT Limits override toggle) +msgid "PowerPlay Limits" +msgstr "Límites de PowerPlay" + +#: components/gpu.tsx:40 +# (PPT Limits override toggle description) +msgid "Override APU TDP settings" +msgstr "Anular la configuración del APU TDP" + +#: components/gpu.tsx:63 +# (SlowPPT slider with unit) +msgid "SlowPPT (W)" +msgstr "SlowPPT (W)" + +#: components/gpu.tsx:87 +# (FastPPT slider with unit) +msgid "FastPPT (W)" +msgstr "FastPPT (W)" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle) +msgid "Downclock Memory" +msgstr "Memoria descendente" + +#: components/gpu.tsx:112 +# (Reduce memory clock speed toggle description) +msgid "Force RAM into low-power mode" +msgstr "Forzar RAM a modo ahorro de energía" From aff5005ca9b7efebac5d9814a911e6fccc95b068 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Wed, 18 Jan 2023 17:54:33 -0500 Subject: [PATCH 35/44] Allow max == min, fix SMT bug, compile missing .mo files --- backend/Cargo.lock | 2 +- backend/Cargo.toml | 2 +- backend/src/api/handler.rs | 1 + backend/src/settings/steam_deck/cpu.rs | 5 +- backend/src/settings/steam_deck/oc_limits.rs | 10 ++-- package.json | 2 +- pt_oc.json | 47 +++++++++++++++++++ src/components/cpus.tsx | 8 ++-- src/components/gpu.tsx | 4 +- translations/es-ES.mo | Bin 0 -> 2450 bytes translations/es-ES.po | 8 ++-- translations/{zh_CN.mo => zh-CN.mo} | Bin translations/{zh_CN.po => zh-CN.po} | 0 translations/zh-HK.mo | Bin 0 -> 2306 bytes translations/{zh_HK.po => zh-HK.po} | 0 15 files changed, 71 insertions(+), 18 deletions(-) create mode 100644 pt_oc.json create mode 100644 translations/es-ES.mo rename translations/{zh_CN.mo => zh-CN.mo} (100%) rename translations/{zh_CN.po => zh-CN.po} (100%) create mode 100644 translations/zh-HK.mo rename translations/{zh_HK.po => zh-HK.po} (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 53a7aa6..4576e9a 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "powertools-rs" -version = "1.1.0" +version = "1.1.0-beta4" dependencies = [ "async-trait", "limits_core", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 8bbfa40..d154972 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "powertools-rs" -version = "1.1.0" +version = "1.1.0-beta4" edition = "2021" authors = ["NGnius (Graham) "] description = "Backend (superuser) functionality for PowerTools" diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 2b9cd60..48a4962 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -145,6 +145,7 @@ impl CpuMessage { matches!(self, Self::SetCpuOnline(_, _) | Self::SetCpusOnline(_) + | Self::SetSmt(_, _) | Self::SetClockLimits(_, _) | Self::SetCpuGovernor(_, _) | Self::SetCpusGovernor(_) diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 2c3544a..539a5f4 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -256,7 +256,8 @@ impl Cpu { }, )?; // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, clock_limits.min); + let valid_min = if clock_limits.min < self.limits.clock_min.min {self.limits.clock_min.min} else {clock_limits.min}; + let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min); usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( |e| SettingError { msg: format!( @@ -339,7 +340,7 @@ impl Cpu { fn limits(&self) -> crate::api::CpuLimits { crate::api::CpuLimits { clock_min_limits: Some(RangeLimit { - min: self.limits.clock_min.min, + min: self.limits.clock_max.min, // allows min to be set by max (it's weird, blame the kernel) max: self.limits.clock_min.max }), clock_max_limits: Some(RangeLimit { diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index fe45826..da5cefa 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use crate::settings::MinMax; -const OC_LIMITS_FILEPATH: &str = "./pt_oc.json"; +const OC_LIMITS_FILEPATH: &str = "pt_oc.json"; #[derive(Serialize, Deserialize, Debug)] pub(super) struct OverclockLimits { @@ -23,7 +23,7 @@ impl Default for OverclockLimits { impl OverclockLimits { /// (Self, is_default) pub fn load_or_default() -> (Self, bool) { - let path = std::path::Path::new(OC_LIMITS_FILEPATH); + let path = oc_limits_filepath(); if path.exists() { log::info!("Steam Deck limits file {} found", path.display()); let mut file = match std::fs::File::open(&path) { @@ -86,7 +86,7 @@ impl Default for CpuLimits { fn default() -> Self { Self { clock_min: MinMax { min: 1400, max: 3500 }, - clock_max: MinMax { min: 500, max: 3500 } + clock_max: MinMax { min: 400, max: 3500 } } } } @@ -109,3 +109,7 @@ impl Default for GpuLimits { } } } + +fn oc_limits_filepath() -> std::path::PathBuf { + crate::utility::settings_dir().join(OC_LIMITS_FILEPATH) +} diff --git a/package.json b/package.json index acca2f6..4988edf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.1.0", + "version": "1.1.0-beta4", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", diff --git a/pt_oc.json b/pt_oc.json new file mode 100644 index 0000000..410b8fd --- /dev/null +++ b/pt_oc.json @@ -0,0 +1,47 @@ +{ + "battery": { + "charge_rate": {"min": 250, "max": 2500} + }, + "cpus": { + "cpus": [ + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + }, + { + "clock_min": {"min": 1400, "max": 3500}, + "clock_max": {"min": 500, "max": 3500} + } + ] + }, + "gpu": { + "fast_ppt": {"min": 1000000, "max": 30000000}, + "slow_ppt": {"min": 1000000, "max": 29000000}, + "clock_min": {"min": 200, "max": 1600}, + "clock_max": {"min": 200, "max": 1600} + } +} diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx index 586200c..fcc73dc 100644 --- a/src/components/cpus.tsx +++ b/src/components/cpus.tsx @@ -173,7 +173,7 @@ export class Cpus extends Component<{}, CpuState> { backend.log(backend.LogLevel.Debug, "Min freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_CPU); const maxNow = get_value(CLOCK_MAX_CPU); - if (freq != freqNow && ((maxNow != null && freq > maxNow) || maxNow == null)) { + if (freq != freqNow && ((maxNow != null && freq <= maxNow) || maxNow == null)) { set_value(CLOCK_MIN_CPU, freq); for (let i = 0; i < total_cpus; i++) { backend.resolve(backend.setCpuClockLimits(i, freq, get_value(CLOCK_MAX_CPU)), @@ -204,7 +204,7 @@ export class Cpus extends Component<{}, CpuState> { backend.log(backend.LogLevel.Debug, "Max freq slider is now " + freq.toString()); const freqNow = get_value(CLOCK_MAX_CPU); const minNow = get_value(CLOCK_MIN_CPU); - if (freq != freqNow && ((minNow != null && freq > minNow) || minNow == null)) { + if (freq != freqNow && ((minNow != null && freq >= minNow) || minNow == null)) { set_value(CLOCK_MAX_CPU, freq); for (let i = 0; i < total_cpus; i++) { backend.resolve(backend.setCpuClockLimits(i, get_value(CLOCK_MIN_CPU), freq), @@ -303,7 +303,7 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Min freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.min && ((freqNow.max != null && freqNow.max > freq) || freqNow.max == null)) { + if (freq != freqNow.min && ((freqNow.max != null && freq <= freqNow.max) || freqNow.max == null)) { backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freq, freqNow.max!), (limits: number[]) => { const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; @@ -328,7 +328,7 @@ export class Cpus extends Component<{}, CpuState> { onChange={(freq: number) => { backend.log(backend.LogLevel.Debug, "Max freq slider for " + advancedCpu.toString() + " is now " + freq.toString()); const freqNow = get_value(CLOCK_MIN_MAX_CPU)[advancedCpuIndex] as MinMax; - if (freq != freqNow.max && ((freqNow.min != null && freq > freqNow.min) || freqNow.min == null)) { + if (freq != freqNow.max && ((freqNow.min != null && freq >= freqNow.min) || freqNow.min == null)) { backend.resolve(backend.setCpuClockLimits(advancedCpuIndex, freqNow.min!, freq), (limits: number[]) => { const clocks = get_value(CLOCK_MIN_MAX_CPU) as MinMax[]; diff --git a/src/components/gpu.tsx b/src/components/gpu.tsx index e101aeb..7e432c7 100644 --- a/src/components/gpu.tsx +++ b/src/components/gpu.tsx @@ -145,7 +145,7 @@ export class Gpu extends Component<{}> { backend.log(backend.LogLevel.Debug, "GPU Clock Min is now " + val.toString()); const valNow = get_value(CLOCK_MIN_GPU); const maxNow = get_value(CLOCK_MAX_GPU); - if (val != valNow && ((maxNow != null && val < maxNow) || maxNow == null)) { + if (val != valNow && ((maxNow != null && val <= maxNow) || maxNow == null)) { backend.resolve(backend.setGpuClockLimits(val, get_value(CLOCK_MAX_GPU)), (limits: number[]) => { set_value(CLOCK_MIN_GPU, limits[0]); @@ -169,7 +169,7 @@ export class Gpu extends Component<{}> { backend.log(backend.LogLevel.Debug, "GPU Clock Max is now " + val.toString()); const valNow = get_value(CLOCK_MAX_GPU); const minNow = get_value(CLOCK_MIN_GPU); - if (val != valNow && ((minNow != null && val > minNow) || minNow == null)) { + if (val != valNow && ((minNow != null && val >= minNow) || minNow == null)) { backend.resolve(backend.setGpuClockLimits(get_value(CLOCK_MIN_GPU), val), (limits: number[]) => { set_value(CLOCK_MIN_GPU, limits[0]); diff --git a/translations/es-ES.mo b/translations/es-ES.mo new file mode 100644 index 0000000000000000000000000000000000000000..40ddd41615c4c8e89364cbc1524361c36b4d4bb2 GIT binary patch literal 2450 zcmZXUJB%Ae7{>?51DudRLV)lb2!uP7J>LZd9R>>LUWpXv%$*5Mgf!m$&Ns<=#+jM5 zbFP7oCV~QlA_XK0M3f>8NGT$@fsPJAK?Sr38Y(3I-+Jvhm(`7bH#?8-`QP6T?D$mR znZkGmoB+SLA3u0H4+!xfcnN$S?1Q_(&q4f&FY$8-{2JT?-U5$;KY+aNFK{RL zFZc-fAGizLw?l}-;2}_gWsuL;!Dqqq#d;rn2=h-sK7SR&72*cSe%%E3g15kj!5@qH z&&B-rg8zW{%bj8SJK+?c+Y9piFv$K$umn~>wzmXw9Opo``#$(0*aZ3fhajK30jP^IkFk0AzbtK+fM) zkn{BwxDWiMn12tl-P<7V{{v+I{w~&c!wI3a-MfSljAK+a1Iwq`8RIbwuETQ}+^1Z-qZsV_0gTCq^~5oAzBo6zq^e0*nV1q$O;g*GVUy%S{aw(J zN@TDyv9f2~MR8JvKyFK5RV-{O*TTlkIWj?>(QO_4=xxm=Bo?d*&Ze?CJSF4d38wy!4Q~*O)XZ99(e_N7+W4ZZQQN}SqSIY+V#%mxN?zI|iA>gRlB0yZ^y8Hd zxu|eCwq`@OGFZ~qh-KwNz21;h?@fzk>td2?)tb}>fg#+eV|(Oen>`+`Zu57z;#8aR z94tG!l#z+IMj@{t87me(8tX(&U6xaeQBttRZO&*T+%+KG*yOd z=0%>ov+%u3;w4anzMQSY8rKb?IX?am6=d};0hp2N@^;C`B ztUJ4*Qxfa7hFDi!lAYlTsZ4@ApwK! z9T^ym0mc&PJz`=o~v_O+|L+X68z3)Uhr^HQ&-nbTVuCs9`H|GlY(>l*=t0 zHnZkTY}@6tD@JF&oX60xHuYugeMY`iUyatNtNG4o5q(sV$7hef7R}B@bMtcUjmnAR z(d>!Y+0q%5JZd;)e5!(V6^S>dm8lj*4N~oic}0?smexzP)3v2L?#|83mbiV9$*8f_ zft`TNlsl=?=FPm3k@L5+uo2DQ*~jKK(1c4Swh8J{k@HO*N}>vN^;KfIJP-*<^pB)e z`mBi>#N;6`lBvo?w~?6`(GhEn+~B&(#g?m!cv}qBDQ*#4{5w+FXsx&lO`IQ>ZH*wD z@`y7Gu1Rz*nMA{z1&c1i8bNs-Xa&v7iqi@=pdC$;uNBwBeJ4(-rcQOp9raSTJIay2 z^A-_|g%|6=O(Rk6i75ScCH9rerKnhaR;o>Sl;?sBxfaI`LGq@2Igfl>bYgj|%QJ)P zoLtX4HXOyQQLV&Ko%mdsJcPUTIk*Oa+L1m-vs|Bp>k#O8Dc9%V8uXc`UgYYuq6&}I zJ^HMgEQQnerXxYo3(ZbQmBgg$W8Lx&2sYR2N~TBYG&;WMif2p<`9m|VC^&Fkat^x}V&hgVqu literal 0 HcmV?d00001 diff --git a/translations/es-ES.po b/translations/es-ES.po index 937fffe..aef82f0 100644 --- a/translations/es-ES.po +++ b/translations/es-ES.po @@ -9,10 +9,10 @@ msgstr "" "Project-Id-Version: v1.1\n" "Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" "POT-Creation-Date: 2023-01-09 19:52-0500\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" +"PO-Revision-Date: 2023-01-18 19:52-0500\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es-ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/translations/zh_CN.mo b/translations/zh-CN.mo similarity index 100% rename from translations/zh_CN.mo rename to translations/zh-CN.mo diff --git a/translations/zh_CN.po b/translations/zh-CN.po similarity index 100% rename from translations/zh_CN.po rename to translations/zh-CN.po diff --git a/translations/zh-HK.mo b/translations/zh-HK.mo new file mode 100644 index 0000000000000000000000000000000000000000..396104d172e7f08680d64ff16aaf276ff9f34557 GIT binary patch literal 2306 zcmZ9MTWl0n7{`wSUKT+_QB;)U4Ywx4QoID$@K7jMS=hiLFBmhsd%7K%owLlPg+8^3 zOAC~OLJ?}EAO#k&AQ;UGu(%Try zJ3=`RQv5FP6>vXDey)LZp6@}j`w67Dw?Ojmf#mmgxIY6$B|q~((q9y^2_*eDLU|=f z{x^o}8Ib(!3gvE)>emaBpOYY+^E~)8SOzJtAH)4$L5lkuNd5i`MEUCXlJsei|GAhP zlWb|cfcXd}-Ax)WV=rS;uW3-PC_d$iR@8e#dC^^=zR`F*Kt1jg`1`p~Zp4caUc!6~ z^HI!aF`vSG7;_0GJpT)Ac9SlI>89jL5PUU6-BQZWnxYayw`WHOpI{?W&oBqGOuEu=yq}ui4i0YC>iOTP+RSlsZobRy-3}n5r#! zXS*=C+Nth_THt}TinNnst+La|=rXgLCq!N%R;#IX2$QWb)U+-vF0)z1aPnzkiY#Sm z-PtJ!QwdYfNTW^5If$f5gRNC9JDE)J=#D0~R+<^Xx3(m>X5e5ru2PVl!sL0%IN1GP zzQK;E=0&{*YfZ7o5k_X;^pV%080#c*G^EKA>Rujg6_%DWnn=*{PM${->$@7Hdz}5Yl1w+HFSa9fEB}JEB3Qo7fgZ*9^h7Ae5kao%p*1uGtlmLsf4a*MK6bZF#L zX~i{)^X1Eyzp5;2R+^Xd$R_kzNtvo)>8dTwIIS2tN6iT(CDeR_9Oqr_@2!73lGu<~ zb2rK6rOP68XHh>TwXXp0HtG>8=&EMCRlmKc^h(EWQ&!y7qi}7wd25V}%%Tf%z9OyJ z5$1Pa_lE|UTkNS_DdV2H6Xz>8hN}}p)zTs6e>~}3J5zr~Zm|f77QX87PaSpp#$iKC zUg@kmb%c2X7qJ!?gd2l>)q!4C9UONL9A^HhQNRBxaJX_~pjJBR?H~6qANS8pl8%3= z=pGtGMDpYgj#Q7A+|eO-WTJMqzdG?DJ>wvwT4~I^GW4I9;!aH<@LiAH*WDtHFyI~> zfopHPuh#uhm}8*&pB#haTap{NcY55rh$GiC3QtH+rh4g;d+r$XhP&O-i?H>3kMJn+ zsFnJf!qxEM1S&jA?}q;V0*dt))lPCP1vVW$?rgIs+h+4-QVzp!mRz`;p&Ym-ihAIB${-z z-y1vMSWQ;B`H4GrGSI4&FVuQJL-A`<2T(VLB)wz3^bd;#QNj*2KA@l#-e8&i3lJKy AfdBvi literal 0 HcmV?d00001 diff --git a/translations/zh_HK.po b/translations/zh-HK.po similarity index 100% rename from translations/zh_HK.po rename to translations/zh-HK.po From ea89de01d7de5ef32d30015970e208bc6c39f9b8 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Wed, 18 Jan 2023 21:05:04 -0500 Subject: [PATCH 36/44] Fix incorrect CPU defaults loaded by defaults button --- backend/src/api/cpu.rs | 21 +++++++++++++++++++++ backend/src/api/handler.rs | 6 +++++- backend/src/main.rs | 4 ++++ backend/src/settings/steam_deck/cpu.rs | 15 +++++++++++++-- src/backend.ts | 4 ++++ src/components/cpus.tsx | 22 +++++++--------------- src/index.tsx | 3 +++ translations/fr-FR.mo | 1 + 8 files changed, 58 insertions(+), 18 deletions(-) create mode 120000 translations/fr-FR.mo diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index 1c4d35f..e1f8aa6 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -122,6 +122,27 @@ pub fn set_smt( } } +pub fn get_smt( + sender: Sender, +) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = move |value: bool| tx.send(value).expect("get_smt callback send failed"); + sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetSmt(Box::new(callback)))).expect("get_smt send failed"); + rx.recv().expect("get_smt callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| { + vec![result.into()] + } + } +} + pub fn get_cpus_online( sender: Sender, ) -> impl AsyncCallable { diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 48a4962..f339ff8 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -57,6 +57,7 @@ pub enum CpuMessage { SetCpuOnline(usize, bool), SetCpusOnline(Vec), SetSmt(bool, Callback>), + GetSmt(Callback), GetCpusOnline(Callback>), SetClockLimits(usize, Option>), GetClockLimits(usize, Callback>>), @@ -113,7 +114,10 @@ impl CpuMessage { result.push(*settings.cpus()[i].online()); } cb(result); - } + }, + Self::GetSmt(cb) => { + cb(*settings.smt()); + }, Self::GetCpusOnline(cb) => { let mut result = Vec::with_capacity(settings.len()); for cpu in settings.cpus() { diff --git a/backend/src/main.rs b/backend/src/main.rs index 43e9696..0603a24 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -125,6 +125,10 @@ fn main() -> Result<(), ()> { "CPU_set_smt", api::cpu::set_smt(api_sender.clone()) ) + .register_async( + "CPU_get_smt", + api::cpu::get_smt(api_sender.clone()) + ) .register( "CPU_set_clock_limits", api::cpu::set_clock_limits(api_sender.clone()) diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 539a5f4..038558b 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -91,7 +91,7 @@ impl Cpus { if let Some(max_cpu) = Self::cpu_count() { let mut sys_cpus = Vec::with_capacity(max_cpu); for i in 0..max_cpu { - sys_cpus.push(Cpu::from_sys(i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); + sys_cpus.push(Cpu::system_default(i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); } let (_, can_smt) = Self::system_smt_capabilities(); Self { @@ -325,7 +325,7 @@ impl Cpu { } } - fn from_sys(cpu_index: usize, oc_limits: CpuLimits) -> Self { + /*fn from_sys(cpu_index: usize, oc_limits: CpuLimits) -> Self { Self { online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, clock_limits: None, @@ -335,6 +335,17 @@ impl Cpu { index: cpu_index, state: crate::state::steam_deck::Cpu::default(), } + }*/ + + fn system_default(cpu_index: usize, oc_limits: CpuLimits) -> Self { + Self { + online: true, + clock_limits: None, + governor: "schedutil".to_owned(), + limits: oc_limits, + index: cpu_index, + state: crate::state::steam_deck::Cpu::default(), + } } fn limits(&self) -> crate::api::CpuLimits { diff --git a/src/backend.ts b/src/backend.ts index 26d88f4..f3dfbd5 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -132,6 +132,10 @@ export async function setCpuSmt(status: boolean): Promise { return await call_backend("CPU_set_smt", [status]); } +export async function getCpuSmt(): Promise { + return await call_backend("CPU_get_smt", []); +} + /*export async function getCpuCount(): Promise { return (await call_backend("CPU_count", []))[0]; }*/ diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx index fcc73dc..9089dac 100644 --- a/src/components/cpus.tsx +++ b/src/components/cpus.tsx @@ -25,33 +25,28 @@ import { set_value, get_value } from "usdpl-front"; interface CpuState { reloadThingy: string; - advancedCpu: number; - advancedMode: boolean; } +let advancedMode = false; +let advancedCpu = 1; + export class Cpus extends Component<{}, CpuState> { constructor(props: {}) { super(props); this.state = { reloadThingy: "/shrug", - advancedCpu: 1, - advancedMode: false, }; } render() { - const reloadGUI = (x: string) => this.setState((state) => { + const reloadGUI = (x: string) => this.setState((_state) => { return { reloadThingy: x, - advancedCpu: state.advancedCpu, - advancedMode: state.advancedMode, }; }); const total_cpus = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.count ?? 8; - const advancedCpuIndex = this.state.advancedCpu - 1; - const advancedCpu = this.state.advancedCpu; - const advancedMode = this.state.advancedMode; + const advancedCpuIndex = advancedCpu - 1; const smtAllowed = (get_value(LIMITS_INFO) as backend.SettingsLimits | null)?.cpu.smt_capable ?? true; const governorOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.map((elem) => {return { @@ -70,12 +65,10 @@ export class Cpus extends Component<{}, CpuState> { label={tr("Advanced")} description={tr("Enables per-thread configuration")} onChange={(advanced: boolean) => { - //advancedMode = advanced; + advancedMode = advanced; this.setState((state) => { return { reloadThingy: state.reloadThingy, - advancedCpu: state.advancedCpu, - advancedMode: advanced, }; }); }} @@ -232,11 +225,10 @@ export class Cpus extends Component<{}, CpuState> { min={1} showValue={true} onChange={(cpuNum: number) => { + advancedCpu = cpuNum; this.setState((state) => { return { reloadThingy: state.reloadThingy, - advancedCpu: cpuNum, - advancedMode: state.advancedMode, }; }); }} diff --git a/src/index.tsx b/src/index.tsx index 4ad0757..56cf799 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -117,6 +117,9 @@ const reload = function() { set_value(ONLINE_CPUS, count); set_value(SMT_CPU, statii.length > 3 && statii[0] == statii[1] && statii[2] == statii[3]); }); + backend.resolve(backend.getCpuSmt(), (smt: boolean) => { + set_value(SMT_CPU, smt); + }); backend.resolve(backend.getCpuClockLimits(0), (limits: number[]) => { set_value(CLOCK_MIN_CPU, limits[0]); set_value(CLOCK_MAX_CPU, limits[1]); diff --git a/translations/fr-FR.mo b/translations/fr-FR.mo new file mode 120000 index 0000000..303685b --- /dev/null +++ b/translations/fr-FR.mo @@ -0,0 +1 @@ +fr-CA.mo \ No newline at end of file From ce5b0ed92611512192e94b835d98d256a21c5802 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 21 Jan 2023 18:15:26 -0500 Subject: [PATCH 37/44] Update USDPL and fix other front-back communication inconsistencies --- backend/Cargo.lock | 4 ++-- backend/Cargo.toml | 2 +- backend/build.sh | 8 ++++---- package.json | 2 +- pnpm-lock.yaml | 28 ++++++++++++++-------------- src/backend.ts | 16 ++++++++++++---- src/index.tsx | 4 ++-- src/usdpl_front/package.json | 2 +- src/usdpl_front/usdpl_front.js | 4 ++-- src/usdpl_front/usdpl_front_bg.wasm | Bin 92157 -> 92304 bytes 10 files changed, 39 insertions(+), 31 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 4576e9a..dac5d74 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1375,9 +1375,9 @@ dependencies = [ [[package]] name = "usdpl-back" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32af4c47bfeca1d75de693be983edc2ecfee10e71f138933c959ea5f97ca1a64" +checksum = "e2938cb40ba84ebea44658ebb1e4e0045fca54a562873bacab2ae094abab61ff" dependencies = [ "async-recursion", "async-trait", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index d154972..edd666a 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -12,7 +12,7 @@ readme = "../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -usdpl-back = { version = "0.9.0", features = ["blocking"] }#, path = "../../usdpl-rs/usdpl-back"} +usdpl-back = { version = "0.9.1", features = ["blocking"] }#, path = "../../usdpl-rs/usdpl-back"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/backend/build.sh b/backend/build.sh index 94cd216..f2fab87 100755 --- a/backend/build.sh +++ b/backend/build.sh @@ -1,10 +1,10 @@ #!/bin/bash -#cargo build --release --target x86_64-unknown-linux-musl -cargo build --target x86_64-unknown-linux-musl +cargo build --release --target x86_64-unknown-linux-musl +#cargo build --target x86_64-unknown-linux-musl #cross build --release mkdir -p ../bin -#cp ./target/x86_64-unknown-linux-musl/release/powertools-rs ../bin/backend -cp ./target/x86_64-unknown-linux-musl/debug/powertools-rs ../bin/backend +cp ./target/x86_64-unknown-linux-musl/release/powertools-rs ../bin/backend +#cp ./target/x86_64-unknown-linux-musl/debug/powertools-rs ../bin/backend #cp ./target/release/powertools-rs ../bin/backend diff --git a/package.json b/package.json index 4988edf..847547a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "typescript": "^4.9.4" }, "dependencies": { - "decky-frontend-lib": "~3.18.5", + "decky-frontend-lib": "~3.18.10", "react-icons": "^4.7.1", "usdpl-front": "file:src/usdpl_front" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e88971e..0e748bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ specifiers: '@rollup/plugin-typescript': ^8.5.0 '@types/react': 16.14.0 '@types/webpack': ^5.28.0 - decky-frontend-lib: ~3.18.5 + decky-frontend-lib: ~3.18.10 react-icons: ^4.7.1 rollup: ^2.79.1 rollup-plugin-import-assets: ^1.1.1 @@ -18,7 +18,7 @@ specifiers: usdpl-front: file:src/usdpl_front dependencies: - decky-frontend-lib: 3.18.5 + decky-frontend-lib: 3.18.10 react-icons: 4.7.1 usdpl-front: file:src/usdpl_front @@ -380,7 +380,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001442 + caniuse-lite: 1.0.30001446 electron-to-chromium: 1.4.284 node-releases: 2.0.8 update-browserslist-db: 1.0.10_browserslist@4.21.4 @@ -395,8 +395,8 @@ packages: engines: {node: '>=6'} dev: true - /caniuse-lite/1.0.30001442: - resolution: {integrity: sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==} + /caniuse-lite/1.0.30001446: + resolution: {integrity: sha512-fEoga4PrImGcwUUGEol/PoFCSBnSkA9drgdkxXkJLsUBOnJ8rs3zDv6ApqYXGQFOyMPsjh79naWhF4DAxbF8rw==} dev: true /chrome-trace-event/1.0.3: @@ -420,8 +420,8 @@ packages: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true - /decky-frontend-lib/3.18.5: - resolution: {integrity: sha512-CTIJs61La17spws5IzAbLbZ/Bqe+gYgnO6xOrolK1QZh7ZbZeoQ67dtnI0zqRMMC10J8H7jPdqmQnwGN10/bzw==} + /decky-frontend-lib/3.18.10: + resolution: {integrity: sha512-2mgbA3sSkuwQR/FnmhXVrcW6LyTS95IuL6muJAmQCruhBvXapDtjk1TcgxqMZxFZwGD1IPnemPYxHZll6IgnZw==} dev: false /deepmerge/4.2.2: @@ -672,8 +672,8 @@ packages: engines: {node: '>=8.6'} dev: true - /punycode/2.2.0: - resolution: {integrity: sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==} + /punycode/2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} dev: true @@ -742,8 +742,8 @@ packages: ajv-keywords: 3.5.2_ajv@6.12.6 dev: true - /serialize-javascript/6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + /serialize-javascript/6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} dependencies: randombytes: 2.1.0 dev: true @@ -820,7 +820,7 @@ packages: '@jridgewell/trace-mapping': 0.3.17 jest-worker: 27.5.1 schema-utils: 3.1.1 - serialize-javascript: 6.0.0 + serialize-javascript: 6.0.1 terser: 5.16.1 webpack: 5.75.0 dev: true @@ -860,7 +860,7 @@ packages: /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.2.0 + punycode: 2.3.0 dev: true /url-join/4.0.1: @@ -927,5 +927,5 @@ packages: file:src/usdpl_front: resolution: {directory: src/usdpl_front, type: directory} name: usdpl-front - version: 0.9.0 + version: 0.9.1 dev: false diff --git a/src/backend.ts b/src/backend.ts index f3dfbd5..5bbe0d1 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -11,12 +11,20 @@ export function resolve(promise: Promise, setter: (t: T) => void) { console.debug("Got resolved", data); setter(data); } else { - console.warn("Resolve failed:", data); - log(LogLevel.Warn, ""); + console.warn("Resolve failed:", data, promise); + log(LogLevel.Warn, "A resolve failed"); } })(); } +export function resolve_nullable(promise: Promise, setter: (t: T | null) => void) { + (async function () { + let data = await promise; + console.debug("Got resolved", data); + setter(data); + })(); +} + export async function initBackend() { // init usdpl await init_embedded(); @@ -102,7 +110,7 @@ export async function getBatteryChargeDesign(): Promise { return (await call_backend("BATTERY_charge_design", []))[0]; } -export async function getBatteryChargeRate(): Promise { +export async function getBatteryChargeRate(): Promise { return (await call_backend("BATTERY_get_charge_rate", []))[0]; } @@ -114,7 +122,7 @@ export async function unsetBatteryChargeRate(): Promise { return await call_backend("BATTERY_unset_charge_rate", []); } -export async function getBatteryChargeMode(): Promise { +export async function getBatteryChargeMode(): Promise { return (await call_backend("BATTERY_get_charge_mode", []))[0]; } diff --git a/src/index.tsx b/src/index.tsx index 56cf799..04cd538 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -104,8 +104,8 @@ const reload = function() { }); backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) }); - backend.resolve(backend.getBatteryChargeRate(), (rate: number) => { set_value(CHARGE_RATE_BATT, rate) }); - backend.resolve(backend.getBatteryChargeMode(), (mode: string) => { set_value(CHARGE_MODE_BATT, mode) }); + backend.resolve_nullable(backend.getBatteryChargeRate(), (rate: number | null) => { set_value(CHARGE_RATE_BATT, rate) }); + backend.resolve_nullable(backend.getBatteryChargeMode(), (mode: string | null) => { set_value(CHARGE_MODE_BATT, mode) }); backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) }); backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) }); backend.resolve(backend.getBatteryChargeDesign(), (rate: number) => { set_value(CHARGE_DESIGN_BATT, rate) }); diff --git a/src/usdpl_front/package.json b/src/usdpl_front/package.json index 1bfd686..1c18e11 100644 --- a/src/usdpl_front/package.json +++ b/src/usdpl_front/package.json @@ -4,7 +4,7 @@ "NGnius (Graham) " ], "description": "Universal Steam Deck Plugin Library front-end designed for WASM", - "version": "0.9.0", + "version": "0.9.1", "license": "GPL-3.0-only", "repository": { "type": "git", diff --git a/src/usdpl_front/usdpl_front.js b/src/usdpl_front/usdpl_front.js index 943d2e7..dc66687 100644 --- a/src/usdpl_front/usdpl_front.js +++ b/src/usdpl_front/usdpl_front.js @@ -523,7 +523,7 @@ function getImports() { throw new Error(getStringFromWasm0(arg0, arg1)); }; imports.wbg.__wbindgen_closure_wrapper385 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 71, __wbg_adapter_26); + const ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_26); return addHeapObject(ret); }; @@ -582,7 +582,7 @@ export default init; // USDPL customization -const encoded = "AGFzbQEAAAABtwEbYAJ/fwBgAn9/AX9gAX8AYAN/f38AYAR/f39/AGADf39/AX9gAX8Bf2AAAGAAAX9gBX9/f39/AGAEf39/fwF/YAV/f39/fwF/YAF/AX5gA39/fwF+YAR/fn9/AGAGf39/f39/AX9gBn9/f39/fwBgBX9/fn9/AGAFf399f38AYAV/f3x/fwBgBH99f38AYAR/fH9/AGACfn8AYAd/f39/f39/AX9gA35/fwF/YAF8AX9gAn9/AX4CqgkjA3diZxpfX3diaW5kZ2VuX29iamVjdF9kcm9wX3JlZgACA3diZxVfX3diaW5kZ2VuX3N0cmluZ19uZXcAAQN3YmcVX193YmluZGdlbl9zdHJpbmdfZ2V0AAADd2JnG19fd2JpbmRnZW5fb2JqZWN0X2Nsb25lX3JlZgAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9uZXcAGQN3YmcWX193YmluZGdlbl9ib29sZWFuX2dldAAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9nZXQAAAN3YmcSX193YmluZGdlbl9pc19udWxsAAYDd2JnF19fd2JpbmRnZW5faXNfdW5kZWZpbmVkAAYDd2JnKF9fd2JnX2luc3RhbmNlb2ZfV2luZG93X2FjYzk3ZmY5ZjVkMmM3YjQABgN3YmccX193YmdfZmV0Y2hfMGZlMDQ5MDVjY2NmYzJhYQABA3diZypfX3diZ19pbnN0YW5jZW9mX1Jlc3BvbnNlX2VhYTQyNjIyMDg0OGEzOWUABgN3YmcbX193YmdfdGV4dF8xMTY5ZDc1MmNjNjk3OTAzAAYDd2JnKF9fd2JnX25ld3dpdGhzdHJhbmRpbml0XzA1ZDcxODA3ODg0MjBjNDAABQN3YmcSX193YmluZGdlbl9jYl9kcm9wAAYDd2JnIF9fd2JnX25ld25vYXJnc19iNWIwNjNmYzZjMmYwMzc2AAEDd2JnG19fd2JnX2NhbGxfOTdhZTlkODY0NWRjMzg4YgABA3diZxpfX3diZ19uZXdfMGI5YmZkZDk3NTgzMjg0ZQAIA3diZxRfX3diaW5kZ2VuX2lzX3N0cmluZwAGA3diZxtfX3diZ19zZWxmXzZkNDc5NTA2ZjcyYzZhNzEACAN3YmcdX193Ymdfd2luZG93X2YyNTU3Y2M3ODQ5MGFjZWIA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QZiHwAAQwwEACyAHQQhqIARqIAUgBmotAAA6AAAgACAIaiEACwJAIA9FIAsgAklyDQAgAEGBCEkEQCACIAdBCGogAGpBgAggAGsQ4QEgAGohAAwBCyAAQYAIQZCFwAAQhgMACyAAQYEITw0CIAshBCADIAdBCGogABDfAUUNAQsLIAdBoAhqJAAgEA8LIABBgAhBoIXAABCHAwALQeCDwABBKyAHQZgIakGMhMAAQciHwAAQtAEAC80NAgd/AX4jAEHgAmsiAiQAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAALQCYBEEBaw4DCQIBAAsgACAAQYgCakGIAhChAxoLAkACQAJAAkAgAC0AgAJBAWsOAw0EAAELIABB7AFqIQYgAC0A7AFBAWsOAwcDAgELIAAoAvABIQMgAiAAQfQBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEgaiACQThqELICIAJBKGogAigCICACKAIkEOUCIAAoAvgBIQMgAiAAQfwBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEYaiACQThqELECIAIoAhghBSACKAIcIQQgAkGUAmogAkEwaigCADYCACACIAIpAyg3AowCIAAgAkE4akHgARChAyIDIAQ2AugBIAMgBTYC5AEgAyAENgLgASADQQA6AOwBIANB7AFqIQYLIAAgACkC1AE3ArABIAAgACkC4AE3ArwBIABBuAFqIABB3AFqKAIANgIAIABBxAFqIgMgAEHoAWooAgAiBDYCAEHo6cAAQejpwAApAwAiCUIBfDcDACACQRBqIAQQngEgAigCECEEIABB0AFqQQA2AgAgAEHMAWogAigCFDYCACAAIAQ2AsgBIAMoAgAhBSAAKAK8ASEEIAIgAEHAAWooAgAiAzYCpAIgAiADIAVBAnRqNgKgAiACIAM2ApwCIAIgBDYCmAIgAEHIAWohBCAFBEADQCACIANBBGo2ApwCIAJBOGogAygCABBCIAAoAtABIgMgACgCyAFGBEAgBCADEPwBIAAoAtABIQMLIAAoAswBIANBBHRqIgMgAikDODcDACADQQhqIAJBQGspAwA3AwAgACAAKALQAUEBajYC0AEgAigCnAIiAyACKAKgAkcNAAsLIAJBmAJqEMcBQfDpwAAvAQAhAyACQThqIABBsAFqENEBIABBmAFqIAJBQGsoAgA2AgAgACACKQM4NwOQASAAIAQpAgA3ApwBIABBpAFqIARBCGooAgA2AgAgAEEAOgCqASAAIAM7AagBIAAgCTcDiAEgAEEANgKAASAAIAk3AwAgAEGqAWohBAwDCyAAQaoBaiEEIAAtAKoBQQFrDgMIAAMBCwALIAAvAagBIQMgACkDACEJCyACQUBrIABBgAFqQSgQoQMaIABBEGogAkE4akEwEKEDGiAAQegAakEAOgAAIABB5ABqIAM7AQAgACAJNwMICyACQThqIABBCGoiBSABECcgAigCOCIBQQtGDQIgAkHIAmogAkHIAGopAwA3AwAgAkHQAmoiAyACQdAAaikDADcDACACQdgCaiIGIAJB2ABqKQMANwMAIAIgAikDQDcDwAIgAigCPCEEIAUQrgEgAUEKRwRAIAJBuAJqIAYpAwA3AwAgAkGwAmogAykDADcDACACQagCaiACQcgCaikDADcDACACIAIpA8ACNwOgAiACIAQ2ApwCIAIgATYCmAIgAUEBRg0CQbSZwABBMhABIQQgAkGYAmoQuQELIABBAToAqgEgABDHAgwHC0GwjsAAQSNBzJrAABD3AQALIAJBsAJqKAIAIQEgAkGsAmooAgAhAyACQagCaigCACEEIABBAToAqgEgABDHAiADRQ0FIAIgARAXNgLAAiACIAM2AqQCIAIgAyABQQR0IgVqNgKgAiACIAM2ApwCIAIgBDYCmAIgAUUNBEEAIQQgAkE4akEBciIGQQdqIQcDQCACIANBEGoiATYCnAIgAy0AACIIQQpGDQUgBiADKQABNwAAIAcgA0EIaikAADcAACACIAg6ADggAkE4ahBeIQMgAkHAAmooAgAgBCADEBggBEEBaiEEIAEhAyAFQXBqIgUNAAsMBAsgBkEDOgAAIARBAzoAAEEBDAYLQbCOwABBI0GcjsAAEPcBAAtBsI7AAEEjQaSZwAAQ9wEAC0GwjsAAQSNB3JrAABD3AQALIAJBmAJqELIBIAIoAsACIQUMAQtBISEFIARBJEkNACAEEAALIABBsAFqEJoCIABBAToA7AFBAAsiAQRAQQMhBCAAQQM6AIACDAELIAAQlgIgAEEBOgCAAiACIAU2AiggAkEgNgI4IAJBCGogAEGQBGoiAyACQThqIAJBKGoQhAIgAigCCEUEQCACKAIMIgRBI0sEQCAEEAALIAIoAjgiBEEkTwRAIAQQAAsgAigCKCIEQSRPBEAgBBAACyADKAIAIgNBJE8EQCADEAALQQEhBCAAKAKUBCIDQSRJDQEgAxAADAELQbiAwABBFRCWAwALIAAgBDoAmAQgAkHgAmokACABQQBHC5IMAQV/IwBBkAJrIgMkACABAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCABLQBgQQFrDgQHAAIDAQsACyABIAEpAwA3AwggA0HIAGogAUEQakEoEKEDGiABIAEvAVw7AV4gARARNgI4IAFBOGoiBBC/ASAEEMIBIANBpAFqQRc2AgAgA0GcAWpBGDYCACADIAFB3gBqNgKgASADQfyYwAA2ApgBIANBGTYClAEgAyABQQhqNgKQASADQQM2AswBIANBBDYCxAEgA0HQmMAANgLAASADQQA2ArgBIAMgA0GQAWo2AsgBIANBgAFqIANBuAFqEEEgAUHEAGogA0GIAWooAgA2AgAgASADKQOAATcCPCADQbgBaiADQcgAakEoEKEDGiADQZABaiADQbgBahCBASADKAKQASEFIAMoApQBIgZFDQsgAUHQAGogAygCmAEiBzYCACABQcwAaiAGNgIAIAEgBTYCSCADQZABaiAGIAcQNyADQcABaiIFIANBmAFqKQMANwMAIAMgAykDkAE3A7gBIANB8ABqIANBuAFqELwBIAUgA0H4AGooAgA2AgAgAyADKQNwNwO4ASADIANBuAFqEI0CNgKQASAEIANBkAFqELABIAMoApABIgVBJE8EQCAFEAALIANBQGsgAUFAaygCACABQcQAaigCACAEEPMBIAMoAkQhBSADKAJADQogASAFNgJUIANBOGoQ7QEgAygCOEUNBiABIAMoAjw2AlggASABQdgAaigCACABQdQAaigCABAKEEg2AmgLIANBMGogAUHoAGoiBCACEI0BIAMoAjAiBkECRg0GIAMoAjQhBSAEEK8BIAYNCCADQShqIAUQ8QEgAygCLCEFIAMoAigNCCABIAU2AmggA0EgaiAEEPYBIAMoAiAhBCABQfQAaiADKAIkIgU2AgAgASAENgJwIAQNASABIAUQSDYCbAsgA0EYaiABQewAaiIEIAIQjQEgAygCGCICQQJGDQEgAygCHCEFIAQQrwEgAg0AIANBEGogBRDyASADKAIUIQQgAygCEEUNAiAEIQULIAEoAmgiAkEkSQ0GIAIQAAwGCyAAQQs2AgBBBAwKCyADQQhqIAQQAiADKAIIIgVFBEAgA0EANgK8AQwECyADKAIMIQIgAyAFNgK8ASADIAI2AsABIAMgAjYCuAEgAyADQbgBahCyAiADQbgBaiADKAIAIAMoAgQQ5QIgAygCvAFFDQMgA0GIAWogA0HAAWoiBigCACICNgIAIAMgAykDuAE3A4ABIANBuAFqIAMoAoQBIAIQmwEgAygCuAEiAkEKRwRAIAMoArwBIQUgA0GQAWogBkEoEKEDGiADQfABaiADQZgBaikDADcDACADQfgBaiADQaABaikDADcDACADQYACaiADQagBaikDADcDACADIAMpA5ABNwPoASADQYABahCaAiAEQSRPBEAgBBAACyABKAJoIgRBJE8EQCAEEAALIAEoAlgiBEEkTwRAIAQQAAsgASgCVCIEQSRPBEAgBBAACyABQcgAahCaAiABQTxqEJoCIAEoAjgiAUEkSQ0JIAEQAAwJCyADIAMpArwBNwOIAiADQYgCahCpASEFIANBgAFqEJoCIARBJE8EQCAEEAALIAEoAmgiAkEkTwRAIAIQAAsgASgCWCICQSRPBEAgAhAACyABKAJUIgJBJE8EQCACEAALIAFByABqEJoCIAFBPGoQmgIgASgCOCIBQSRJDQcgARAADAcLQbCOwABBI0GgmMAAEPcBAAtB6JHAAEErQYSZwAAQ9wEACyAAQQs2AgBBAwwGC0HokcAAQStBlJnAABD3AQALIAEoAlgiAkEkTwRAIAIQAAsgASgCVCICQSRJDQAgAhAACyABQcgAahCaAgsgAUE8ahCaAiABKAI4IgFBJEkNACABEAALQQohAgsgACAFNgIEIAAgAjYCACAAIAMpA+gBNwMIIABBEGogA0HwAWopAwA3AwAgAEEYaiADQfgBaikDADcDACAAQSBqIANBgAJqKQMANwMAQQELOgBgIANBkAJqJAAL4gsCCn8CfiMAQeACayICJAACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAC0A2AJBAWsOAwcCAQALIAAgAEGoAWpBqAEQoQMaCwJAIAAtAKABQQFrDgMFAQACCyAAQQhqIQUgAEGYAWotAABBAWsOAwcAAwILAAsgACgCACEDIAIgACgCBCIENgJQIAIgAzYCTCACIAQ2AkggAkEwaiACQcgAahCyAiACQThqIAIoAjAgAigCNBDlAiACQdQBaiACQUBrKAIANgIAIAIgAikDODcCzAEgAEEIaiIFIAJByABqQZABEKEDGiAAQZgBakEAOgAACyAAQYgBaiAAQZQBaigCADYCACAAQYABaiIDIABBjAFqKQIANwIAQejpwABB6OnAACkDACIMQgF8NwMAIAJBhAJqIAMQ0QEgAEEYakEJNgIAIAAgDDcDCCAAQegAakEAOgAAIABBHGogAikChAI3AgAgAEEkaiACQYwCaigCADYCACAAQeQAakHw6cAALwEAOwEACyACQcgAaiAFIAEQJyACKAJIQQtGDQIgAkHYAWogAkHIAGpBKBChAxogBRCuAQJAAkAgAigC2AEiB0F4ag4DAQYABgsgAigC3AEhAUG06sAAKAIABEAQ4wILQbTqwABBADYCACABQSRJDQggARAADAgLIAJB4AFqKAIAIQEgAkHkAWooAgAhAyACKALcASEGIAJBIGoQ5wEgAikDICEMIAIpAyghDSACQcgAaiADEGsgAkGoAmoiCCACQdAAaiIJKQMANwMAIAIgAikDSDcDoAIgAiANNwOYAiACIAw3A5ACIAIgATYCVCACIAEgA0EYbCIEajYCUCACIAE2AkwgAiAGNgJIIANFDQUgAkHYAmohBgNAIAIgAUEYaiIDNgJMIAEoAgQiCkUNBiABKAIAIQsgAiABKAIINgLIAiACIAo2AsQCIAIgCzYCwAIgBiABQRRqKAIANgIAIAIgASkCDDcD0AIgAkGwAmogAkGQAmogAkHAAmogAkHQAmoQSyACKAK0AgRAIAJBsAJqEKYCIAJBsAJqEMoCCyADIQEgBEFoaiIEDQALDAULQbCOwABBI0H8msAAEPcBAAtBsI7AAEEjQZyOwAAQ9wEAC0EDIQQgAEEDOgCgASAAQQM6AJgBQQEhAQwFC0GwjsAAQSNB7JrAABD3AQALQbTqwAAoAgAEQBDjAgtBtOrAAEEANgIAQQEhAQwBCyACQcgAahC7ASACQeAAaiAIKQMANwMAIAJB2ABqIgMgAkGgAmopAwA3AwAgCSACQZgCaikDADcDACACIAIpA5ACNwNIQQAhAUG06sAAKAIABEAQ4wILQZjqwAAgAikDSDcDAEGw6sAAIAJB4ABqKQMANwMAQajqwAAgAykDADcDAEGg6sAAIAJB0ABqKQMANwMACwJAAkAgB0F4ag4DAQACAAsgAkHYAWoQuQEMAQsgAUUNACACQdgBakEEciIBEJsCIAEQygILIABBgAFqEJoCQQEhASAAQQE6AJgBIAUQrAIgAkEYakKAgICAgAQ3AwAgAigCHCEDIAIoAhghBSAAQQE6AKABQQMhBAJAAkACQAJAAkAgBQ4DAAEFAQsgAiADNgLYASACQSA2AkggAkEQaiAAQdACaiACQcgAaiACQdgBahCEAiACKAIQDQIgAigCFCIBQSRPBEAgARAACyACKAJIIgFBJE8EQCABEAALIAIoAtgBIgFBJEkNASABEAAMAQsgAiADNgLYASACQSA2AkggAkEIaiAAQdQCaiACQcgAaiACQdgBahCEAiACKAIIDQIgAigCDCIBQSRPBEAgARAACyACKAJIIgFBJE8EQCABEAALIAIoAtgBIgFBJEkNACABEAALIAAoAtACIgFBJE8EQCABEAALQQEhBEEAIQEgACgC1AIiA0EkSQ0CIAMQAAwCC0G4gMAAQRUQlgMAC0G4gMAAQRUQlgMACyAAIAQ6ANgCIAJB4AJqJAAgAQvUCAEEfyMAQfAAayIFJAAgBSADNgIMIAUgAjYCCAJAAkACQAJAIAUCfwJAAkAgAUGBAk8EQANAIAAgBmogBkF/aiIHIQZBgAJqLAAAQb9/TA0ACyAHQYECaiIGIAFJDQIgAUH/fWogB0cNBCAFIAY2AhQMAQsgBSABNgIUCyAFIAA2AhBB+MvAACEHQQAMAQsgACAHakGBAmosAABBv39MDQEgBSAGNgIUIAUgADYCEEGQ1MAAIQdBBQs2AhwgBSAHNgIYAkAgAiABSyIGIAMgAUtyRQRAAn8CQAJAIAIgA00EQAJAAkAgAkUNACACIAFPBEAgASACRg0BDAILIAAgAmosAABBQEgNAQsgAyECCyAFIAI2AiAgAiABIgZJBEAgAkEBaiIDQQAgAkF9aiIGIAYgAksbIgZJDQYgACADaiAAIAZqayEGA0AgBkF/aiEGIAAgAmogAkF/aiIHIQIsAABBQEgNAAsgB0EBaiEGCwJAIAZFDQAgBiABTwRAIAEgBkYNAQwKCyAAIAZqLAAAQb9/TA0JCyABIAZGDQcCQCAAIAZqIgEsAAAiAEF/TARAIAEtAAFBP3EhAyAAQR9xIQIgAEFfSw0BIAJBBnQgA3IhAAwECyAFIABB/wFxNgIkQQEMBAsgAS0AAkE/cSADQQZ0ciEDIABBcE8NASADIAJBDHRyIQAMAgsgBUHkAGpBgAE2AgAgBUHcAGpBgAE2AgAgBUHUAGpB7AA2AgAgBUE8akEENgIAIAVBxABqQQQ2AgAgBUH01MAANgI4IAVBADYCMCAFQewANgJMIAUgBUHIAGo2AkAgBSAFQRhqNgJgIAUgBUEQajYCWCAFIAVBDGo2AlAgBSAFQQhqNgJIDAgLIAJBEnRBgIDwAHEgAS0AA0E/cSADQQZ0cnIiAEGAgMQARg0FCyAFIAA2AiRBASAAQYABSQ0AGkECIABBgBBJDQAaQQNBBCAAQYCABEkbCyEHIAUgBjYCKCAFIAYgB2o2AiwgBUE8akEFNgIAIAVBxABqQQU2AgAgBUHsAGpBgAE2AgAgBUHkAGpBgAE2AgAgBUHcAGpBggE2AgAgBUHUAGpBgwE2AgAgBUHI1cAANgI4IAVBADYCMCAFQewANgJMIAUgBUHIAGo2AkAgBSAFQRhqNgJoIAUgBUEQajYCYCAFIAVBKGo2AlggBSAFQSRqNgJQIAUgBUEgajYCSAwFCyAFIAIgAyAGGzYCKCAFQTxqQQM2AgAgBUHEAGpBAzYCACAFQdwAakGAATYCACAFQdQAakGAATYCACAFQbjUwAA2AjggBUEANgIwIAVB7AA2AkwgBSAFQcgAajYCQCAFIAVBGGo2AlggBSAFQRBqNgJQIAUgBUEoajYCSAwECyAGIANBjNbAABCIAwALIAAgAUEAIAYgBBDzAgALQfjLwABBKyAEEPcBAAsgACABIAYgASAEEPMCAAsgBUEwaiAEEKgCAAvwBwEIfwJAAkAgAEEDakF8cSICIABrIgUgAUsgBUEES3INACABIAVrIgdBBEkNACAHQQNxIQhBACEBAkAgACACRg0AIAVBA3EhAwJAIAIgAEF/c2pBA0kEQCAAIQIMAQsgBUF8cSEGIAAhAgNAIAEgAiwAAEG/f0pqIAIsAAFBv39KaiACLAACQb9/SmogAiwAA0G/f0pqIQEgAkEEaiECIAZBfGoiBg0ACwsgA0UNAANAIAEgAiwAAEG/f0pqIQEgAkEBaiECIANBf2oiAw0ACwsgACAFaiEAAkAgCEUNACAAIAdBfHFqIgIsAABBv39KIQQgCEEBRg0AIAQgAiwAAUG/f0pqIQQgCEECRg0AIAQgAiwAAkG/f0pqIQQLIAdBAnYhBSABIARqIQMDQCAAIQEgBUUNAiAFQcABIAVBwAFJGyIEQQNxIQYgBEECdCEIAkAgBEH8AXEiB0UEQEEAIQIMAQsgASAHQQJ0aiEJQQAhAgNAIABFDQEgAiAAKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIABBBGooAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWogAEEIaigCACICQX9zQQd2IAJBBnZyQYGChAhxaiAAQQxqKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIQIgAEEQaiIAIAlHDQALCyAFIARrIQUgASAIaiEAIAJBCHZB/4H8B3EgAkH/gfwHcWpBgYAEbEEQdiADaiEDIAZFDQALAkAgAUUEQEEAIQIMAQsgASAHQQJ0aiEAIAZBf2pB/////wNxIgJBAWoiBEEDcSEBAkAgAkEDSQRAQQAhAgwBCyAEQfz///8HcSEGQQAhAgNAIAIgACgCACICQX9zQQd2IAJBBnZyQYGChAhxaiAAQQRqKAIAIgJBf3NBB3YgAkEGdnJBgYKECHFqIABBCGooAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWogAEEMaigCACICQX9zQQd2IAJBBnZyQYGChAhxaiECIABBEGohACAGQXxqIgYNAAsLIAFFDQADQCACIAAoAgAiAkF/c0EHdiACQQZ2ckGBgoQIcWohAiAAQQRqIQAgAUF/aiIBDQALCyACQQh2Qf+B/AdxIAJB/4H8B3FqQYGABGxBEHYgA2oPCyABRQRAQQAPCyABQQNxIQICQCABQX9qQQNJBEAMAQsgAUF8cSEBA0AgAyAALAAAQb9/SmogACwAAUG/f0pqIAAsAAJBv39KaiAALAADQb9/SmohAyAAQQRqIQAgAUF8aiIBDQALCyACRQ0AA0AgAyAALAAAQb9/SmohAyAAQQFqIQAgAkF/aiICDQALCyADC5EHAQV/IAAQqwMiACAAEJcDIgIQqAMhAQJAAkACQCAAEJgDDQAgACgCACEDAkAgABCBA0UEQCACIANqIQIgACADEKkDIgBB0O7AACgCAEcNASABKAIEQQNxQQNHDQJByO7AACACNgIAIAAgAiABEMUCDwsgAiADakEQaiEADAILIANBgAJPBEAgABBiDAELIABBDGooAgAiBCAAQQhqKAIAIgVHBEAgBSAENgIMIAQgBTYCCAwBC0HA7sAAQcDuwAAoAgBBfiADQQN2d3E2AgALAkAgARD8AgRAIAAgAiABEMUCDAELAkACQAJAQdTuwAAoAgAgAUcEQCABQdDuwAAoAgBHDQFB0O7AACAANgIAQcjuwABByO7AACgCACACaiIBNgIAIAAgARDhAg8LQdTuwAAgADYCAEHM7sAAQczuwAAoAgAgAmoiATYCACAAIAFBAXI2AgQgAEHQ7sAAKAIARg0BDAILIAEQlwMiAyACaiECAkAgA0GAAk8EQCABEGIMAQsgAUEMaigCACIEIAFBCGooAgAiAUcEQCABIAQ2AgwgBCABNgIIDAELQcDuwABBwO7AACgCAEF+IANBA3Z3cTYCAAsgACACEOECIABB0O7AACgCAEcNAkHI7sAAIAI2AgAMAwtByO7AAEEANgIAQdDuwABBADYCAAtB4O7AACgCACABTw0BQQhBCBDmAiEAQRRBCBDmAiEBQRBBCBDmAiEDQQBBEEEIEOYCQQJ0ayICQYCAfCADIAAgAWpqa0F3cUF9aiIAIAIgAEkbRQ0BQdTuwAAoAgBFDQFBCEEIEOYCIQBBFEEIEOYCIQFBEEEIEOYCIQJBAAJAQczuwAAoAgAiBCACIAEgAEEIa2pqIgJNDQBB1O7AACgCACEBQajswAAhAAJAA0AgACgCACABTQRAIAAQgwMgAUsNAgsgACgCCCIADQALQQAhAAsgABCZAw0AIABBDGooAgAaDAALQQAQZWtHDQFBzO7AACgCAEHg7sAAKAIATQ0BQeDuwABBfzYCAA8LIAJBgAJJDQEgACACEGBB6O7AAEHo7sAAKAIAQX9qIgA2AgAgAA0AEGUaDwsPCyACQXhxQbjswABqIQECf0HA7sAAKAIAIgNBASACQQN2dCICcQRAIAEoAggMAQtBwO7AACACIANyNgIAIAELIQMgASAANgIIIAMgADYCDCAAIAE2AgwgACADNgIIC4YHAQh/AkACQCAAKAIIIgpBAUdBACAAKAIQIgNBAUcbRQRAAkAgA0EBRw0AIAEgAmohCSAAQRRqKAIAQQFqIQYgASEEA0ACQCAEIQMgBkF/aiIGRQ0AIAMgCUYNAgJ/IAMsAAAiBUF/SgRAIAVB/wFxIQUgA0EBagwBCyADLQABQT9xIQggBUEfcSEEIAVBX00EQCAEQQZ0IAhyIQUgA0ECagwBCyADLQACQT9xIAhBBnRyIQggBUFwSQRAIAggBEEMdHIhBSADQQNqDAELIARBEnRBgIDwAHEgAy0AA0E/cSAIQQZ0cnIiBUGAgMQARg0DIANBBGoLIgQgByADa2ohByAFQYCAxABHDQEMAgsLIAMgCUYNACADLAAAIgRBf0ogBEFgSXIgBEFwSXJFBEAgBEH/AXFBEnRBgIDwAHEgAy0AA0E/cSADLQACQT9xQQZ0IAMtAAFBP3FBDHRycnJBgIDEAEYNAQsCQAJAIAdFDQAgByACTwRAQQAhAyACIAdGDQEMAgtBACEDIAEgB2osAABBQEgNAQsgASEDCyAHIAIgAxshAiADIAEgAxshAQsgCkUNAiAAQQxqKAIAIQcCQCACQRBPBEAgASACECohBAwBCyACRQRAQQAhBAwBCyACQQNxIQUCQCACQX9qQQNJBEBBACEEIAEhAwwBCyACQXxxIQZBACEEIAEhAwNAIAQgAywAAEG/f0pqIAMsAAFBv39KaiADLAACQb9/SmogAywAA0G/f0pqIQQgA0EEaiEDIAZBfGoiBg0ACwsgBUUNAANAIAQgAywAAEG/f0pqIQQgA0EBaiEDIAVBf2oiBQ0ACwsgByAESwRAIAcgBGsiBCEGAkACQAJAQQAgAC0AICIDIANBA0YbQQNxIgNBAWsOAgABAgtBACEGIAQhAwwBCyAEQQF2IQMgBEEBakEBdiEGCyADQQFqIQMgAEEEaigCACEEIAAoAhwhBSAAKAIAIQACQANAIANBf2oiA0UNASAAIAUgBCgCEBEBAEUNAAtBAQ8LQQEhAyAFQYCAxABGDQIgACABIAIgBCgCDBEFAA0CQQAhAwNAIAMgBkYEQEEADwsgA0EBaiEDIAAgBSAEKAIQEQEARQ0ACyADQX9qIAZJDwsMAgsgACgCACABIAIgACgCBCgCDBEFACEDCyADDwsgACgCACABIAIgACgCBCgCDBEFAAutBwIGfwJ+IwBBMGsiAyQAIANB/wE6AA8gA0EQaiABIANBD2pBASACKAIgIgYRBAACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADLQAQQQRHBEAgAykDECIJQv8Bg0IGUg0BCyADLQAPQX9qDgoTEAIDBAUGBwkIAQsgACAJNwIEDBMLIABBBToABAwSCyADQX82AiggA0EQaiABIANBKGpBBCAGEQQAIAMtABBBBEcEQCADMQAQQgZSDQ0LIAM1AighCUEEIQVBAiEEDBALIANCfzcDKCADQRBqIAEgA0EoakEIIAYRBAAgAy0AEEEERwRAIAMxABBCBlINCwsgAykDKCIKQiCGIQkgCkIgiKchB0EIIQVBAyEEDA8LIANBfzYCKCADQRBqIAEgA0EoakEEIAYRBAAgAy0AEEEERwRAIAMpAxAiCUL/AYNCBlINCQsgAzUCKCEJQQQhBEEEIQUMDgsgA0J/NwMgIANBKGogASADQSBqQQggBhEEACADLQAoQQRHBEAgAykDKCIJQv8Bg0IGUg0HCyADIAMpAyAiCTcCFCAJQiCIpyEHIAMpAxAhCUEIIQVBBSEEDA0LIANBfzYCKCADQRBqIAEgA0EoakEEIAYRBAAgAy0AEEEERwRAIAMpAxAiCUL/AYNCBlINBQsgAzUCKCEJQQQhBUEGIQQMDAsgA0J/NwMgIANBKGogASADQSBqQQggBhEEACADLQAoQQRHBEAgAykDKCIJQv8Bg0IGUg0DCyADIAMpAyAiCTcCFCAJQiCIpyEHIAMpAxAhCUEIIQVBByEEDAsLIANBEGogASACEEUgAygCFEUNCCADKAIYIQcgAykDECEJIAMoAhwhBUEJIQQMCgsgA0EQaiABIAIQvgEgAygCEEUNCCAAIAMpAhQ3AgQMCgsgACAJNwIEDAkLIAAgCTcCBAwICyAAIAk3AgQMBwsgACAJNwIEDAYLIAAgAzUCECADNQIUQiCGhDcCBAwFCyAAIAM1AhAgAzUCFEIghoQ3AgQMBAsgA0EQaiABIAIQRSADKAIUBEAgAygCGCEHIAMpAxAhCSADKAIcIQVBASEEDAMLIAAgAykDGDcCBAwDCyAAIAMpAxg3AgQMAgtBCCEEIANBGGooAgAhBSADLQAUIQgLIAAgBzYADCAAIAk3AAQgACAIOgABIAAgBDoAACAAIAVBAWo2AhAMAQsgAEEKOgAACyADQTBqJAALjwcBBn8CQAJAAkAgAkEJTwRAIAMgAhBJIgINAUEADwtBCEEIEOYCIQFBFEEIEOYCIQVBEEEIEOYCIQRBACECQQBBEEEIEOYCQQJ0ayIGQYCAfCAEIAEgBWpqa0F3cUF9aiIBIAYgAUkbIANNDQFBECADQQRqQRBBCBDmAkF7aiADSxtBCBDmAiEFIAAQqwMiASABEJcDIgYQqAMhBAJAAkACQAJAAkACQAJAIAEQgQNFBEAgBiAFTw0BIARB1O7AACgCAEYNAiAEQdDuwAAoAgBGDQMgBBD8Ag0HIAQQlwMiByAGaiIIIAVJDQcgCCAFayEGIAdBgAJJDQQgBBBiDAULIAEQlwMhBCAFQYACSQ0GIAQgBUEEak9BACAEIAVrQYGACEkbDQUgASgCACIGIARqQRBqIQcgBUEfakGAgAQQ5gIhBEEAIgVFDQYgBSAGaiIBIAQgBmsiAEFwaiICNgIEIAEgAhCoA0EHNgIEIAEgAEF0ahCoA0EANgIEQdjuwABB2O7AACgCACAEIAdraiIANgIAQeTuwABB5O7AACgCACICIAUgBSACSxs2AgBB3O7AAEHc7sAAKAIAIgIgACACIABLGzYCAAwJCyAGIAVrIgRBEEEIEOYCSQ0EIAEgBRCoAyEGIAEgBRC6AiAGIAQQugIgBiAEEDwMBAtBzO7AACgCACAGaiIGIAVNDQQgASAFEKgDIQQgASAFELoCIAQgBiAFayIFQQFyNgIEQczuwAAgBTYCAEHU7sAAIAQ2AgAMAwtByO7AACgCACAGaiIGIAVJDQMCQCAGIAVrIgRBEEEIEOYCSQRAIAEgBhC6AkEAIQRBACEGDAELIAEgBRCoAyIGIAQQqAMhByABIAUQugIgBiAEEOECIAcgBygCBEF+cTYCBAtB0O7AACAGNgIAQcjuwAAgBDYCAAwCCyAEQQxqKAIAIgkgBEEIaigCACIERwRAIAQgCTYCDCAJIAQ2AggMAQtBwO7AAEHA7sAAKAIAQX4gB0EDdndxNgIACyAGQRBBCBDmAk8EQCABIAUQqAMhBCABIAUQugIgBCAGELoCIAQgBhA8DAELIAEgCBC6AgsgAQ0DCyADECQiBUUNASAFIAAgARCXA0F4QXwgARCBAxtqIgEgAyABIANJGxChAyAAECsPCyACIAAgASADIAEgA0kbEKEDGiAAECsLIAIPCyABEIEDGiABEKoDC5EHAQ1/AkACQCACKAIAIgtBIiACKAIEIg0oAhAiDhEBAEUEQAJAIAFFBEBBACECDAELIAAgAWohD0EAIQIgACEHAkADQAJAIAciCCwAACIFQX9KBEAgCEEBaiEHIAVB/wFxIQMMAQsgCC0AAUE/cSEEIAVBH3EhAyAFQV9NBEAgA0EGdCAEciEDIAhBAmohBwwBCyAILQACQT9xIARBBnRyIQQgCEEDaiEHIAVBcEkEQCAEIANBDHRyIQMMAQsgA0ESdEGAgPAAcSAHLQAAQT9xIARBBnRyciIDQYCAxABGDQIgCEEEaiEHC0GCgMQAIQVBMCEEAkACQAJAAkACQAJAAkACQAJAIAMOIwYBAQEBAQEBAQIEAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEFAAsgA0HcAEYNBAsgAxBORQRAIAMQcg0GCyADQYGAxABGDQUgA0EBcmdBAnZBB3MhBCADIQUMBAtB9AAhBAwDC0HyACEEDAILQe4AIQQMAQsgAyEECyAGIAJJDQECQCACRQ0AIAIgAU8EQCABIAJGDQEMAwsgACACaiwAAEFASA0CCwJAIAZFDQAgBiABTwRAIAEgBkcNAwwBCyAAIAZqLAAAQb9/TA0CCyALIAAgAmogBiACayANKAIMEQUABEBBAQ8LQQUhCQNAIAkhDCAFIQJBgYDEACEFQdwAIQoCQAJAAkACQAJAAkAgAkGAgLx/akEDIAJB///DAEsbQQFrDgMBBQACC0EAIQlB/QAhCiACIQUCQAJAAkAgDEH/AXFBAWsOBQcFAAECBAtBAiEJQfsAIQoMBQtBAyEJQfUAIQoMBAtBBCEJQdwAIQoMAwtBgIDEACEFIAQhCiAEQYCAxABHDQMLAn9BASADQYABSQ0AGkECIANBgBBJDQAaQQNBBCADQYCABEkbCyAGaiECDAQLIAxBASAEGyEJQTBB1wAgAiAEQQJ0dkEPcSIFQQpJGyAFaiEKIARBf2pBACAEGyEECyACIQULIAsgCiAOEQEARQ0AC0EBDwsgBiAIayAHaiEGIAcgD0cNAQwCCwsgACABIAIgBkGk0MAAEPMCAAsgAkUEQEEAIQIMAQsgAiABTwRAIAEgAkYNAQwECyAAIAJqLAAAQb9/TA0DCyALIAAgAmogASACayANKAIMEQUARQ0BC0EBDwsgC0EiIA4RAQAPCyAAIAEgAiABQbTQwAAQ8wIAC4cGAQh/AkAgAkUNAEEAIAJBeWoiBCAEIAJLGyEJIAFBA2pBfHEgAWshCkEAIQQDQAJAAkACQAJAAkACQAJAAkACQCABIARqLQAAIgdBGHRBGHUiCEEATgRAIAogBGtBA3EgCkF/RnINASAEIAlJDQIMCAtBASEGQQEhAwJAAkACQAJAAkACQAJAAkAgB0GQ0sAAai0AAEF+ag4DAAECDgsgBEEBaiIFIAJJDQZBACEDDA0LQQAhAyAEQQFqIgUgAk8NDCABIAVqLAAAIQUgB0GgfmoiA0UNASADQQ1GDQIMAwsgBEEBaiIDIAJPBEBBACEDDAwLIAEgA2osAAAhBQJAAkACQCAHQZB+ag4FAQAAAAIACyAIQQ9qQf8BcUECSwRAQQEhAwwOCyAFQX9MDQlBASEDDA0LIAVB8ABqQf8BcUEwSQ0JDAsLIAVBj39KDQoMCAsgBUFgcUGgf0cNCQwCCyAFQaB/Tg0IDAELAkAgCEEfakH/AXFBDE8EQCAIQX5xQW5HBEBBASEDDAsLIAVBf0wNAUEBIQMMCgsgBUG/f0oNCAwBC0EBIQMgBUFATw0IC0EAIQMgBEECaiIFIAJPDQcgASAFaiwAAEG/f0wNBUEBIQNBAiEGDAcLIAEgBWosAABBv39KDQUMBAsgBEEBaiEEDAcLA0AgASAEaiIDKAIAQYCBgoR4cQ0GIANBBGooAgBBgIGChHhxDQYgBEEIaiIEIAlJDQALDAULQQEhAyAFQUBPDQMLIARBAmoiAyACTwRAQQAhAwwDCyABIANqLAAAQb9/SgRAQQIhBkEBIQMMAwtBACEDIARBA2oiBSACTw0CIAEgBWosAABBv39MDQBBAyEGQQEhAwwCCyAFQQFqIQQMAwtBASEDCyAAIAQ2AgQgAEEJaiAGOgAAIABBCGogAzoAACAAQQE2AgAPCyAEIAJPDQADQCABIARqLAAAQQBIDQEgAiAEQQFqIgRHDQALDAILIAQgAkkNAAsLIAAgATYCBCAAQQhqIAI2AgAgAEEANgIAC/QFAQd/An8gAQRAQStBgIDEACAAKAIYIglBAXEiARshCiABIAVqDAELIAAoAhghCUEtIQogBUEBagshCAJAIAlBBHFFBEBBACECDAELAkAgA0EQTwRAIAIgAxAqIQYMAQsgA0UEQAwBCyADQQNxIQsCQCADQX9qQQNJBEAgAiEBDAELIANBfHEhByACIQEDQCAGIAEsAABBv39KaiABLAABQb9/SmogASwAAkG/f0pqIAEsAANBv39KaiEGIAFBBGohASAHQXxqIgcNAAsLIAtFDQADQCAGIAEsAABBv39KaiEGIAFBAWohASALQX9qIgsNAAsLIAYgCGohCAsCQAJAIAAoAghFBEBBASEBIAAoAgAiByAAQQRqKAIAIgAgCiACIAMQogINAQwCCwJAAkACQAJAIABBDGooAgAiByAISwRAIAlBCHENBCAHIAhrIgYhB0EBIAAtACAiASABQQNGG0EDcSIBQQFrDgIBAgMLQQEhASAAKAIAIgcgAEEEaigCACIAIAogAiADEKICDQQMBQtBACEHIAYhAQwBCyAGQQF2IQEgBkEBakEBdiEHCyABQQFqIQEgAEEEaigCACEGIAAoAhwhCCAAKAIAIQACQANAIAFBf2oiAUUNASAAIAggBigCEBEBAEUNAAtBAQ8LQQEhASAIQYCAxABGDQEgACAGIAogAiADEKICDQEgACAEIAUgBigCDBEFAA0BQQAhAQJ/A0AgByABIAdGDQEaIAFBAWohASAAIAggBigCEBEBAEUNAAsgAUF/agsgB0khAQwBCyAAKAIcIQsgAEEwNgIcIAAtACAhDEEBIQEgAEEBOgAgIAAoAgAiBiAAQQRqKAIAIgkgCiACIAMQogINACAHIAhrQQFqIQECQANAIAFBf2oiAUUNASAGQTAgCSgCEBEBAEUNAAtBAQ8LQQEhASAGIAQgBSAJKAIMEQUADQAgACAMOgAgIAAgCzYCHEEADwsgAQ8LIAcgBCAFIAAoAgwRBQAL7gUCB38CfiMAQdAAayIDJAAgAyACNgIQIAEoAgghAiADIANBEGo2AhQCQCACQQFqIgUgAkkEQBDoASADKAIEIQUgAygCACEEDAELAkACQAJAAkAgBSABKAIAIgQgBEEBakEDdkEHbCAEQQhJGyIEQQF2SwRAIAUgBEEBaiIEIAUgBEsbIgRBCEkNASAEIARB/////wFxRgRAQX8gBEEDdEEHbkF/amd2QQFqIQQMAwsQ6AEgAygCCCEEIAMoAgwiBUGBgICAeEcNBQwCCyABIANBFGpBmIDAAEEYEDMMAgtBBEEIIARBBEkbIQQLIANBMGpBGCAEEGYgAygCMCEEIAMoAjwiBUUNASADKAI0IQYgBUH/ASAEQQlqEKIDIQcgA0KYgICAgAE3AyggAyAHNgIkIAMgBDYCGCADIAI2AiAgAyAGIAJrNgIcIAEoAgAiCEF/RwRAQQAhBgNAIAEoAgwiAiAGaiwAAEEATgRAIAcgBCADKAIUKAIAIAJBACAGa0EYbGpBaGoQQ6ciCXEiBWopAABCgIGChIiQoMCAf4MiClAEQEEIIQIDQCACIAVqIQUgAkEIaiECIAcgBCAFcSIFaikAAEKAgYKEiJCgwIB/gyIKUA0ACwsgByAKeqdBA3YgBWogBHEiAmosAABBf0oEQCAHKQMAQoCBgoSIkKDAgH+DeqdBA3YhAgsgAiAHaiAJQRl2IgU6AAAgAkF4aiAEcSAHakEIaiAFOgAAIAcgAkF/c0EYbGoiAiABKAIMIAZBf3NBGGxqIgUpAAA3AAAgAkEQaiAFQRBqKQAANwAAIAJBCGogBUEIaikAADcAAAsgBiAIRiAGQQFqIQZFDQALCyABKQIAIQogASADKQMYNwIAIANBIGoiAikDACELIAIgAUEIaiIBKQIANwMAIAEgCzcCACADIAo3AxggA0EYahDlAQtBgYCAgHghBQwBCyADKAI0IQULIAAgBTYCBCAAIAQ2AgAgA0HQAGokAAvJBQIOfwF+IAAoAgBBAWohByAAKAIMIQYDQAJAAn8gBEEBcQRAIAVBB2oiBCAFSSAEIAdPcg0CIAVBCGoMAQsgBSAHSSIKRQ0BIAogBSIEagshBSAEIAZqIgQgBCkDACISQn+FQgeIQoGChIiQoMCAAYMgEkL//v379+/fv/8AhHw3AwBBASEEDAELCwJAIAdBCE8EQCAGIAdqIAYpAAA3AAAMAQsgBkEIaiAGIAcQowMLIAACf0EAIAAoAgAiDUF/Rg0AGkEAIANrIQpBACEFA0ACQCAAKAIMIgQgBSIHai0AAEGAAUcNACAEIAtqIQ4gBCAHQX9zIANsaiEPIAIoAhQhEAJAA0AgASAAIAcgEBENACESIAAoAgAiCSASpyIMcSIGIQQgACgCDCIIIAZqKQAAQoCBgoSIkKDAgH+DIhJQBEBBCCEFIAYhBANAIAQgBWohBCAFQQhqIQUgCCAEIAlxIgRqKQAAQoCBgoSIkKDAgH+DIhJQDQALCyAIIBJ6p0EDdiAEaiAJcSIEaiwAAEF/SgRAIAgpAwBCgIGChIiQoMCAf4N6p0EDdiEECyAEIAZrIAcgBmtzIAlxQQhJDQEgCCAEQX9zIANsaiEFIAQgCGoiBi0AACAGIAxBGXYiBjoAACAEQXhqIAlxIAhqQQhqIAY6AABB/wFHBEAgA0UNASAKIQQDQCAEIA5qIgYtAAAhCCAGIAUtAAA6AAAgBSAIOgAAIAVBAWohBSAEQQFqIgQNAAsMAQsLIAAoAgwiBCAHakH/AToAACAEIAAoAgAgB0F4anFqQQhqQf8BOgAAIAUgDyADEKEDGgwBCyAHIAhqIAxBGXYiBDoAACAJIAdBeGpxIAhqQQhqIAQ6AAALIAdBAWohBSALIANrIQsgByANRw0ACyAAKAIAIgEgAUEBakEDdkEHbCABQQhJGwsgACgCCGs2AgQL9wUCCH8CfiMAQdAAayIBJAAgAUH46cAANgIQQZDqwAAoAgAhBCABIAFBEGo2AhQCQCAEQQFqIgIgBEkEQBDoASABKAIEIQIgASgCACEDDAELAkACQAJAAkAgAkGI6sAAKAIAIgMgA0EBakEDdkEHbCADQQhJGyIDQQF2SwRAIAIgA0EBaiIDIAIgA0sbIgNBCEkNASADIANB/////wFxRgRAQX8gA0EDdEEHbkF/amd2QQFqIQMMAwsQ6AEgASgCCCEDIAEoAgwiAkGBgICAeEcNBQwCC0GI6sAAIAFBFGpBgIDAAEEQEDMMAgtBBEEIIANBBEkbIQMLIAFBMGpBECADEGYgASgCMCEDIAEoAjwiAkUNASABKAI0IQUgAkH/ASADQQlqEKIDIQYgAUKQgICAgAE3AyggASAGNgIkIAEgAzYCGCABIAQ2AiAgASAFIARrNgIcQYjqwAAoAgAiB0F/RwRAQQAhBQNAQZTqwAAoAgAiAiAFaiwAAEEATgRAIAYgAyABKAIUKAIAIAIgBUEEdGtBcGoQQ6ciCHEiAmopAABCgIGChIiQoMCAf4MiCVAEQEEIIQQDQCACIARqIQIgBEEIaiEEIAYgAiADcSICaikAAEKAgYKEiJCgwIB/gyIJUA0ACwsgBiAJeqdBA3YgAmogA3EiBGosAABBf0oEQCAGKQMAQoCBgoSIkKDAgH+DeqdBA3YhBAsgBCAGaiAIQRl2IgI6AAAgBEF4aiADcSAGakEIaiACOgAAIAYgBEF/c0EEdGoiAkGU6sAAKAIAIAVBf3NBBHRqIgQpAAA3AAAgAkEIaiAEQQhqKQAANwAACyAFIAdGIAVBAWohBUUNAAsLQYjqwAApAgAhCUGI6sAAIAEpAxg3AgAgAUEgaiICKQMAIQogAkGQ6sAAKQIANwMAQZDqwAAgCjcCACABIAk3AxggAUEYahDlAQtBgYCAgHghAgwBCyABKAI0IQILIAAgAjYCBCAAIAM2AgAgAUHQAGokAAuSBQEHfwJAAkACfwJAIAAgAWsgAkkEQCABIAJqIQUgACACaiEDIAJBD0sNASAADAILIAJBD00EQCAAIQMMAwsgAEEAIABrQQNxIgVqIQQgBQRAIAAhAyABIQADQCADIAAtAAA6AAAgAEEBaiEAIANBAWoiAyAESQ0ACwsgBCACIAVrIgJBfHEiBmohAwJAIAEgBWoiBUEDcSIABEAgBkEBSA0BIAVBfHEiB0EEaiEBQQAgAEEDdCIIa0EYcSEJIAcoAgAhAANAIAQgACAIdiABKAIAIgAgCXRyNgIAIAFBBGohASAEQQRqIgQgA0kNAAsMAQsgBkEBSA0AIAUhAQNAIAQgASgCADYCACABQQRqIQEgBEEEaiIEIANJDQALCyACQQNxIQIgBSAGaiEBDAILIANBfHEhAEEAIANBA3EiBmshByAGBEAgASACakF/aiEEA0AgA0F/aiIDIAQtAAA6AAAgBEF/aiEEIAAgA0kNAAsLIAAgAiAGayIGQXxxIgJrIQNBACACayECAkAgBSAHaiIFQQNxIgQEQCACQX9KDQEgBUF8cSIHQXxqIQFBACAEQQN0IghrQRhxIQkgBygCACEEA0AgAEF8aiIAIAQgCXQgASgCACIEIAh2cjYCACABQXxqIQEgAyAASQ0ACwwBCyACQX9KDQAgASAGakF8aiEBA0AgAEF8aiIAIAEoAgA2AgAgAUF8aiEBIAMgAEkNAAsLIAZBA3EiAEUNAiACIAVqIQUgAyAAawshACAFQX9qIQEDQCADQX9qIgMgAS0AADoAACABQX9qIQEgACADSQ0ACwwBCyACRQ0AIAIgA2ohAANAIAMgAS0AADoAACABQQFqIQEgA0EBaiIDIABJDQALCwuJBgIEfwF+IwBBIGsiBCQAIAQgAS0AACIGQQFqOgAQIARBGGogAiAEQRBqQQEgAygCDCIFEQQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/IAQtABhBBEYEQCAEKAIcDAELIAQpAxgiCEL/AYNCBlINASAIQiCIpwshByAGQQFrDgkBAgMEBQYHCAkLCyAAIAg3AgAMDAsgBEEIaiABQQRqIAIgAxCGAQwICyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQQAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAgLIAQgBCkDGDcDCAwHCyAEIAErAwg5AxggBEEQaiACIARBGGpBCCAFEQQAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAcLIAQgBCkDEDcDCAwGCyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQQAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAYLIAQgBCkDGDcDCAwFCyAEIAEpAwg3AxggBEEQaiACIARBGGpBCCAFEQQAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAULIAQgBCkDEDcDCAwECyAEIAEoAgQ2AhAgBEEYaiACIARBEGpBBCAFEQQAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAQLIAQgBCkDGDcDCAwDCyAEIAEpAwg3AxggBEEQaiACIARBGGpBCCAFEQQAIAQtABBBBEYEQCAEIAQoAhQ2AgwgBEEGOgAIDAMLIAQgBCkDEDcDCAwCCyAEIAEtAAE6ABAgBEEYaiACIARBEGpBASAFEQQAIAQtABhBBEYEQCAEIAQoAhw2AgwgBEEGOgAIDAILIAQgBCkDGDcDCAwBCyAEQQhqIAFBBGogAiADEIYBCyAELQAIQQZGBEAgBCgCDCEGDAELIAQpAwgiCEL/AYNCBlINASAIQiCIpyEGCyAAQQY6AAAgACAGIAdqNgIEDAELIAAgCDcCAAsgBEEgaiQAC9MFAQV/IwBB8ABrIgMkACADQShqIAEgAhD5AiADIAMpAyg3AzAgA0HQAGogA0EwahA+AkAgAygCUARAIANB6ABqIANB2ABqKQMANwMAIAMgAykDUDcDYCADQSBqIANB4ABqEJ0DIAMoAiQhBCADKAIgIQYgA0EYaiADQeAAahCeAyADKAIcRQRAIAAgBjYCBCAAQQA2AgAgAEEIaiAENgIADAILAkACQAJAIAJFBEBBASEBDAELIAJBf0wNAiACQQEQ9wIiAUUNAQsgA0EANgJAIAMgATYCPCADIAI2AjggBCACSwR/IANBOGpBACAEEIUBIAMoAkAhBSADKAI8BSABCyAFaiAGIAQQoQMaIAMgBCAFaiICNgJAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEQfTLwAAvAAAiBTsAACAEQQJqQfbLwAAtAAAiBjoAACADIAJBA2oiAjYCQCADIAMpAzA3A0ggA0HQAGogA0HIAGoQPiADKAJQBEADQCADQegAaiADQdgAaikDADcDACADIAMpA1A3A2AgA0EQaiADQeAAahCdAyADKAIQIQcgAygCOCACayADKAIUIgRJBEAgA0E4aiACIAQQhQEgAygCQCECIAMoAjwhAQsgASACaiAHIAQQoQMaIAMgAiAEaiICNgJAIANBCGogA0HgAGoQngMgAygCDARAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEIAU7AAAgBEECaiAGOgAAIAMgAkEDaiICNgJACyADQdAAaiADQcgAahA+IAMoAlANAAsLIAAgAykDODcCBCAAQQE2AgAgAEEMaiADQUBrKAIANgIADAMLIAJBARCbAwALEJgCAAsgAEHAysAANgIEIABBADYCACAAQQhqQQA2AgALIANB8ABqJAAL0AQCBH8GfiAAIAAoAjggAmo2AjgCQCAAAn8CQAJAAkAgACgCPCIFRQRADAELAn4gAkEIIAVrIgQgAiAESRsiBkEDTQRAQgAMAQtBBCEDIAE1AAALIQcgACAAKQMwIANBAXIgBkkEQCABIANqMwAAIANBA3SthiAHhCEHIANBAnIhAwsgAyAGSQR+IAEgA2oxAAAgA0EDdK2GIAeEBSAHCyAFQQN0QThxrYaEIgc3AzAgBCACSw0BIAAgACkDGCAHhSIIIAApAwh8IgkgACkDECIKQg2JIAogACkDAHwiCoUiC3wiDCALQhGJhTcDECAAIAxCIIk3AwggACAJIAhCEImFIghCFYkgCCAKQiCJfCIIhTcDGCAAIAcgCIU3AwALIAIgBGsiAkEHcSEDIAQgAkF4cSICSQRAIAApAwghCCAAKQMQIQcgACkDACEJIAApAxghCgNAIAggASAEaikAACILIAqFIgh8IgogByAJfCIJIAdC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ACACQSRqQQA2AgAgAkH4nMAANgIYIAJBrJvAADYCICACQQA2AhAgASACQRBqENgBDAELIAIgADYCDCACQRxqQQI2AgAgAkEkakEBNgIAIAJB0JzAADYCGCACQQA2AhAgAkE+NgIsIAIgAkEoajYCICACIAJBDGo2AiggASACQRBqENgBCyACQTBqJAAL6QECAn8BfiMAQSBrIgMkACAAKAIARQRAIABBfzYCACADQRhqIABBHGopAgA3AwAgA0EQaiAAQRRqKQIANwMAIABBDGoiBCkCACEFIARBADYCACADIAU3AwggA0EIahDaAgJAIABBJGooAgBBAkYNACAAQShqKAIAIgRBJEkNACAEEAALIAAgATYCJCAAQShqIAI2AgAgAEEIaiICKAIAIQEgAkEANgIAIAAgACgCAEEBajYCACABBEAgACgCBCABKAIEEQIACyADQSBqJAAPC0GstMAAQRAgA0EIakG8tMAAQYS2wAAQtAEAC+kBAgN/An4jAEEgayIDJAAgA0EQaiABIAIQRQJAAkAgAygCFCIEBEAgAygCECEFIAMgAykDGCIHPgIIIAMgBDYCBCADIAU2AgAgA0EQaiABIAIQUyADKAIUIgFFDQEgAygCECECIAMpAxghBiAAIAMpAwA3AgAgACAGPgIUIAAgATYCECAAIAI2AgwgAEEIaiADQQhqKAIANgIAIAAgBkIgiKcgB0IgiKdqNgIYDAILIAMpAxghBiAAQQA2AgQgACAGNwIIDAELIAMpAxghBiAAQQA2AgQgACAGNwIIIAMQmgILIANBIGokAAvQAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEMbCEEIAVBq9Wq1QBJQQJ0IQYCQCACBEAgASgCBCEHIANBBDYCGCADIAJBDGw2AhQgAyAHNgIQDAELIANBADYCGAsgAyAEIAYgA0EQahCXASADKAIEIQQgAygCAARAIANBCGooAgAMAQsgASAFNgIAIAEgBDYCBEGBgICAeAs2AgQgACAENgIAIANBIGokAAvQAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEEdCEEIAVBgICAwABJQQN0IQYCQCACBEAgASgCBCEHIANBCDYCGCADIAJBBHQ2AhQgAyAHNgIQDAELIANBADYCGAsgAyAEIAYgA0EQahCXASADKAIEIQQgAygCAARAIANBCGooAgAMAQsgASAFNgIAIAEgBDYCBEGBgICAeAs2AgQgACAENgIAIANBIGokAAvPAQEFfyMAQSBrIgMkACAAAn9BACACQQFqIgQgAkkNABogASgCACICQQF0IgUgBCAFIARLGyIEQQQgBEEESxsiBUEobCEEIAVBtObMGUlBA3QhBgJAIAIEQCABKAIEIQcgA0EINgIYIAMgAkEobDYCFCADIAc2AhAMAQsgA0EANgIYCyADIAQgBiADQRBqEJcBIAMoAgQhBCADKAIABEAgA0EIaigCAAwBCyABIAU2AgAgASAENgIEQYGAgIB4CzYCBCAAIAQ2AgAgA0EgaiQAC88BAQV/IwBBIGsiAyQAIAACf0EAIAJBAWoiBCACSQ0AGiABKAIAIgJBAXQiBSAEIAUgBEsbIgRBBCAEQQRLGyIFQRhsIQQgBUHWqtUqSUECdCEGAkAgAgRAIAEoAgQhByADQQQ2AhggAyACQRhsNgIUIAMgBzYCEAwBCyADQQA2AhgLIAMgBCAGIANBEGoQlwEgAygCBCEEIAMoAgAEQCADQQhqKAIADAELIAEgBTYCACABIAQ2AgRBgYCAgHgLNgIEIAAgBDYCACADQSBqJAAL0AEBBX8jAEEgayIDJAAgAAJ/QQAgAkEBaiIEIAJJDQAaIAEoAgAiAkEBdCIFIAQgBSAESxsiBEEEIARBBEsbIgVBAnQhBCAFQYCAgIACSUECdCEGAkAgAgRAIAEoAgQhByADQQQ2AhggAyACQQJ0NgIUIAMgBzYCEAwBCyADQQA2AhgLIAMgBCAGIANBEGoQlwEgAygCBCEEIAMoAgAEQCADQQhqKAIADAELIAEgBTYCACABIAQ2AgRBgYCAgHgLNgIEIAAgBDYCACADQSBqJAALyQEBBX8jAEEwayICJAAgAkEIakGACBDeASACQQA2AhggAiACKQMINwMQIAJBIGogASACQRBqEIMBAkAgAi0AIEEGRgRAIAIoAiQhBSACKAIUIQQgAiACKAIYIgMQ3gEgAigCACEGIAIoAgQgBCADEKEDIQQgACAFNgIMIAAgAzYCCCAAIAQ2AgQgACAGNgIADAELIAIgAikDIDcDKCACQShqEKoBIQMgAEEANgIEIAAgAzYCAAsgAkEQahCaAiABELkBIAJBMGokAAvgAQECfyMAQSBrIgIkACACIAA2AgwgAiABKAIAQZjiwABBESABKAIEKAIMEQUAOgAYIAIgATYCFCACQQA6ABkgAkEANgIQIAJBEGogAkEMakGI4sAAEF8hAAJ/IAItABgiASAAKAIAIgNFDQAaIAFB/wFxIQBBASAADQAaIAIoAhQhAAJAIANBAUcNACACLQAZRQ0AIAAtABhBBHENAEEBIAAoAgBB5M3AAEEBIAAoAgQoAgwRBQANARoLIAAoAgBBo8zAAEEBIAAoAgQoAgwRBQALIAJBIGokAEH/AXFBAEcLvQECAn8BfiMAQSBrIgMkACADQYAIEN4BIANBADYCECADIAMpAwA3AwggA0EYaiABIANBCGpBqIvAABBWAkACQAJAAn8gAy0AGEEGRgRAIAMoAhwMAQsgAykDGCIFQv8Bg0IGUg0BIAVCIIinCyEBIAMoAhAiBCABSQ0CIAMoAgwgASACEOoBIABBBjoAACAAIAE2AgQMAQsgACAFNwIACyADQQhqEJoCIANBIGokAA8LIAEgBEGcjMAAEIcDAAvMAQECfyMAQSBrIgMkAAJAAkAgASACaiICIAFJDQAgACgCACIBQQF0IgQgAiAEIAJLGyICQQggAkEISxsiAkF/c0EfdiEEAkAgAQRAIANBATYCGCADIAE2AhQgAyAAQQRqKAIANgIQDAELIANBADYCGAsgAyACIAQgA0EQahCYASADKAIEIQEgAygCAEUEQCAAIAI2AgAgACABNgIEDAILIANBCGooAgAiAEGBgICAeEYNASAARQ0AIAEgABCbAwALEJgCAAsgA0EgaiQAC8wBAQJ/IwBBIGsiAyQAAkACQCABIAJqIgIgAUkNACAAKAIAIgFBAXQiBCACIAQgAksbIgJBCCACQQhLGyICQX9zQR92IQQCQCABBEAgA0EBNgIYIAMgATYCFCADIABBBGooAgA2AhAMAQsgA0EANgIYCyADIAIgBCADQRBqEJIBIAMoAgQhASADKAIARQRAIAAgAjYCACAAIAE2AgQMAgsgA0EIaigCACIAQYGAgIB4Rg0BIABFDQAgASAAEJsDAAsQmAIACyADQSBqJAALywECA38BfiMA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hgMAC6YBAQF/IwBBMGsiAyQAIANBBDoACCADIAE2AhAgA0EoaiACQRBqKQIANwMAIANBIGogAkEIaikCADcDACADIAIpAgA3AxgCQCADQQhqQZyJwAAgA0EYahA6BEAgAy0ACEEERgRAIABBxInAADYCBCAAQQI2AgAMAgsgACADKQMINwIADAELIABBBDoAACADLQAIQQRGDQAgA0EIahCHAgsgA0EwaiQAC6kBAQN/IwBBMGsiAiQAIAEoAgRFBEAgASgCDCEDIAJBEGoiBEEANgIAIAJCgICAgBA3AwggAiACQQhqNgIUIAJBKGogA0EQaikCADcDACACQSBqIANBCGopAgA3AwAgAiADKQIANwMYIAJBFGpBtLzAACACQRhqEDoaIAFBCGogBCgCADYCACABIAIpAwg3AgALIABBuMTAADYCBCAAIAE2AgAgAkEwaiQAC50BAQF/IwBBQGoiBCQAIAQgAjYCOCAEIAE2AjQgBCACNgIwIARBCGogBEEwahCyAiAEQSBqIAQoAgggBCgCDBDlAiAEQThqIgEgBEEoaigCADYCACAEIAQpAyA3AzAgBEEQaiAEQTBqIAMQUCABIARBGGooAgA2AgAgBCAEKQMQNwMwIAQgBEEwahCyAiAAIAQpAwA3AwAgBEFAayQAC6wBAQN/IwBBIGsiAyQAIANCADcDCCADQQE6ABwgA0EIahCGAiICIAIoAgBBAWoiBDYCAAJAIAQEQCACKAIIDQEgAkF/NgIIIAJBDGoiBBCJAiACQRhqQay3wAA2AgAgAkEUaiACQQhqNgIAIAJBEGogATYCACAEIAA2AgAgAkEANgIIIAIQ9AEgA0EgaiQADwsAC0GstMAAQRAgA0EIakG8tMAAQZi3wAAQtAEAC5sBAQF/IwBBQGoiAyQAIAMgAjYCOCADIAE2AjQgAyACNgIwIANBCGogA0EwahCyAiADQSBqIAMoAgggAygCDBDlAiADQThqIgEgA0EoaigCADYCACADIAMpAyA3AzAgA0EQaiADQTBqEFIgASADQRhqKAIANgIAIAMgAykDEDcDMCADIANBMGoQsgIgACADKQMANwMAIANBQGskAAuzAQECfyAAKAIIIgIEQCAAKAIEIQAgAkEobCECA0ACQAJAAkACQAJAAkACQCAAKAIADgkBAgYGAwYGBAUACyAAQQRq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CyAAQoKAgIDAl4AINwIACyAEQRBqJAALhwECAX8BfiMAQRBrIgEkAEGQ68AAKQMAUARAQaDrwAACfgJAIABFDQAgACkDACAAQgA3AwBCAVINACAAKQMIIQIgACkDEAwBCyABQgI3AwggAUIBNwMAIAEpAwAhAiABKQMICzcDAEGY68AAIAI3AwBBkOvAAEIBNwMACyABQRBqJABBmOvAAAt+AQF/IwBBEGsiASQAIAFBtrDAAEEEEAE2AgggAUHMsMAAQQQQATYCDCABIAAgAUEIaiABQQxqEOIBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHsADYCACADQfzMwAA2AhAgA0EANgIIIANB7AA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACEKgCAAt5AQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EUakECNgIAIANBHGpBAjYCACADQSxqQewANgIAIANBrNHAADYCECADQQA2AgggA0HsADYCJCADIANBIGo2AhggAyADQQRqNgIoIAMgAzYCICADQQhqIAIQqAIAC3kBAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRRqQQI2AgAgA0EcakECNgIAIANBLGpB7AA2AgAgA0HM0cAANgIQIANBADYCCCADQewANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANBCGogAhCoAgALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHsADYCACADQYDSwAA2AhAgA0EANgIIIANB7AA2AiQgAyADQSBqNgIYIAMgA0EEajYCKCADIAM2AiAgA0EIaiACEKgCAAtzAQR/IwBBEGsiASQAIAAoAggiAiAAKAIEIgNHBEAgAiADa0ECdkECdCECA0AgAygCACIEQSRPBEAgBBAACyADQQRqIQMgAkF8aiICDQALCyABIAAoAgw2AgwgASAAKAIANgIIIAFBCGoQmQIgAUEQaiQAC2wBAX8jAEEwayIDJAAgAyABNgIoIAMgADYCJCADIAE2AiAgA0EIaiADQSBqELICIANBEGogAygCCCADKAIMEOUCIANBKGogA0EYaigCADYCACADIAMpAxA3AyAgA0EgaiACEM8BIANBMGokAAtpAQF/IwBBMGsiAiQAIAIgATYCKCACIAA2AiQgAiABNgIgIAJBCGogAkEgahCyAiACQRBqIAIoAgggAigCDBDlAiACQShqIAJBGGooAgA2AgAgAiACKQMQNwMgIAJBIGoQaCACQTBqJAALcgEDfyMAQSBrIgIkAAJ/QQEgACABEFsNABogASgCBCEDIAEoAgAhBCACQQA2AhwgAkH4y8AANgIYIAJBATYCFCACQajMwAA2AhAgAkEANgIIQQEgBCADIAJBCGoQOg0AGiAAQQRqIAEQWwsgAkEgaiQAC3cBAX8CQAJAIABFDQAgACgCACEBIABBADYCACAAKAIEIQACQCABDgIBAgALIABBJEkNACAAEAALEFchAAtB1OrAACgCACEBQdTqwAAgADYCAEHQ6sAAKAIAQdDqwABBATYCAEUgAUEkSXJFBEAgARAAC0HU6sAAC3wBA38gACAAEKoDIgBBCBDmAiAAayICEKgDIQBBzO7AACABIAJrIgE2AgBB1O7AACAANgIAIAAgAUEBcjYCBEEIQQgQ5gIhAkEUQQgQ5gIhA0EQQQgQ5gIhBCAAIAEQqAMgBCADIAJBCGtqajYCBEHg7sAAQYCAgAE2AgALcwAjAEEwayIBJABBuOrAAC0AAARAIAFBFGpBAjYCACABQRxqQQE2AgAgAUHEw8AANgIQIAFBADYCCCABQewANgIkIAEgADYCLCABIAFBIGo2AhggASABQSxqNgIgIAFBCGpB7MPAABCoAgALIAFBMGokAAt2AQF/IAAtAAQhASAALQAFBEAgAUH/AXEhASAAAn9BASABDQAaIAAoAgAiAS0AGEEEcUUEQCABKAIAQd/NwABBAiABKAIEKAIMEQUADAELIAEoAgBB3s3AAEEBIAEoAgQoAgwRBQALIgE6AAQLIAFB/wFxQQBHC2kBAX8jAEEgayICJABBlOrAACgCAEUEQEHokcAAQStBrJrAABD3AQALIAJBGGogAEEIaigCADYCACACIAApAgA3AxAgAkEIaiACQRBqIAEQVSACKAIIIQAgAigCDCACQSBqJABBISAAGwtrAQJ/IwBBIGsiAiQAIAJBCGogASgCABACAkAgAigCCCIDBEAgAigCDCEBIAIgAzYCFCACIAE2AhggAiABNgIQIAIgAkEQahCyAiAAIAIoAgAgAigCBBDlAgwBCyAAQQA2AgQLIAJBIGokAAtrAQJ/IAFBBGooAgAhAwJAAkACQCABQQhqKAIAIgFFBEBBASECDAELIAFBf0wNASABQQEQ9wIiAkUNAgsgAiADIAEQoQMhAiAAIAE2AgggACACNgIEIAAgATYCAA8LEJgCAAsgAUEBEJsDAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQZCLwAAgAkEIahA6IAJBIGokAAthAQN/IAAgARDLAiAAKAIEIgQgACgCCCICaiEDAkACQCABQQJPBEAgA0EAIAFBf2oiARCiAxogBCABIAJqIgJqIQMMAQsgAUUNAQsgA0EAOgAAIAJBAWohAgsgACACNgIIC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0JHAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBtLzAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBqMrAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB8M/AACACQQhqEDogAkEgaiQAC1MBAn8jAEEgayICJAAgACgCBCEDIAAoAgAgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAyACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBkIvAACACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0JHAACACQQhqEDogAkEgaiQAC44BAgF/An4jAEEQayIBJABB8OnAACAAOwEAQejpwABCATcDACABEOcBIAEpAwghAiABKQMAIQNBlOrAACgCAARAQYjqwAAoAgAEQBCcARCrAgsLQZTqwABB+JfAADYCAEGI6sAAQgA3AwBB+OnAACADNwMAQYDqwAAgAjcDAEGQ6sAAQQA2AgAgAUEQaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB8M/AACACQQhqEDogAkEgaiQAC2EBAX8jAEFAaiIBJAAgAUEBOgAPIABBADYCCCAAQoCAgIAQNwIAIAFBEGogABC+AiABQQ9qIAFBEGoQkwEEQEGskMAAQTcgAUE4akHkkMAAQcCRwAAQtAEACyABQUBrJAALSAECfwJAIAFFBEBBASECDAELIAFBAE4EQCABIAFBf3NBH3YiAxD3AiICDQEgASADEJsDAAsQmAIACyAAIAI2AgQgACABNgIAC2IBAX8jAEEgayIDJAAgACgCACADQQhqIAEgAhAwIAMoAggEQCADIAMpAgw3AxhBvK3AAEErIANBGGpB6K3AAEHcrsAAELQBAAsgAygCDCADQRBqKAIAEJcCIANBIGokAEEAC2kBA38jAEEQayIBJAACQEEAQai3wAAoAgARBgAiAgRAIAAoAgAoAgAiACAAKAIAQQFqIgM2AgAgA0UNASACIAAQtgEgAUEQaiQADwtB/LfAAEHGACABQQhqQcS4wABBpLnAABC0AQALAAtWAQJ/AkAgAEEDcEEDc0EDcCIERQRADAELQQAhAANAIAAgAkcEQCAAIAFqQT06AAAgAEEBaiEDQQEhACADIARJDQEMAgsLIAIgAkH8ncAAEMMBAAsgAwtaAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAECAhASAEQQhqEL0CIAACfyAEKAIIRQRAIAAgAUEARzoAAUEADAELIAAgBCgCDDYCBEEBCzoAACAEQRBqJAALVAEBfyMAQTBrIgEkACABQRBqQZCawABBBRCFAiABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC1kBAn8gACgCDCICIAAoAgAiA0YEQCAAEKsBIAAoAgwhAiAAKAIAIQMLIAAoAgQgACgCCCACaiICQQAgAyACIANJG2tBAnRqIAE2AgAgACAAKAIMQQFqNgIMC0cBAn8CQCAAKAIAIgJFDQAgAiAAQRRqKAIAIgEgADUCECACQQFqrX6nakF/akEAIAFrcSIBakEJakUNACAAKAIMIAFrECsLC2ABAn8jAEEQayIBJAAgAUGMgcAAQRUQhQJBDEEEEPcCIgJFBEBBDEEEEJsDAAsgAiABKQMANwIAIAJBCGogAUEIaigCADYCACAAQeCAwAA2AgQgACACNgIAIAFBEGokAAtkAgJ/AX4jAEEQayICJABBAEHUjsAAKAIAEQYAIgEEQCABIAEpAwAiA0IBfDcDACAAIAEpAwg3AwggACADNwMAIAJBEGokAA8LQdiOwABBxgAgAkEIakGgj8AAQYCQwAAQtAEAC0oBAX8jAEEgayIAJAAgAEEUakEBNgIAIABBHGpBADYCACAAQcDJwAA2AhAgAEGkycAANgIYIABBADYCCCAAQQhqQZjKwAAQqAIAC00BAX8jAEEwayIBJAAgAUEQahDdASABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC2cBAX8jAEEgayIDJAAgAyACNgIMIANBEGoiAkGAAjsBBCACQQZqQQA6AAAgAkH9BTYCACADQRBqIAAgASADQQxqECUEQEHslsAAQSIgA0EYakGUksAAQeiXwAAQtAEACyADQSBqJAALTAECfyAAKAIIIgEEQCAAKAIEIQAgAUEEdCEBA0AgAC0AACICQX5qQQdJIAJFckUEQCAAQQRqEJoCCyAAQRBqIQAgAUFwaiIBDQALCwtWAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBD3AiIBRQ0BIAEgAzYCBCABIAI2AgAgAEGcsMAANgIEIAAgATYCAA8LAAtBCEEEEJsDAAtRAQN/IwBBEGsiASQAIAFBCGoQjwIQtAIgASgCDCECAkAgASgCCEUEQEEBIQMMAQsgAkEkSQ0AIAIQAAsgACACNgIEIAAgAzYCACABQRBqJAALSwECfyMAQRBrIgEkACABIABBeGo2AgggAC0AFCAAQQE6ABQgASABQQhqNgIMQQFxRQRAIAFBDGoQ4AELIAFBCGoQtQEgAUEQaiQAC18BA38jAEEQayIBJAACQCAAKAIMIgIEQCAAKAIIIgNFDQEgASACNgIIIAEgADYCBCABIAM2AgAgARC2AgALQcy8wABBK0GoxMAAEPcBAAtBzLzAAEErQZjEwAAQ9wEAC1ACAn8CfiABQRBqKAIAIgIgASkDACIEIAKtIgUgBCAFVBunIgNJBEAgAyACQfCCwAAQhgMACyAAIAIgA2s2AgQgACABQQxqKAIAIANqNgIAC0gBA38jAEEQayICJAAgAiABNgIMQQEhASACQQxqKAIAEAtBAEcgAigCDCEDBEBBACEBCyAAIAM2AgQgACABNgIAIAJBEGokAAtIAQN/IwBBEGsiAiQAIAIgATYCDEEBIQEgAkEMaigCABASQQFGIAIoAgwhAwRAQQAhAQsgACADNgIEIAAgATYCACACQRBqJAALSgEBfyMAQRBrIgQkACABIAIgAygCABANIQEgBEEIahC9AiAAAn8gASAEKAIIIgFFDQAaIAQoAgwLNgIEIAAgATYCACAEQRBqJAALWAECfyMAQRBrIgEkACABIAA2AgRBAEGot8AAKAIAEQYAIgIEQCACIAAQtgEgAUEQaiQADwsgAUEEahC1AUH8t8AAQcYAIAFBCGpBxLjAAEGkucAAELQBAAtYAQF/IwBBIGsiACQAIABBDGpBATYCACAAQRRqQQE2AgAgAEHQksAANgIIIABBADYCACAAQRg2AhwgAEH0lcAANgIYIAAgAEEYajYCECAAQfyVwAAQqAIAC0YBAX8jAEEQayICJAAgASgCABAMIQEgAkEIahC9AiAAAn8gASACKAIIIgFFDQAaIAIoAgwLNgIEIAAgATYCACACQRBqJAALUgEBfyMAQSBrIgMkACADQQxqQQE2AgAgA0EUakEANgIAIANB+MvAADYCECADQQA2AgAgAyABNgIcIAMgADYCGCADIANBGGo2AgggAyACEKgCAAtTAQF/IwBBIGsiAiQAIAJBDGpBATYCACACQRRqQQE2AgAgAkGczcAANgIIIAJBADYCACACQYABNgIcIAIgADYCGCACIAJBGGo2AhAgAiABEKgCAAtDAQN/AkAgAkUNAANAIAAtAAAiBCABLQAAIgVGBEAgAEEBaiEAIAFBAWohASACQX9qIgINAQwCCwsgBCAFayEDCyADC0sBAX8jAEEQayICJAAgAkEIaiAAIAFBARCMAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEH4CQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSAEBfyMAQRBrIgIkACACQQhqIAAgARB9AkAgAigCDCIAQYGAgIB4RwRAIABFDQEgAigCCCAAEJsDAAsgAkEQaiQADwsQmAIAC0gBAX8jAEEQayICJAAgAkEIaiAAIAEQfwJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEHwCQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSwEBfyMAQRBrIgMkACADQQhqIAAgASACEIwBAkAgAygCDCIAQYGAgIB4RwRAIABFDQEgAygCCCAAEJsDAAsgA0EQaiQADwsQmAIAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQfS0wABBHBCWAwALIAIgAzYCDCADQQhqQQAgARB6IAJBDGoQrwEgAkEQaiQAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQfS0wABBHBCWAwALIAIgAzYCDCADQQhqQQEgARB6IAJBDGoQrwEgAkEQaiQAC0MBAn8jAEEQayIBJAAgASAAQXhqNgIIIAAtABQgAEEBOgAUIAEgAUEIajYCDEEBcUUEQCABQQxqEOABCyABQRBqJAALSQEBfyMAQRBrIgIkACACQQhqIAAgARCAAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtOAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAEBkhASAEQQhqEL0CIAQoAgwhAiAAIAQoAggiAzYCACAAIAIgASADGzYCBCAEQRBqJAALSQEDfyMAQRBrIgMkACADQQhqIAIQ3gEgAygCCCEEIAAgAygCDCIFNgIEIAAgBDYCACAFIAEgAhChAxogACACNgIIIANBEGokAAtQAQF/QSBBBBD3AiIBRQRAQSBBBBCbAwALIAFCgYCAgBA3AgAgASAAKQIANwIIIAFBEGogAEEIaikCADcCACABQRhqIABBEGopAgA3AgAgAQtFAQJ/IAAtAABBA0YEQCAAKAIEIgEoAgAgASgCBCgCABECACABKAIEIgIoAgQEQCACKAIIGiABKAIAECsLIAAoAgQQKwsLSgEBfyMAQbABayIBJAAgASAAQagBEKEDIgAgADYCrAEgAEGsAWpBkI3AABCnAyAALQCgAUEDRgRAIABBCGoQrAILIABBsAFqJAALSAEBfyAAKAIAIgEEQCABIAAoAgQoAgARAgAgACgCBCIBKAIEBEAgASgCCBogACgCABArCyAAKAIIIABBDGooAgAoAgwRAgALC0gBAX8gACgCACIAKAIAIAAoAggiA2sgAkkEQCAAIAMgAhCEASAAKAIIIQMLIAAoAgQgA2ogASACEKEDGiAAIAIgA2o2AghBAAtIAQF/IAAoAgAiACgCACAAKAIIIgNrIAJJBEAgACADIAIQhQEgACgCCCEDCyAAKAIEIANqIAEgAhChAxogACACIANqNgIIQQALQAECfyAAKAIIIgEEQCAAKAIEIQAgAUECdCEBA0AgACgCACICQSRPBEAgAhAACyAAQQRqIQAgAUF8aiIBDQALCws+AQJ/IwBBEGsiASQAIAFBCGogAEEIaigCACICNgIAIAEgACkCADcDACABKAIEIAIQASABEJoCIAFBEGokAAtPAQF/IAAoAgAiACAAKAIAQX9qIgE2AgACQCABDQAgAEEMaiIBEJUBIAEoAgAEQCABKAIEECsLIAAgACgCBEF/aiIBNgIEIAENACAAECsLC0kBAn8jAEEQayIBJABBAEG0ucAAKAIAEQYAIgAEQCAAKAIAEAMgAUEQaiQADwtB87nAAEHGACABQQhqQby6wABBnLvAABC0AQALRwEBfyMAQZACayIBJAAgASAAQYgCEKEDIgAgADYCjAIgAEGMAmpBpI3AABCnAyAALQCAAkEDRgRA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JAAjAEEQayIAJAAgAEEIaiABEL8CIABBCGoQzgEgAEEQaiQACzMBAX9BNEEEEPcCIgFFBEBBNEEEEJsDAAsgAUKBgICAEDcCACABQQhqIABBLBChAxogAQsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ8CIAEoAggFIAILNgIEIAAgASgCBDYCAAsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ4CIAEoAggFIAILNgIEIAAgASgCBDYCAAsuAQF/IAEoAgAiAgRAIABBATYCCCAAIAI2AgQgACABKAIENgIADwsgAEEANgIICyMBAX8Cf0EBIAEQCUUNABpBAAshAiAAIAE2AgQgACACNgIACzABAX8gAUF4aiICIAIoAgBBAWoiAjYCACACRQRAAAsgAEGst8AANgIEIAAgATYCAAstAQF/IwBBEGsiASQAIAFBCGogAEEIaigCADYCACABIAApAgA3AwAgARCsAQALIwAgACgCAEFwaiIAEJoCIABBDGooAgAiAEEkTwRAIAAQAAsLMQEBf0EEQQQQ9wIiAkUEQEEEQQQQmwMACyACIAE2AgAgAEHMtMAANgIEIAAgAjYCAAsxAQF/QQRBBBD3AiICRQRAQQRBBBCbAwALIAIgATYCACAAQeC0wAA2AgQgACACNgIACycAIAAgACgCBEEBcSABckECcjYCBCAAIAFqIgAgACgCBEEBcjYCBAsmAQF/IwBBEGsiASQAIAEgAEF4ajYCDCABQQxqELUBIAFBEGokAAsmAAJAIABFDQAgACABKAIAEQIAIAEoAgRFDQAgASgCCBogABArCws6AQJ/QfDqwAAtAAAhAUHw6sAAQQA6AABB9OrAACgCACECQfTqwABBADYCACAAIAI2AgQgACABNgIACzQAIABBAzoAICAAQoCAgICABDcCGCAAQQA2AhAgAEEANgIIIABBlJDAADYCBCAAIAE2AgALMgEBfyABKAIAQfe8wABBCyABKAIEKAIMEQUAIQIgAEEAOgAFIAAgAjoABCAAIAE2AgALIAEBfwJAIABBBGooAgAiAUUNACAAKAIARQ0AIAEQKwsLJgEBfyMAQRBrIgMkACADIAE2AgwgAyAANgIIIANBCGogAhD4AQALEwAgACABKQAANwABIABBADoAAAsmAQF/IABBB2oiASAASQRAQeyuwABBM0H4r8AAEIoDAAsgAUEDdgsjAAJAIAFB/P///wdNBEAgACABQQQgAhDoAiIADQELAAsgAAsjACACIAIoAgRBfnE2AgQgACABQQFyNgIEIAAgAWogATYCAAseACAAKAIAIgCtQgAgAKx9IABBf0oiABsgACABEFoLKgACQAJAAkAgAC0AqgEOBAACAgECCyAAQYABahC5AQ8LIABBCGoQrgELCyUAIABFBEBBw7nAAEEwEJYDAAsgACACIAMgBCAFIAEoAhARCwALHQAgACgCACgCACABKAIMQQAgAmtBGGxqQWhqEEMLEQAgACgCAARAIAAoAgQQKwsLIAEBfyAAKAIAIAAoAggiAmsgAUkEQCAAIAIgARD/AQsLIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARCgALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARBAALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARDgALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARFAALIwAgAEUEQEHDucAAQTAQlgMACyAAIAIgAyAEIAEoAhARFQALFwAgASADRgR/IAAgAiABEPkBRQVBAAsLHgAgACABQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIECyEAIABFBEBBw7nAAEEwEJYDAAsgACACIAMgASgCEBEDAAsUACAAKAIABEAgAEEEaigCABArCwsaACAAKAIAKAIAIAEoAgwgAkEEdGtBcGoQQwsdACABKAIARQRAAAsgAEGcsMAANgIEIAAgATYCAAsfACAARQRAQYiywABBMBCWAwALIAAgAiABKAIQEQAACx8AIABFBEBBzLfAAEEwEJYDAAsgACACIAEoAhARAAALHwAgAEUEQEHDucAAQTAQlgMACyAAIAIgASgCEBEBAAsXACAAKAIABEAgABCpAiAAQQxqEKkCCwsfAQF/IAAoAgQgACgCCBABIAAoAgAEQCAAKAIEECsLCx4BAX9B1OrAACEBQdDqwAAoAgAEfyABBSAAEMsBCwsZAQF/IAAoAhAiAQR/IAEFIABBFGooAgALCxkAIAEgAiADEJcCIABBBDoAACAAIAM2AgQLFwAgAEEEaigCACAAQQhqKAIAIAEQnAMLEgBBAEEZIABBAXZrIABBH0YbCxYAIAAgAUEBcjYCBCAAIAFqIAE2AgALFgAgAEEEaigCACAAQQhqKAIAIAEQLwsTAEGo6sAAKAIABEAQmQEQpAILCxcAQcDqwAAoAgBFBEAgABBvC0G86sAACxcAIAAgAjYCCCAAIAE2AgQgACACNgIACxAAIAAgAWpBf2pBACABa3ELEgAgAC0AAEEERwRAIAAQhwILCwwAIAAgASACIAMQLgsLACABBEAgABArCwsPACAAQQF0IgBBACAAa3ILGQAgASgCAEGwzMAAQQsgASgCBCgCDBEFAAsZACABKAIAQbvMwABBDiABKAIEKAIMEQUACxkAIAEoAgBBxOLAAEEFIAEoAgQoAgwRBQALEwAgACgCACgCCCABIAIQlwJBAAsSACABIAIgAxCXAiAAQQQ6AAALCgAgAEEIahCaAgsPACAAKAIABEAgABCvAQsLFAAgACgCACABIAAoAgQoAgwRAQALDwAgACABIAIgAyAEECkACw4AIAAoAgAgARBwGkEACxAAIAAoAgggASACEJcCQQALEAAgACgCACABIAIQlwJBAAsIACAAIAEQSQsRACAAKAIAIAAoAgQgARCcAwsQACAAIAI2AgQgACABNgIACxYAQfTqwAAgADYCAEHw6sAAQQE6AAALEwAgAEHIxMAANgIEIAAgATYCAAsNACAALQAEQQJxQQF2Cw8AIAAgAUEEaikCADcDAAsQACABIAAoAgAgACgCBBAsCw0AIAAgASACEJcCQQALCgBBACAAayAAcQsLACAALQAEQQNxRQsMACAAIAFBA3I2AgQLDQAgACgCACAAKAIEagsNACAAKAIAIAEQWEEACw4AIAAoAgAaA0AMAAsACwwAIAAgASACEMQBAAsMACAAIAEgAhDFAQALDAAgACABIAIQxgEACw0AIAA1AgBBASABEFoLDAAgACABIAIQwQIACw0AIAAoAgAgASACEEcLDQAgACkDAEEBIAEQWgsNACAAMwEAQQEgARBaCw4AIAAoAgAtAAAgARBdCwsAIAAjAGokACMACwoAIAAgASACEDsLCwAgACACIAEQoQELBwAgABCaAgsNACABQZCQwABBAhAsCwsAIAAoAgAgARBKCwsAIAAgAUHZABAiCwkAIAAgARAhAAsKACAAKAIEQXhxCwoAIAAoAgRBAXELCgAgACgCDEEBcQsKACAAKAIMQQF2CxoAIAAgAUH46sAAKAIAIgBB7QAgABsRAAAACwoAIAIgACABECwLDAAgACABKQIANwMACwwAIAAgASkCCDcDAAsNACABQcTQwABBAhAsCwsAIAAoAgAgARBbCwoAIAAgASACEFkLCwAgACABIAIQlgELCgAgACABIAIQNQsHACAAEMEBCwkAIABBBDoAAAsJACAAQQA2AgALCAAgACABEBoLBwAgACABagsHACAAIAFrCwcAIABBCGoLBwAgAEF4agsHACAAENsBCwcAIAAQjgILBABBAQsMAEK52M2vmbD740ALDQBCyLXgz8qG29OJfwsMAEKCmOfjkpTcsV4LDABCmcDi9+TewpMdCwMAAQsDAAELC8FpBABBgIDAAAuQUwEAAAAEAAAABAAAAAIAAAADAAAAAwAAAAEAAAAEAAAABAAAAAQAAAAFAAAABQAAAP//////////YHVud3JhcF90aHJvd2AgZmFpbGVkAAAABgAAAAwAAAAEAAAABwAAAAYAAAAMAAAABAAAAAgAAAAHAAAAUAAQAAkAAAAKAAAACwAAAAkAAAAMAAAAZmFpbGVkIHRvIGZpbGwgYnVmZmVyZmFpbGVkIHRvIGZpbGwgd2hvbGUgYnVmZmVyoQAQABsAAAAlAAAAL3J1c3RjL2JkYjA3YThlYzhlNzdhYTEwZmI4NGZhZTFkNGZmNzFjMjExODBiYjQvbGlicmFyeS9zdGQvc3JjL2lvL2ltcGxzLnJzAMgAEABLAAAA8gAAAA0AAAAvcnVzdGMvYmRiMDdhOGVjOGU3N2FhMTBmYjg0ZmFlMWQ0ZmY3MWMyMTE4MGJiNC9saWJyYXJ5L3N0ZC9zcmMvaW8vY3Vyc29yLnJzJAEQAEwAAADrAAAACgAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy9pby9yZWFkYnVmLnJzAAAAgAEQAE0AAAAhAQAAKwAAAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUADQAAAAAAAAABAAAADgAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAAAcAhAAYQAAAC0AAAAaAAAAHAIQAGEAAAA3AAAARAAAABwCEABhAAAAOgAAACcAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzsAIQAFgAAAC2AAAAIAAAALACEABYAAAAtwAAACUAAACwAhAAWAAAAPwAAAAcAAAAsAIQAFgAAAD9AAAAIQAAALACEABYAAAAEwEAAC4AAACwAhAAWAAAABMBAAAJAAAAsAIQAFgAAAAUAQAACQAAALACEABYAAAACwEAAC4AAACwAhAAWAAAAAsBAAAJAAAAsAIQAFgAAAANAQAADwAAALACEABYAAAADAEAAAkAAACwAhAAWAAAAA8BAAAJAAAAsAIQAFgAAACgAAAAKgAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy9pby9tb2QucnMAAADYAxAASQAAAFMBAAAYAAAAc3RyZWFtIGRpZCBub3QgY29udGFpbiB2YWxpZCBVVEYtOAAANAQQACIAAAAVAAAA2AMQAEkAAACHAQAAGwAAAGZhaWxlZCB0byB3cml0ZSB3aG9sZSBidWZmZXJ0BBAAHAAAABcAAAAPAAAADAAAAAQAAAAQAAAAEQAAABIAAABmb3JtYXR0ZXIgZXJyb3IAtAQQAA8AAAAoAAAA2AMQAEkAAAAkBQAAFgAAANgDEABJAAAAKAUAAA0AAABhZHZhbmNpbmcgaW8gc2xpY2VzIGJleW9uZCB0aGVpciBsZW5ndGgA8AQQACcAAADYAxAASQAAACYFAAANAAAAL3J1c3RjL2JkYjA3YThlYzhlNzdhYTEwZmI4NGZhZTFkNGZmNzFjMjExODBiYjQvbGlicmFyeS9zdGQvc3JjL2lvL3JlYWRidWYucnMAAAAwBRAATQAAAMsAAAA2AAAAEwAAAAQAAAAEAAAAFAAAABUAAAAWAAAAGgAAAAwAAAAEAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAAC9ob21lL25nbml1cy9Eb2N1bWVudHMvZ2l0LXJlcG9zL3VzZHBsLXJzL3VzZHBsLWNvcmUvc3JjL3NlcmRlcy90cmFpdHMucnMAAADQBRAASQAAAHYAAAAcAAAAIgAAABgAAAAIAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAABgdW53cmFwX3Rocm93YCBmYWlsZWQAAAArAAAAYAEAAAgAAAAsAAAALQAAACACAAAIAAAALgAAAC8AAAAEAAAABAAAADAAAAAxAAAALwAAAAQAAAAEAAAAMgAAADMAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvd2FzbS1iaW5kZ2VuLWZ1dHVyZXMtMC40LjMzL3NyYy9saWIucnMAuAYQAGMAAADaAAAAFQAAAAAAAABgYXN5bmMgZm5gIHJlc3VtZWQgYWZ0ZXIgY29tcGxldGlvbgA0AAAAY2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAALwAAAAAAAAABAAAANQAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMAsAcQAE8AAACmAQAACQAAACgpAAAaAAAADAAAAAQAAAA2AAAANwAAADgAAABhIERpc3BsYXkgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IgdW5leHBlY3RlZGx5AC8AAAAAAAAAAQAAADkAAAAvcnVzdGMvYmRiMDdhOGVjOGU3N2FhMTBmYjg0ZmFlMWQ0ZmY3MWMyMTE4MGJiNC9saWJyYXJ5L2FsbG9jL3NyYy9zdHJpbmcucnMAdAgQAEsAAADoCQAACQAAAC8AAAAEAAAABAAAADoAAAA7AAAAPAAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUALwAAAAAAAAABAAAAPQAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAAJAkQACoAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzWAkQAFgAAADSAQAAHwAAAFgJEABYAAAA2AEAAB8AAABYCRAAWAAAAOEBAAAfAAAAWAkQAFgAAADqAQAAHwAAAFgJEABYAAAA8wEAAB8AAABYCRAAWAAAAPwBAAAfAAAAWAkQAFgAAAAFAgAAHwAAAFgJEABYAAAADgIAAB8AAABYCRAAWAAAAAMBAAAkAAAAWAkQAFgAAAAEAQAAKQAAAFgJEABYAAAAKgEAABYAAABYCRAAWAAAAC0BAAAaAAAAWAkQAFgAAABBAQAADgAAAFgJEABYAAAARAEAABIAAABYCRAAWAAAAFgBAAATAAAASW1wb3NzaWJsZTogbXVzdCBvbmx5IGhhdmUgMCB0byA4IGlucHV0IGJ5dGVzIGluIGxhc3QgY2h1bmssIHdpdGggbm8gaW52YWxpZCBsZW5ndGhzoAoQAFQAAABYCRAAWAAAAJ0BAAAOAAAAWAkQAFgAAACxAQAACQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgb3V0cHV0IGJ1ZmZlciBsZW5ndGgAAFgJEABYAAAAlgAAAAoAAABYCRAAWAAAAJsAAAAhAAAAV3JpdGluZyB0byBhIFN0cmluZyBzaG91bGRuJ3QgZmFpbC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9lbmNvZGUucnMAAI4LEABYAAAAUwAAAA4AAAD//////////3VzZHBsLWZyb250L3NyYy9jb25uZWN0aW9uLnJzAAAAAAwQAB0AAAAZAAAAJgAAAFBPU1RodHRwOi8vdXNkcGwuOi91c2RwbC9jYWxsAAAANAwQAAwAAABADBAAAQAAAEEMEAABAAAAQgwQAAsAAABsb2NhbGhvc3QAAABwDBAACQAAAAAMEAAdAAAALQAAACQAAAAADBAAHQAAADQAAAAnAAAAAAwQAB0AAABJAAAAJgAAAEV4cGVjdGVkIGNhbGwgcmVzcG9uc2UgbWVzc2FnZSwgZ290IHNvbWV0aGluZyBlbHNldXNkcGwtZnJvbnQvc3JjL2NvbnZlcnQucnPmDBAAGgAAACAAAAAnAAAAMC45LjB1c2RwbC1mcm9udC9zcmMvbGliLnJzABUNEAAWAAAAYgAAABgAAAAVDRAAFgAAAGoAAAAYAAAAFQ0QABYAAABxAAAATgAAABUNEAAWAAAAcAAAAAEAAAAVDRAAFgAAAKAAAAAmAAAAFQ0QABYAAACfAAAAAQAAABUNEAAWAAAAxAAAAEAAAAAVDRAAFgAAANIAAABAAAAAY3JhbmtzaGFmdAAArA0QAAoAAABkZWNreQAAAMANEAAFAAAAYW55ANANEAADAAAATG9hZEVycm9yOiBJbygpANwNEAAOAAAA6g0QAAEAAABMb2FkRXJyb3I6IEludmFsaWREYXRhAAD8DRAAFgAAAExvYWRFcnJvcjogVG9vU21hbGxCdWZmZXIAAAAcDhAAGQAAAER1bXBFcnJvcjogSW8oAABADhAADgAAAOoNEAABAAAARHVtcEVycm9yOiBVbnN1cHBvcnRlZAAAYA4QABYAAABEdW1wRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAgA4QABkAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzpA4QAFgAAAA7AQAACQAAACEiIyQlJicoKSorLC0wMTIzNDU2Nzg5QEFCQ0RFRkdISUpLTE1OUFFSU1RVVlhZWltgYWJjZGVoaWprbG1wcXJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSssLi9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL////////////////////////////////////////////wABAgMEBQYHCAkKCwz//w0ODxAREhMUFRb///////8XGBkaGxwdHh8gISIjJCX/JicoKSorLP8tLi8w/////zEyMzQ1Nv//Nzg5Ojs8//89Pj//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pj////80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABNjc4OTo7PD0+P/////////8CAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG////////xwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0wQEAAMEBAAzA8QAIwPEABMDxAADA8QAIwVEACMFBAAjBMQAIwSEACMERAAjBAQAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAPwAAAAgAAAAEAAAAQAAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAAD4FhAAYQAAAGgAAAAwAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBudW1iZXIgb2YgY2h1bmtzIGluIGlucHV0L2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5ycwCfFxAAWAAAALwAAAAKAAAAQQAAAAgAAAAEAAAAQgAAAEMAAABBAAAACAAAAAQAAABEAAAAYm9keW1ldGhvZG1vZGVzYW1lLW9yaWdpbm5vLWNvcnNjb3JzbmF2aWdhdGVhdHRlbXB0ZWQgdG8gY29udmVydCBpbnZhbGlkIFJlcXVlc3RNb2RlIGludG8gSlNWYWx1ZS9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93ZWItc3lzLTAuMy42MC9zcmMvZmVhdHVyZXMvZ2VuX1JlcXVlc3RNb2RlLnJzjRgQAGsAAAADAAAAAQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeUgAAAAEAAAABAAAAEkAAABKAAAAYWxyZWFkeSBib3Jyb3dlZEsAAAAAAAAAAQAAAEwAAABhbHJlYWR5IG11dGFibHkgYm9ycm93ZWRLAAAAAAAAAAEAAABNAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvcXVldWUucnMAAACUGRAAZQAAABoAAAAuAAAAlBkQAGUAAAAdAAAAKQAAAJQZEABlAAAAMgAAABoAAABhbHJlYWR5IGJvcnJvd2VkTgAAAAAAAAABAAAATAAAAE8AAAAEAAAABAAAAFAAAABRAAAATwAAAAQAAAAEAAAAUgAAAFMAAABGbk9uY2UgY2FsbGVkIG1vcmUgdGhhbiBvbmNlL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvbGliLnJzAJAaEABjAAAApQAAAA8AAACQGhAAYwAAAIUAAAAnAAAAkBoQAGMAAACvAAAAJAAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93YXNtLWJpbmRnZW4tZnV0dXJlcy0wLjQuMzMvc3JjL3Rhc2svc2luZ2xldGhyZWFkLnJzAAAAJBsQAHEAAAAhAAAAFQAAAFQAAABVAAAAVgAAAFcAAABYAAAAJBsQAHEAAABVAAAAJQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeWNhbm5vdCBhY2Nlc3MgYSBUaHJlYWQgTG9jYWwgU3RvcmFnZSB2YWx1ZSBkdXJpbmcgb3IgYWZ0ZXIgZGVzdHJ1Y3Rpb24AAFoAAAAAAAAAAQAAADUAAAAvcnVzdGMvYmRiMDdhOGVjOGU3N2FhMTBmYjg0ZmFlMWQ0ZmY3MWMyMTE4MGJiNC9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAFQcEABPAAAApgEAAAkAAABbAAAAcmV0dXJuIHRoaXNjbG9zdXJlIGludm9rZWQgcmVjdXJzaXZlbHkgb3IgZGVzdHJveWVkIGFscmVhZHljYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAAAAaAAAAAAAAAABAAAANQAAAC9ydXN0Yy9iZGIwN2E4ZWM4ZTc3YWExMGZiODRmYWUxZDRmZjcxYzIxMTgwYmI0L2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMATB0QAE8AAACmAQAACQAAAFRyaWVkIHRvIHNocmluayB0byBhIGxhcmdlciBjYXBhY2l0eawdEAAkAAAAL3J1c3RjL2JkYjA3YThlYzhlNzdhYTEwZmI4NGZhZTFkNGZmNzFjMjExODBiYjQvbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc9gdEABMAAAAqgEAAAkAAABuAAAABAAAAAQAAABvAAAAcAAAAHEAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlQWNjZXNzRXJyb3IAAEweEAAAAAAAdW5jYXRlZ29yaXplZCBlcnJvcm90aGVyIGVycm9yb3V0IG9mIG1lbW9yeXVuZXhwZWN0ZWQgZW5kIG9mIGZpbGV1bnN1cHBvcnRlZG9wZXJhdGlvbiBpbnRlcnJ1cHRlZGFyZ3VtZW50IGxpc3QgdG9vIGxvbmdpbnZhbGlkIGZpbGVuYW1ldG9vIG1hbnkgbGlua3Njcm9zcy1kZXZpY2UgbGluayBvciByZW5hbWVkZWFkbG9ja2V4ZWN1dGFibGUgZmlsZSBidXN5cmVzb3VyY2UgYnVzeWZpbGUgdG9vIGxhcmdlZmlsZXN5c3RlbSBxdW90YSBleGNlZWRlZHNlZWsgb24gdW5zZWVrYWJsZSBmaWxlbm8gc3RvcmFnZSBzcGFjZXdyaXRlIHplcm90aW1lZCBvdXRpbnZhbGlkIGRhdGFpbnZhbGlkIGlucHV0IHBhcmFtZXRlcnN0YWxlIG5ldHdvcmsgZmlsZSBoYW5kbGVmaWxlc3lzdGVtIGxvb3Agb3IgaW5kaXJlY3Rpb24gbGltaXQgKGUuZy4gc3ltbGluayBsb29wKXJlYWQtb25seSBmaWxlc3lzdGVtIG9yIHN0b3JhZ2UgbWVkaXVtZGlyZWN0b3J5IG5vdCBlbXB0eWlzIGEgZGlyZWN0b3J5bm90IGEgZGlyZWN0b3J5b3BlcmF0aW9uIHdvdWxkIGJsb2NrZW50aXR5IGFscmVhZHkgZXhpc3RzYnJva2VuIHBpcGVuZXR3b3JrIGRvd25hZGRyZXNzIG5vdCBhdmFpbGFibGVhZGRyZXNzIGluIHVzZW5vdCBjb25uZWN0ZWRjb25uZWN0aW9uIGFib3J0ZWRuZXR3b3JrIHVucmVhY2hhYmxlaG9zdCB1bnJlYWNoYWJsZWNvbm5lY3Rpb24gcmVzZXRjb25uZWN0aW9uIHJlZnVzZWRwZXJtaXNzaW9uIGRlbmllZGVudGl0eSBub3QgZm91bmQgKG9zIGVycm9yICkAAABMHhAAAAAAAHkhEAALAAAAhCEQAAEAAABtZW1vcnkgYWxsb2NhdGlvbiBvZiAgYnl0ZXMgZmFpbGVkCgCgIRAAFQAAALUhEAAOAAAAbGlicmFyeS9zdGQvc3JjL2FsbG9jLnJz1CEQABgAAABVAQAACQAAAGxpYnJhcnkvc3RkL3NyYy9wYW5pY2tpbmcucnP8IRAAHAAAAD4CAAAPAAAA/CEQABwAAAA9AgAADwAAAHIAAAAMAAAABAAAAHMAAABuAAAACAAAAAQAAAB0AAAAdQAAABAAAAAEAAAAdgAAAHcAAABuAAAACAAAAAQAAAB4AAAAeQAAAG4AAAAAAAAAAQAAAHoAAABvcGVyYXRpb24gc3VjY2Vzc2Z1bA4AAAAQAAAAFgAAABUAAAALAAAAFgAAAA0AAAALAAAAEwAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABEAAAASAAAAEAAAABAAAAATAAAAEgAAAA0AAAAOAAAAFQAAAAwAAAALAAAAFQAAABUAAAAPAAAADgAAABMAAAAmAAAAOAAAABkAAAAXAAAADAAAAAkAAAAKAAAAEAAAABcAAAAZAAAADgAAAA0AAAAUAAAACAAAABsAAAATHxAAAx8QAO0eEADYHhAAzR4QALceEACqHhAAnx4QAIweEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABpIRAAaSEQAGkhEABYIRAARiEQADYhEAAmIRAAEyEQAAEhEAD0IBAA5iAQANEgEADFIBAAuiAQAKUgEACQIBAAgSAQAHMgEABgIBAAOiAQAAIgEADpHxAA0h8QAMYfEAC9HxAAsx8QAKMfEACMHxAAcx8QAGUfEABYHxAARB8QADwfEAAhHxAASGFzaCB0YWJsZSBjYXBhY2l0eSBvdmVyZmxvd6QkEAAcAAAAL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvaGFzaGJyb3duLTAuMTIuMy9zcmMvcmF3L21vZC5ycwDIJBAATwAAAFoAAAAoAAAAewAAAAQAAAAEAAAAfAAAAH0AAAB+AAAAbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc2NhcGFjaXR5IG92ZXJmbG93AAAAXCUQABEAAABAJRAAHAAAAAYCAAAFAAAAYSBmb3JtYXR0aW5nIHRyYWl0IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yAHsAAAAAAAAAAQAAADkAAABsaWJyYXJ5L2FsbG9jL3NyYy9mbXQucnPMJRAAGAAAAGQCAAAJAAAA77+9AGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUpLi4AACQmEAACAAAAQm9ycm93RXJyb3JCb3Jyb3dNdXRFcnJvcgBpbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIEomEAAgAAAAaiYQABIAAACEAAAAAAAAAAEAAACFAAAA+CUQAAAAAABgOiAA+CUQAAAAAAClJhAAAgAAAIQAAAAMAAAABAAAAIYAAACHAAAAiAAAACAgICAgewosCiwgIHsgfSB9KAooLAAAAIQAAAAEAAAABAAAAIkAAABsaWJyYXJ5L2NvcmUvc3JjL2ZtdC9udW0ucnMA+CYQABsAAABlAAAAFAAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTkAAIQAAAAEAAAABAAAAIoAAACLAAAAjAAAAGxpYnJhcnkvY29yZS9zcmMvZm10L21vZC5ycwAIKBAAGwAAAHoJAAAeAAAACCgQABsAAACBCQAAFgAAACgpbGlicmFyeS9jb3JlL3NyYy9zbGljZS9tZW1jaHIucnMAAEYoEAAgAAAAaAAAACcAAAByYW5nZSBzdGFydCBpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggeCgQABIAAACKKBAAIgAAAHJhbmdlIGVuZCBpbmRleCC8KBAAEAAAAIooEAAiAAAAc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCAA3CgQ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"; +const encoded = "AGFzbQEAAAABtwEbYAJ/fwBgAn9/AX9gAX8AYAN/f38AYAR/f39/AGADf39/AX9gAX8Bf2AAAGAAAX9gBX9/f39/AGAEf39/fwF/YAV/f39/fwF/YAF/AX5gA39/fwF+YAR/fn9/AGAGf39/f39/AX9gBn9/f39/fwBgBX9/fn9/AGAFf399f38AYAV/f3x/fwBgBH99f38AYAR/fH9/AGACfn8AYAd/f39/f39/AX9gA35/fwF/YAF8AX9gAn9/AX4CqgkjA3diZxpfX3diaW5kZ2VuX29iamVjdF9kcm9wX3JlZgACA3diZxVfX3diaW5kZ2VuX3N0cmluZ19uZXcAAQN3YmcVX193YmluZGdlbl9zdHJpbmdfZ2V0AAADd2JnG19fd2JpbmRnZW5fb2JqZWN0X2Nsb25lX3JlZgAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9uZXcAGQN3YmcWX193YmluZGdlbl9ib29sZWFuX2dldAAGA3diZxVfX3diaW5kZ2VuX251bWJlcl9nZXQAAAN3YmcSX193YmluZGdlbl9pc19udWxsAAYDd2JnF19fd2JpbmRnZW5faXNfdW5kZWZpbmVkAAYDd2JnKF9fd2JnX2luc3RhbmNlb2ZfV2luZG93X2FjYzk3ZmY5ZjVkMmM3YjQABgN3YmccX193YmdfZmV0Y2hfMGZlMDQ5MDVjY2NmYzJhYQABA3diZypfX3diZ19pbnN0YW5jZW9mX1Jlc3BvbnNlX2VhYTQyNjIyMDg0OGEzOWUABgN3YmcbX193YmdfdGV4dF8xMTY5ZDc1MmNjNjk3OTAzAAYDd2JnKF9fd2JnX25ld3dpdGhzdHJhbmRpbml0XzA1ZDcxODA3ODg0MjBjNDAABQN3YmcSX193YmluZGdlbl9jYl9kcm9wAAYDd2JnIF9fd2JnX25ld25vYXJnc19iNWIwNjNmYzZjMmYwMzc2AAEDd2JnG19fd2JnX2NhbGxfOTdhZTlkODY0NWRjMzg4YgABA3diZxpfX3diZ19uZXdfMGI5YmZkZDk3NTgzMjg0ZQAIA3diZxRfX3diaW5kZ2VuX2lzX3N0cmluZwAGA3diZxtfX3diZ19zZWxmXzZkNDc5NTA2ZjcyYzZhNzEACAN3YmcdX193Ymdfd2luZG93X2YyNTU3Y2M3ODQ5MGFjZWIA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hsAAEMMBAAsgBiAIQfCGwAAQwwEACyAHQQhqIARqIAUgBmotAAA6AAAgACAIaiEACwJAIA9FIAsgAklyDQAgAEGBCEkEQCACIAdBCGogAGpBgAggAGsQ4QEgAGohAAwBCyAAQYAIQeiEwAAQhgMACyAAQYEITw0CIAshBCADIAdBCGogABDfAUUNAQsLIAdBoAhqJAAgEA8LIABBgAhB+ITAABCHAwALQbiDwABBKyAHQZgIakHkg8AAQaCHwAAQtAEAC80NAgd/AX4jAEHgAmsiAiQAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAALQCYBEEBaw4DCQIBAAsgACAAQYgCakGIAhCiAxoLAkACQAJAAkAgAC0AgAJBAWsOAw0EAAELIABB7AFqIQYgAC0A7AFBAWsOAwcDAgELIAAoAvABIQMgAiAAQfQBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEgaiACQThqELICIAJBKGogAigCICACKAIkEOUCIAAoAvgBIQMgAiAAQfwBaigCACIENgJAIAIgAzYCPCACIAQ2AjggAkEYaiACQThqELECIAIoAhghBSACKAIcIQQgAkGUAmogAkEwaigCADYCACACIAIpAyg3AowCIAAgAkE4akHgARCiAyIDIAQ2AugBIAMgBTYC5AEgAyAENgLgASADQQA6AOwBIANB7AFqIQYLIAAgACkC1AE3ArABIAAgACkC4AE3ArwBIABBuAFqIABB3AFqKAIANgIAIABBxAFqIgMgAEHoAWooAgAiBDYCAEGw68AAQbDrwAApAwAiCUIBfDcDACACQRBqIAQQngEgAigCECEEIABB0AFqQQA2AgAgAEHMAWogAigCFDYCACAAIAQ2AsgBIAMoAgAhBSAAKAK8ASEEIAIgAEHAAWooAgAiAzYCpAIgAiADIAVBAnRqNgKgAiACIAM2ApwCIAIgBDYCmAIgAEHIAWohBCAFBEADQCACIANBBGo2ApwCIAJBOGogAygCABBCIAAoAtABIgMgACgCyAFGBEAgBCADEPwBIAAoAtABIQMLIAAoAswBIANBBHRqIgMgAikDODcDACADQQhqIAJBQGspAwA3AwAgACAAKALQAUEBajYC0AEgAigCnAIiAyACKAKgAkcNAAsLIAJBmAJqEMcBQbjrwAAvAQAhAyACQThqIABBsAFqENEBIABBmAFqIAJBQGsoAgA2AgAgACACKQM4NwOQASAAIAQpAgA3ApwBIABBpAFqIARBCGooAgA2AgAgAEEAOgCqASAAIAM7AagBIAAgCTcDiAEgAEEANgKAASAAIAk3AwAgAEGqAWohBAwDCyAAQaoBaiEEIAAtAKoBQQFrDgMIAAMBCwALIAAvAagBIQMgACkDACEJCyACQUBrIABBgAFqQSgQogMaIABBEGogAkE4akEwEKIDGiAAQegAakEAOgAAIABB5ABqIAM7AQAgACAJNwMICyACQThqIABBCGoiBSABECcgAigCOCIBQQtGDQIgAkHIAmogAkHIAGopAwA3AwAgAkHQAmoiAyACQdAAaikDADcDACACQdgCaiIGIAJB2ABqKQMANwMAIAIgAikDQDcDwAIgAigCPCEEIAUQrgEgAUEKRwRAIAJBuAJqIAYpAwA3AwAgAkGwAmogAykDADcDACACQagCaiACQcgCaikDADcDACACIAIpA8ACNwOgAiACIAQ2ApwCIAIgATYCmAIgAUEBRg0CQeyawABBMhABIQQgAkGYAmoQugELIABBAToAqgEgABDHAgwHC0GAkMAAQSNBhJzAABD3AQALIAJBsAJqKAIAIQEgAkGsAmooAgAhAyACQagCaigCACEEIABBAToAqgEgABDHAiADRQ0FIAIgARAXNgLAAiACIAM2AqQCIAIgAyABQQR0IgVqNgKgAiACIAM2ApwCIAIgBDYCmAIgAUUNBEEAIQQgAkE4akEBciIGQQdqIQcDQCACIANBEGoiATYCnAIgAy0AACIIQQpGDQUgBiADKQABNwAAIAcgA0EIaikAADcAACACIAg6ADggAkE4ahBeIQMgAkHAAmooAgAgBCADEBggBEEBaiEEIAEhAyAFQXBqIgUNAAsMBAsgBkEDOgAAIARBAzoAAEEBDAYLQYCQwABBI0Hkj8AAEPcBAAtBgJDAAEEjQdyawAAQ9wEAC0GAkMAAQSNBlJzAABD3AQALIAJBmAJqELIBIAIoAsACIQUMAQtBISEFIARBJEkNACAEEAALIABBsAFqEJoCIABBAToA7AFBAAsiAQRAQQMhBCAAQQM6AIACDAELIAAQlgIgAEEBOgCAAiACIAU2AiggAkEgNgI4IAJBCGogAEGQBGoiAyACQThqIAJBKGoQhAIgAigCCEUEQCACKAIMIgRBI0sEQCAEEAALIAIoAjgiBEEkTwRAIAQQAAsgAigCKCIEQSRPBEAgBBAACyADKAIAIgNBJE8EQCADEAALQQEhBCAAKAKUBCIDQSRJDQEgAxAADAELQbiAwABBFRCWAwALIAAgBDoAmAQgAkHgAmokACABQQBHC5IMAQV/IwBBkAJrIgMkACABAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCABLQBgQQFrDgQHAAIDAQsACyABIAEpAwA3AwggA0HIAGogAUEQakEoEKIDGiABIAEvAVw7AV4gARARNgI4IAFBOGoiBBDAASAEEMIBIANBpAFqQRk2AgAgA0GcAWpBGjYCACADIAFB3gBqNgKgASADQbSawAA2ApgBIANBGzYClAEgAyABQQhqNgKQASADQQM2AswBIANBBDYCxAEgA0GImsAANgLAASADQQA2ArgBIAMgA0GQAWo2AsgBIANBgAFqIANBuAFqEEEgAUHEAGogA0GIAWooAgA2AgAgASADKQOAATcCPCADQbgBaiADQcgAakEoEKIDGiADQZABaiADQbgBahCBASADKAKQASEFIAMoApQBIgZFDQsgAUHQAGogAygCmAEiBzYCACABQcwAaiAGNgIAIAEgBTYCSCADQZABaiAGIAcQNyADQcABaiIFIANBmAFqKQMANwMAIAMgAykDkAE3A7gBIANB8ABqIANBuAFqEL0BIAUgA0H4AGooAgA2AgAgAyADKQNwNwO4ASADIANBuAFqEIwCNgKQASAEIANBkAFqELABIAMoApABIgVBJE8EQCAFEAALIANBQGsgAUFAaygCACABQcQAaigCACAEEPMBIAMoAkQhBSADKAJADQogASAFNgJUIANBOGoQ7QEgAygCOEUNBiABIAMoAjw2AlggASABQdgAaigCACABQdQAaigCABAKEEg2AmgLIANBMGogAUHoAGoiBCACEI0BIAMoAjAiBkECRg0GIAMoAjQhBSAEEK8BIAYNCCADQShqIAUQ8gEgAygCLCEFIAMoAigNCCABIAU2AmggA0EgaiAEEPYBIAMoAiAhBCABQfQAaiADKAIkIgU2AgAgASAENgJwIAQNASABIAUQSDYCbAsgA0EYaiABQewAaiIEIAIQjQEgAygCGCICQQJGDQEgAygCHCEFIAQQrwEgAg0AIANBEGogBRDxASADKAIUIQQgAygCEEUNAiAEIQULIAEoAmgiAkEkSQ0GIAIQAAwGCyAAQQs2AgBBBAwKCyADQQhqIAQQAiADKAIIIgVFBEAgA0EANgK8AQwECyADKAIMIQIgAyAFNgK8ASADIAI2AsABIAMgAjYCuAEgAyADQbgBahCyAiADQbgBaiADKAIAIAMoAgQQ5QIgAygCvAFFDQMgA0GIAWogA0HAAWoiBigCACICNgIAIAMgAykDuAE3A4ABIANBuAFqIAMoAoQBIAIQmgEgAygCuAEiAkEKRwRAIAMoArwBIQUgA0GQAWogBkEoEKIDGiADQfABaiADQZgBaikDADcDACADQfgBaiADQaABaikDADcDACADQYACaiADQagBaikDADcDACADIAMpA5ABNwPoASADQYABahCaAiAEQSRPBEAgBBAACyABKAJoIgRBJE8EQCAEEAALIAEoAlgiBEEkTwRAIAQQAAsgASgCVCIEQSRPBEAgBBAACyABQcgAahCaAiABQTxqEJoCIAEoAjgiAUEkSQ0JIAEQAAwJCyADIAMpArwBNwOIAiADQYgCahCpASEFIANBgAFqEJoCIARBJE8EQCAEEAALIAEoAmgiAkEkTwRAIAIQAAsgASgCWCICQSRPBEAgAhAACyABKAJUIgJBJE8EQCACEAALIAFByABqEJoCIAFBPGoQmgIgASgCOCIBQSRJDQcgARAADAcLQYCQwABBI0HYmcAAEPcBAAtBoJPAAEErQbyawAAQ9wEACyAAQQs2AgBBAwwGC0Ggk8AAQStBzJrAABD3AQALIAEoAlgiAkEkTwRAIAIQAAsgASgCVCICQSRJDQAgAhAACyABQcgAahCaAgsgAUE8ahCaAiABKAI4IgFBJEkNACABEAALQQohAgsgACAFNgIEIAAgAjYCACAAIAMpA+gBNwMIIABBEGogA0HwAWopAwA3AwAgAEEYaiADQfgBaikDADcDACAAQSBqIANBgAJqKQMANwMAQQELOgBgIANBkAJqJAAL4gsCCn8CfiMAQeACayICJAACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAC0A2AJBAWsOAwcCAQALIAAgAEGoAWpBqAEQogMaCwJAIAAtAKABQQFrDgMFAQACCyAAQQhqIQUgAEGYAWotAABBAWsOAwcAAwILAAsgACgCACEDIAIgACgCBCIENgJQIAIgAzYCTCACIAQ2AkggAkEwaiACQcgAahCyAiACQThqIAIoAjAgAigCNBDlAiACQdQBaiACQUBrKAIANgIAIAIgAikDODcCzAEgAEEIaiIFIAJByABqQZABEKIDGiAAQZgBakEAOgAACyAAQYgBaiAAQZQBaigCADYCACAAQYABaiIDIABBjAFqKQIANwIAQbDrwABBsOvAACkDACIMQgF8NwMAIAJBhAJqIAMQ0QEgAEEYakEJNgIAIAAgDDcDCCAAQegAakEAOgAAIABBHGogAikChAI3AgAgAEEkaiACQYwCaigCADYCACAAQeQAakG468AALwEAOwEACyACQcgAaiAFIAEQJyACKAJIQQtGDQIgAkHYAWogAkHIAGpBKBCiAxogBRCuAQJAAkAgAigC2AEiB0F4ag4DAQYABgsgAigC3AEhAUH868AAKAIABEAQ4wILQfzrwABBADYCACABQSRJDQggARAADAgLIAJB4AFqKAIAIQEgAkHkAWooAgAhAyACKALcASEGIAJBIGoQ5wEgAikDICEMIAIpAyghDSACQcgAaiADEGogAkGoAmoiCCACQdAAaiIJKQMANwMAIAIgAikDSDcDoAIgAiANNwOYAiACIAw3A5ACIAIgATYCVCACIAEgA0EYbCIEajYCUCACIAE2AkwgAiAGNgJIIANFDQUgAkHYAmohBgNAIAIgAUEYaiIDNgJMIAEoAgQiCkUNBiABKAIAIQsgAiABKAIINgLIAiACIAo2AsQCIAIgCzYCwAIgBiABQRRqKAIANgIAIAIgASkCDDcD0AIgAkGwAmogAkGQAmogAkHAAmogAkHQAmoQSyACKAK0AgRAIAJBsAJqEKYCIAJBsAJqEMoCCyADIQEgBEFoaiIEDQALDAULQYCQwABBI0G0nMAAEPcBAAtBgJDAAEEjQeSPwAAQ9wEAC0EDIQQgAEEDOgCgASAAQQM6AJgBQQEhAQwFC0GAkMAAQSNBpJzAABD3AQALQfzrwAAoAgAEQBDjAgtB/OvAAEEANgIAQQEhAQwBCyACQcgAahC8ASACQeAAaiAIKQMANwMAIAJB2ABqIgMgAkGgAmopAwA3AwAgCSACQZgCaikDADcDACACIAIpA5ACNwNIQQAhAUH8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f0wNAiACQQEQ9wIiAUUNAQsgA0EANgJAIAMgATYCPCADIAI2AjggBCACSwR/IANBOGpBACAEEIUBIAMoAkAhBSADKAI8BSABCyAFaiAGIAQQogMaIAMgBCAFaiICNgJAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEQazNwAAvAAAiBTsAACAEQQJqQa7NwAAtAAAiBjoAACADIAJBA2oiAjYCQCADIAMpAzA3A0ggA0HQAGogA0HIAGoQPiADKAJQBEADQCADQegAaiADQdgAaikDADcDACADIAMpA1A3A2AgA0EQaiADQeAAahCdAyADKAIQIQcgAygCOCACayADKAIUIgRJBEAgA0E4aiACIAQQhQEgAygCQCECIAMoAjwhAQsgASACaiAHIAQQogMaIAMgAiAEaiICNgJAIANBCGogA0HgAGoQngMgAygCDARAIAMoAjggAmtBAk0EQCADQThqIAJBAxCFASADKAJAIQILIAMoAjwiASACaiIEIAU7AAAgBEECaiAGOgAAIAMgAkEDaiICNgJACyADQdAAaiADQcgAahA+IAMoAlANAAsLIAAgAykDODcCBCAAQQE2AgAgAEEMaiADQUBrKAIANgIADAMLIAJBARCbAwALEJgCAAsgAEH4y8AANgIEIABBADYCACAAQQhqQQA2AgALIANB8ABqJAAL0AQCBH8GfiAAIAAoAjggAmo2AjgCQCAAAn8CQAJAAkAgACgCPCIFRQRADAELAn4gAkEIIAVrIgQgAiAESRsiBkEDTQRAQgAMAQtBBCEDIAE1AAALIQcgACAAKQMwIANBAXIgBkkEQCABIANqMwAAIANBA3SthiAHhCEHIANBAnIhAwsgAyAGSQR+IAEgA2oxAAAgA0EDdK2GIAeEBSAHCyAFQQN0QThxrYaEIgc3AzAgBCACSw0BIAAgACkDGCAHhSIIIAApAwh8IgkgACkDECIKQg2JIAogACkDAHwiCoUiC3wiDCALQhGJhTcDECAAIAxCIIk3AwggACAJIAhCEImFIghCFYkgCCAKQiCJfCIIhTcDGCAAIAcgCIU3AwALIAIgBGsiAkEHcSEDIAQgAkF4cSICSQRAIAApAwghCCAAKQMQIQcgACkDACEJIAApAxghCgNAIAggASAEaikAACILIAqFIgh8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CGpBADYCACAAQQE2AgAL3AEBAX8jAEEgayICJAACfwJAAkACQCAALQAAQQFrDgIBAgALIAJBFGpBATYCACACQRxqQQA2AgAgAkGMncAANgIQIAJB5JzAADYCGCACQQA2AgggASACQQhqENgBDAILIAJBFGpBATYCACACQRxqQQA2AgAgAkGAncAANgIQIAJB5JzAADYCGCACQQA2AgggASACQQhqENgBDAELIAJBFGpBATYCACACQRxqQQA2AgAgAkHwnMAANgIQIAJB5JzAADYCGCACQQA2AgggASACQQhqENgBCyACQSBqJAALugECAn8BfiMAQRBrIgQkACAEQQhqIAEgAiADEIYBAkACQAJ/IAQtAAhBBkYEQCAEKAIMDAELIAQpAwgiBkL/AYNCBlINASAGQiCIpwshBSAEQQhqIAFBDGogAiADEHcCQAJ/IAQtAAhBBkYEQCAEKAIMDAELIAQpAwgiBkL/AYNCBlINASAGQiCIpwshAyAAQQY6AAAgACADIAVqNgIEDAILIAAgBjcCAAwBCyAAIAY3AgALIARBEGokAAusAQEEfwJAIAAoAgwiAkUNACAAKAIEIQMgACgCACIBIAAoAggiAEEAIAEgACABSRtrIgAgAmogAiABIABrIgFLGyAARwRAIAMgAEECdGohACACIAEgAiABSRtBAnQhBANAIAAQtgEgAEEEaiEAIARBfGoiBA0ACwsgAiABTQ0AIAJBAnQgAiABIAIgAUkbQQJ0ayEAA0AgAxC2ASADQQRqIQMgAEF8aiIADQALCwurAQEDfwJAIAJBD00EQCAAIQMMAQsgAEEAIABrQQNxIgRqIQUgBARAIAAhAwNAIAMgAToAACADQQFqIgMgBUkNAAsLIAUgAiAEayICQXxxIgRqIQMgBEEBTgRAIAFB/wFxQYGChAhsIQQDQCAFIAQ2AgAgBUEEaiIFIANJDQALCyACQQNxIQILIAIEQCACIANqIQIDQCADIAE6AAAgA0EBaiIDIAJJDQALCyAAC64BAQF/IAACfwJAAn8CQCACBEACQAJAAkAgAUEATgRAIAMoAghFDQIgAygCBCIEDQEgAQ0DDAULIABBCGpBADYCAAwGCyADKAIAIAQgAiABEOgCDAQLIAFFDQILIAEgAhD3AgwCCyAAIAE2AgQgAEEIakEANgIADAILIAILIgME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CyAAQQRqIgEQpwEgARDKAgwBCyAAQQRqIgEQmwIgARDKAgsgAEEoaiEAIAJBWGoiAg0ACwsLmwEBA38jAEEQayIFJAAgAygCCCECIAVBCGogARDwASADKAIEIgQgAkkEQCACIARB4IzAABCGAwALIAMoAgAgAmogBSgCCCAEIAJrIgQgBSgCDCIGIAQgBkkbIgQQogMaIAMgAiAEaiICNgIIIABBBDoAACABIAEpAwAgBK18NwMAIAMgAygCDCIAIAIgACACSxs2AgwgBUEQaiQAC5gBAQN/IwBBQGoiASQAIAFBADYCCCABQoCAgIAQNwMAIAFBEGogARC+AiAAIAFBEGoQeEUEQCABQRhqIAFBCGooAgA2AgAgASABKQMANwMQIAFBEGoQ2wIgAC0AACIDQQRPQQAgA0EGcUEERhtFBEAgABCHAgsgAUFAayQADwtB/JHAAEE3IAFBOGpBtJLAAEGQk8AAELQBAAuYAQEDfyMAQUBqIgEkACABQQA2AgggAUKAgICAEDcDACABQRBqIAEQvgIgACABQRBqEHlFBEAgAUEYaiABQQhqKAIANgIAIAEgASkDADcDECABQRBqENsCIAAtAAAiA0EET0EAIANBBnFBBEYbRQRAIAAQhwILIAFBQGskAA8LQfyRwABBNyABQThqQbSSwABBkJPAABC0AQALigEBBX8gACAAKAIAIgEQgwIgACgCCCIFIAEgACgCDCICa0sEQCABIAVrIgMgAiADayICS0EAIAAoAgAiBCABayACTxtFBEAgACgCBCIBIAQgA2siBEECdGogASAFQQJ0aiADQQJ0EKEDIAAgBDYCCA8LIAAoAgQiACABQQJ0aiAAIAJBAnQQogMaCwu1AQEDfyMAQRBrIgEkACAAKAIAIgJBFGooAgAhAwJAAn8CQAJAIAJBDGooAgAOAgABAwsgAw0CQQAhAkGEvsAADAELIAMNASACKAIIIgMoAgQhAiADKAIACyEDIAEgAjYCBCABIAM2AgAgAUGkxsAAIAAoAgQiASgCCCAAKAIIIAEtABAQiwEACyABQQA2AgQgASACNgIMIAFBkMbAACAAKAIEIgEoAgggACgCCCABLQAQEIsBAAuXAQECfyMAQRBrIgEkACAAKAIARQRAIABBfzYCACAAAn9BACAAKAIEIgJFDQAaIABBADoAFCABIABB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AEHY7MAAKQMAUARAQejswAACfgJAIABFDQAgACkDACAAQgA3AwBCAVINACAAKQMIIQIgACkDEAwBCyABQgI3AwggAUIBNwMAIAEpAwAhAiABKQMICzcDAEHg7MAAIAI3AwBB2OzAAEIBNwMACyABQRBqJABB4OzAAAt+AQF/IwBBEGsiASQAIAFB7rHAAEEEEAE2AgggAUGEssAAQQQQATYCDCABIAAgAUEIaiABQQxqEOIBIAEoAgwiAEEkTwRAIAAQAAsgASgCCCIAQSRPBEAgABAACwJAIAEtAABFDQAgASgCBCIAQSRJDQAgABAACyABQRBqJAALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHrADYCACADQbTOwAA2AhAgA0EANgIIIANB6wA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACEKgCAAt5AQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EUakECNgIAIANBHGpBAjYCACADQSxqQesANgIAIANB5NLAADYCECADQQA2AgggA0HrADYCJCADIANBIGo2AhggAyADQQRqNgIoIAMgAzYCICADQQhqIAIQqAIAC3kBAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRRqQQI2AgAgA0EcakECNgIAIANBLGpB6wA2AgAgA0GE08AANgIQIANBADYCCCADQesANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANBCGogAhCoAgALeQEBfyMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBFGpBAjYCACADQRxqQQI2AgAgA0EsakHrADYCACADQbjTwAA2AhAgA0EANgIIIANB6wA2AiQgAyADQSBqNgIYIAMgA0EEajYCKCADIAM2AiAgA0EIaiACEKgCAAtzAQR/IwBBEGsiASQAIAAoAggiAiAAKAIEIgNHBEAgAiADa0ECdkECdCECA0AgAygCACIEQSRPBEAgBBAACyADQQRqIQMgAkF8aiICDQALCyABIAAoAgw2AgwgASAAKAIANgIIIAFBCGoQmQIgAUEQaiQAC2wBAX8jAEEwayIDJAAgAyABNgIoIAMgADYCJCADIAE2AiAgA0EIaiADQSBqELICIANBEGogAygCCCADKAIMEOUCIANBKGogA0EYaigCADYCACADIAMpAxA3AyAgA0EgaiACEM8BIANBMGokAAtpAQF/IwBBMGsiAiQAIAIgATYCKCACIAA2AiQgAiABNgIgIAJBCGogAkEgahCyAiACQRBqIAIoAgggAigCDBDlAiACQShqIAJBGGooAgA2AgAgAiACKQMQNwMgIAJBIGoQZyACQTBqJAALcgEDfyMAQSBrIgIkAAJ/QQEgACABEFwNABogASgCBCEDIAEoAgAhBCACQQA2AhwgAkGwzcAANgIYIAJBATYCFCACQeDNwAA2AhAgAkEANgIIQQEgBCADIAJBCGoQOg0AGiAAQQRqIAEQXAsgAkEgaiQAC3cBAX8CQAJAIABFDQAgACgCACEBIABBADYCACAAKAIEIQACQCABDgIBAgALIABBJEkNACAAEAALEFYhAAtBnOzAACgCACEBQZzswAAgADYCAEGY7MAAKAIAQZjswABBATYCAEUgAUEkSXJFBEAgARAAC0Gc7MAAC3wBA38gACAAEKoDIgBBCBDmAiAAayICEKgDIQBBlPDAACABIAJrIgE2AgBBnPDAACAANgIAIAAgAUEBcjYCBEEIQQgQ5gIhAkEUQQgQ5gIhA0EQQQgQ5gIhBCAAIAEQqAMgBCADIAJBCGtqajYCBEGo8MAAQYCAgAE2AgALcwAjAEEwayIBJABBgOzAAC0AAARAIAFBFGpBAjYCACABQRxqQQE2AgAgAUH8xMAANgIQIAFBADYCCCABQesANgIkIAEgADYCLCABIAFBIGo2AhggASABQSxqNgIgIAFBCGpBpMXAABCoAgALIAFBMGokAAt2AQF/IAAtAAQhASAALQAFBEAgAUH/AXEhASAAAn9BASABDQAaIAAoAgAiAS0AGEEEcUUEQCABKAIAQZfPwABBAiABKAIEKAIMEQUADAELIAEoAgBBls/AAEEBIAEoAgQoAgwRBQALIgE6AAQLIAFB/wFxQQBHC2kBAX8jAEEgayICJABB3OvAACgCAEUEQEGgk8AAQStB5JvAABD3AQALIAJBGGogAEEIaigCADYCACACIAApAgA3AxAgAkEIaiACQRBqIAEQVyACKAIIIQAgAigCDCACQSBqJABBISAAGwtrAQJ/IwBBIGsiAiQAIAJBCGogASgCABACAkAgAigCCCIDBEAgAigCDCEBIAIgAzYCFCACIAE2AhggAiABNgIQIAIgAkEQahCyAiAAIAIoAgAgAigCBBDlAgwBCyAAQQA2AgQLIAJBIGokAAtrAQJ/IAFBBGooAgAhAwJAAkACQCABQQhqKAIAIgFFBEBBASECDAELIAFBf0wNASABQQEQ9wIiAkUNAgsgAiADIAEQogMhAiAAIAE2AgggACACNgIEIAAgATYCAA8LEJgCAAsgAUEBEJsDAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQaCDwAAgAkEIahA6IAJBIGokAAtZAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQYiDwAAgAkEIahA6IAJBIGokAAthAQN/IAAgARDLAiAAKAIEIgQgACgCCCICaiEDAkACQCABQQJPBEAgA0EAIAFBf2oiARCjAxogBCABIAJqIgJqIQMMAQsgAUUNAQsgA0EAOgAAIAJBAWohAgsgACACNgIIC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB7L3AACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB4MvAACACQQhqEDogAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBqNHAACACQQhqEDogAkEgaiQAC1MBAn8jAEEgayICJAAgACgCBCEDIAAoAgAgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAyACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBiIPAACACQQhqEDogAkEgaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBoIPAACACQQhqEDogAkEgaiQAC44BAgF/An4jAEEQayIBJABBuOvAACAAOwEAQbDrwABCADcDACABEOcBIAEpAwghAiABKQMAIQNB3OvAACgCAARAQdDrwAAoAgAEQBCbARCrAgsLQdzrwABBsJnAADYCAEHQ68AAQgA3AwBBwOvAACADNwMAQcjrwAAgAjcDAEHY68AAQQA2AgAgAUEQaiQAC1YBAX8jAEEgayICJAAgAiAANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBqNHAACACQQhqEDogAkEgaiQAC2EBAX8jAEFAaiIBJAAgAUEBOgAPIABBADYCCCAAQoCAgIAQNwIAIAFBEGogABC+AiABQQ9qIAFBEGoQkwEEQEH8kcAAQTcgAUE4akG0ksAAQZCTwAAQtAEACyABQUBrJAALSAECfwJAIAFFBEBBASECDAELIAFBAE4EQCABIAFBf3NBH3YiAxD3AiICDQEgASADEJsDAAsQmAIACyAAIAI2AgQgACABNgIAC2IBAX8jAEEgayIDJAAgACgCACADQQhqIAEgAhAwIAMoAggEQCADIAMpAgw3AxhB9K7AAEErIANBGGpBoK/AAEGUsMAAELQBAAsgAygCDCADQRBqKAIAEJcCIANBIGokAEEAC2kBA38jAEEQayIBJAACQEEAQeC4wAAoAgARBgAiAgRAIAAoAgAoAgAiACAAKAIAQQFqIgM2AgAgA0UNASACIAAQtwEgAUEQaiQADwtBtLnAAEHGACABQQhqQfy5wABB3LrAABC0AQALAAtWAQJ/AkAgAEEDcEEDc0EDcCIERQRADAELQQAhAANAIAAgAkcEQCAAIAFqQT06AAAgAEEBaiEDQQEhACADIARJDQEMAgsLIAIgAkG0n8AAEMMBAAsgAwtaAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAECAhASAEQQhqEL0CIAACfyAEKAIIRQRAIAAgAUEARzoAAUEADAELIAAgBCgCDDYCBEEBCzoAACAEQRBqJAALVAEBfyMAQTBrIgEkACABQRBqQcibwABBBRCFAiABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC1kBAn8gACgCDCICIAAoAgAiA0YEQCAAEKsBIAAoAgwhAiAAKAIAIQMLIAAoAgQgACgCCCACaiICQQAgAyACIANJG2tBAnRqIAE2AgAgACAAKAIMQQFqNgIMC0cBAn8CQCAAKAIAIgJFDQAgAiAAQRRqKAIAIgEgADUCECACQQFqrX6nakF/akEAIAFrcSIBakEJakUNACAAKAIMIAFrECsLC2ABAn8jAEEQayIBJAAgAUGwh8AAQRUQhQJBDEEEEPcCIgJFBEBBDEEEEJsDAAsgAiABKQMANwIAIAJBCGogAUEIaigCADYCACAAQeCAwAA2AgQgACACNgIAIAFBEGokAAtkAgJ/AX4jAEEQayICJABBAEGkkMAAKAIAEQYAIgEEQCABIAEpAwAiA0IBfDcDACAAIAEpAwg3AwggACADNwMAIAJBEGokAA8LQaiQwABBxgAgAkEIakHwkMAAQdCRwAAQtAEAC0oBAX8jAEEgayIAJAAgAEEUakEBNgIAIABBHGpBADYCACAAQfjKwAA2AhAgAEHcysAANgIYIABBADYCCCAAQQhqQdDLwAAQqAIAC00BAX8jAEEwayIBJAAgAUEQahDdASABQShqIAFBGGooAgA2AgAgASABKQMQNwMgIAFBCGogAUEgahCyAiAAIAEpAwg3AwAgAUEwaiQAC2cBAX8jAEEgayIDJAAgAyACNgIMIANBEGoiAkGAAjsBBCACQQZqQQA6AAAgAkH9BTYCACADQRBqIAAgASADQQxqECUEQEGkmMAAQSIgA0EYakHMk8AAQaCZwAAQtAEACyADQSBqJAALTAECfyAAKAIIIgEEQCAAKAIEIQAgAUEEdCEBA0AgAC0AACICQX5qQQdJIAJFckUEQCAAQQRqEJoCCyAAQRBqIQAgAUFwaiIBDQALCwtWAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBD3AiIBRQ0BIAEgAzYCBCABIAI2AgAgAEHUscAANgIEIAAgATYCAA8LAAtBCEEEEJsDAAtRAQN/IwBBEGsiASQAIAFBCGoQjwIQtAIgASgCDCECAkAgASgCCEUEQEEBIQMMAQsgAkEkSQ0AIAIQAAsgACACNgIEIAAgAzYCACABQRBqJAALSwECfyMAQRBrIgEkACABIABBeGo2AgggAC0AFCAAQQE6ABQgASABQQhqNgIMQQFxRQRAIAFBDGoQ4AELIAFBCGoQtgEgAUEQaiQAC18BA38jAEEQayIBJAACQCAAKAIMIgIEQCAAKAIIIgNFDQEgASACNgIIIAEgADYCBCABIAM2AgAgARC2AgALQYS+wABBK0HgxcAAEPcBAAtBhL7AAEErQdDFwAAQ9wEAC1ACAn8CfiABQRBqKAIAIgIgASkDACIEIAKtIgUgBCAFVBunIgNJBEAgAyACQfSJwAAQhgMACyAAIAIgA2s2AgQgACABQQxqKAIAIANqNgIAC0gBA38jAEEQayICJAAgAiABNgIMQQEhASACQQxqKAIAEBJBAUYgAigCDCEDBEBBACEBCyAAIAM2AgQgACABNgIAIAJBEGokAAtIAQN/IwBBEGsiAiQAIAIgATYCDEEBIQEgAkEMaigCABALQQBHIAIoAgwhAwRAQQAhAQsgACADNgIEIAAgATYCACACQRBqJAALSgEBfyMAQRBrIgQkACABIAIgAygCABANIQEgBEEIahC9AiAAAn8gASAEKAIIIgFFDQAaIAQoAgwLNgIEIAAgATYCACAEQRBqJAALWAECfyMAQRBrIgEkACABIAA2AgRBAEHguMAAKAIAEQYAIgIEQCACIAAQtwEgAUEQaiQADwsgAUEEahC2AUG0ucAAQcYAIAFBCGpB/LnAAEHcusAAELQBAAtYAQF/IwBBIGsiACQAIABBDGpBATYCACAAQRRqQQE2AgAgAEGIlMAANgIIIABBADYCACAAQRo2AhwgAEGsl8AANgIYIAAgAEEYajYCECAAQbSXwAAQqAIAC0YBAX8jAEEQayICJAAgASgCABAMIQEgAkEIahC9AiAAAn8gASACKAIIIgFFDQAaIAIoAgwLNgIEIAAgATYCACACQRBqJAALUgEBfyMAQSBrIgMkACADQQxqQQE2AgAgA0EUakEANgIAIANBsM3AADYCECADQQA2AgAgAyABNgIcIAMgADYCGCADIANBGGo2AgggAyACEKgCAAtTAQF/IwBBIGsiAiQAIAJBDGpBATYCACACQRRqQQE2AgAgAkHUzsAANgIIIAJBADYCACACQf8ANgIcIAIgADYCGCACIAJBGGo2AhAgAiABEKgCAAtDAQN/AkAgAkUNAANAIAAtAAAiBCABLQAAIgVGBEAgAEEBaiEAIAFBAWohASACQX9qIgINAQwCCwsgBCAFayEDCyADC0gBAX8jAEEQayICJAAgAkEIaiAAIAEQfwJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEHwCQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSAEBfyMAQRBrIgIkACACQQhqIAAgARB+AkAgAigCDCIAQYGAgIB4RwRAIABFDQEgAigCCCAAEJsDAAsgAkEQaiQADwsQmAIAC0sBAX8jAEEQayICJAAgAkEIaiAAIAFBARCMAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtIAQF/IwBBEGsiAiQAIAJBCGogACABEH0CQCACKAIMIgBBgYCAgHhHBEAgAEUNASACKAIIIAAQmwMACyACQRBqJAAPCxCYAgALSwEBfyMAQRBrIgMkACADQQhqIAAgASACEIwBAkAgAygCDCIAQYGAgIB4RwRAIABFDQEgAygCCCAAEJsDAAsgA0EQaiQADwsQmAIAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQay2wABBHBCWAwALIAIgAzYCDCADQQhqQQEgARB6IAJBDGoQrwEgAkEQaiQAC00BAn8jAEEQayICJAAgACgCACEDIABBADYCACADRQRAQay2wABBHBCWAwALIAIgAzYCDCADQQhqQQAgARB6IAJBDGoQrwEgAkEQaiQAC0MBAn8jAEEQayIBJAAgASAAQXhqNgIIIAAtABQgAEEBOgAUIAEgAUEIajYCDEEBcUUEQCABQQxqEOABCyABQRBqJAALSQEBfyMAQRBrIgIkACACQQhqIAAgARCAAQJAIAIoAgwiAEGBgICAeEcEQCAARQ0BIAIoAgggABCbAwALIAJBEGokAA8LEJgCAAtOAQF/IwBBEGsiBCQAIAEoAgAgAigCACADKAIAEBkhASAEQQhqEL0CIAQoAgwhAiAAIAQoAggiAzYCACAAIAIgASADGzYCBCAEQRBqJAALSQEDfyMAQRBrIgMkACADQQhqIAIQ3gEgAygCCCEEIAAgAygCDCIFNgIEIAAgBDYCACAFIAEgAhCiAxogACACNgIIIANBEGokAAtQAQF/QSBBBBD3AiIBRQRAQSBBBBCbAwALIAFCgYCAgBA3AgAgASAAKQIANwIIIAFBEGogAEEIaikCADcCACABQRhqIABBEGopAgA3AgAgAQtFAQJ/IAAtAABBA0YEQCAAKAIEIgEoAgAgASgCBCgCABECACABKAIEIgIoAgQEQCACKAIIGiABKAIAECsLIAAoAgQQKwsLSgEBfyMAQbABayIBJAAgASAAQagBEKIDIgAgADYCrAEgAEGsAWpB2I7AABCnAyAALQCgAUEDRgRAIABBCGoQrAILIABBsAFqJAALSAEBfyAAKAIAIgEEQCABIAAoAgQoAgARAgAgACgCBCIBKAIEBEAgASgCCBogACgCABArCyAAKAIIIABBDGooAgAoAgwRAgALC0gBAX8gACgCACIAKAIAIAAoAggiA2sgAkkEQCAAIAMgAhCEASAAKAIIIQMLIAAoAgQgA2ogASACEKIDGiAAIAIgA2o2AghBAAtIAQF/IAAoAgAiACgCACAAKAIIIgNrIAJJBEAgACADIAIQhQEgACgCCCEDCyAAKAIEIANqIAEgAhCiAxogACACIANqNgIIQQALPgECfyMAQRBrIgEkACABQQhqIABBCGooAgAiAjYCACABIAApAgA3AwAgASgCBCACEAEgARCaAiABQRBqJAALQAECfyAAKAIIIgEEQCAAKAIEIQAgAUECdCEBA0AgACgCACICQSRPBEAgAhAACyAAQQRqIQAgAUF8aiIBDQALCwtPAQF/IAAoAgAiACAAKAIAQX9qIgE2AgACQCABDQAgAEEMaiIBEJUBIAEoAgAEQCABKAIEECsLIAAgACgCBEF/aiIBNgIEIAENACAAECsLC0kBAn8jAEEQayIBJABBAEHsusAAKAIAEQYAIgAEQCAAKAIAEAMgAUEQaiQADwtBq7vAAEHGACABQQhqQfS7wABB1LzAABC0AQALRwEBfyMAQZACayIBJAAgASAAQYgCEKIDIgAgADYCjAIgAEGMAmpB7I7AABCnAyAALQCAAkEDRgRAIAAQlgILIABBkAJqJAALRgEBfyMAQZACayIEJAAgBEEAOgCIAiAE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NEEEEPcCIgFFBEBBNEEEEJsDAAsgAUKBgICAEDcCACABQQhqIABBLBCiAxogAQsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ4CIAEoAggFIAILNgIEIAAgASgCBDYCAAsyAQF/IAAgASgCACABKAIIIgJLBH8gASACEJ8CIAEoAggFIAILNgIEIAAgASgCBDYCAAsuAQF/IAEoAgAiAgRAIABBATYCCCAAIAI2AgQgACABKAIENgIADwsgAEEANgIICyMBAX8Cf0EBIAEQCUUNABpBAAshAiAAIAE2AgQgACACNgIACzABAX8gAUF4aiICIAIoAgBBAWoiAjYCACACRQRAAAsgAEHkuMAANgIEIAAgATYCAAstAQF/IwBBEGsiASQAIAFBCGogAEEIaigCADYCACABIAApAgA3AwAgARCsAQALIwAgACgCAEFwaiIAEJoCIABBDGooAgAiAEEkTwRAIAAQAAsLMQEBf0EEQQQQ9wIiAkUEQEEEQQQQmwMACyACIAE2AgAgAEGEtsAANgIEIAAgAjYCAAsxAQF/QQRBBBD3AiICRQRAQQRBBBCbAwALIAIgATYCACAAQZi2wAA2AgQgACACNgIACycAIAAgACgCBEEBcSABckECcjYCBCAAIAFqIgAgACgCBEEBcjYCBAsmAQF/IwBBEGsiASQAIAEgAEF4ajYCDCABQQxqELYBIAFBEGokAAsmAAJAIABFDQAgACABKAIAEQIAIAEoAgRFDQAgASgCCBogABArCws6AQJ/QbjswAAtAAAhAUG47MAAQQA6AABBvOzAACgCACECQbzswABBADYCACAAIAI2AgQgACABNgIACzQAIABBAzoAICAAQoCAgICABDcCGCAAQQA2AhAgAEEANgIIIABB5JHAADYCBCAAIAE2AgALMgEBfyABKAIAQa++wABBCyABKAIEKAIMEQUAIQIgAEEAOgAFIAAgAjoABCAAIAE2AgALIAEBfwJAIABBBGooAgAiAUUNACAAKAIARQ0AIAEQKwsLJgEBfyMAQRBrIgMkACADIAE2AgwgAyAANgIIIANBCGogAhD4AQALEwAgACABKQAANwABIABBADoAAAsmAQF/IABBB2oiASAASQRAQaSwwABBM0GwscAAEIoDAAsgAUEDdgsjAAJAIAFB/P///wdNBEAgACABQQQgAhDoAiIADQELAAsgAAsjACACIAIoAgRBfnE2AgQgACABQQFyNgIEIAAgAWogATYCAAseACAAKAIAIgCtQgAgAKx9IABBf0oiABsgACABEFoLKgACQAJAAkAgAC0AqgEOBAACAgECCyAAQYABahC6AQ8LIABBCGoQrgELCyUAIABFBEBB+7rAAEEwEJYDAAsgACACIAMgBCAFIAEoAhARCwALHQAgACgCACgCACABKAIMQQAgAmtBGGxqQWhqEEMLEQAgACgCAARAIAAoAgQQKwsLIAEBfyAAKAIAIAAoAggiAmsgAUkEQCAAIAIgARD/AQsLIwAgAEUEQEH7usAAQTAQlgMACyAAIAIgAyAEIAEoAhARCgALIwAgAEUEQEH7usAAQTAQlgMACyAAIAIgAyAEIAEoAhARBAALIwAgAEUEQEH7usAAQTAQlgMACyAAIAIgAyAEIAEoAhARFQALIwAgAEUEQEH7usAAQTAQlgMACyAAIAIgAyAEIAEoAhARDgALIwAgAEUEQEH7usAAQTAQlgMACyAAIAIgAyAEIAEoAhARFAALFwAgASADRgR/IAAgAiABEPkBRQVBAAsLHgAgACABQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIECyEAIABFBEBB+7rAAEEwEJYDAAsgACACIAMgASgCEBEDAAsUACAAKAIABEAgAEEEaigCABArCwsaACAAKAIAKAIAIAEoAgwgAkEEdGtBcGoQQwsdACABKAIARQRAAAsgAEHUscAANgIEIAAgATYCAAsfACAARQRAQcCzwABBMBCWAwALIAAgAiABKAIQEQAACx8AIABFBEBBhLnAAEEwEJYDAAsgACACIAEoAhARAAALHwAgAEUEQEH7usAAQTAQlgMACyAAIAIgASgCEBEBAAsXACAAKAIABEAgABCpAiAAQQxqEKkCCwsfAQF/IAAoAgQgACgCCBABIAAoAgAEQCAAKAIEECsLCx4BAX9BnOzAACEBQZjswAAoAgAEfyABBSAAEMsBCwsZAQF/IAAoAhAiAQR/IAEFIABBFGooAgALCxkAIAEgAiADEJcCIABBBDoAACAAIAM2AgQLFwAgAEEEaigCACAAQQhqKAIAIAEQnAMLEgBBAEEZIABBAXZrIABBH0YbCxYAIAAgAUEBcjYCBCAAIAFqIAE2AgALFgAgAEEEaigCACAAQQhqKAIAIAEQLwsTAEHw68AAKAIABEAQmQEQpAILCxcAQYjswAAoAgBFBEAgABBvC0GE7MAACxcAIAAgAjYCCCAAIAE2AgQgACACNgIACxAAIAAgAWpBf2pBACABa3ELEgAgAC0AAEEERwRAIAAQhwILCwwAIAAgASACIAMQLgsLACABBEAgABArCwsPACAAQQF0IgBBACAAa3ILGQAgASgCAEHozcAAQQsgASgCBCgCDBEFAAsZACABKAIAQfPNwABBDiABKAIEKAIMEQUACxkAIAEoAgBB/OPAAEEFIAEoAgQoAgwRBQALEwAgACgCACgCCCABIAIQlwJBAAsSACABIAIgAxCXAiAAQQQ6AAALCgAgAEEIahCaAgsPACAAKAIABEAgABCvAQsLFAAgACgCACABIAAoAgQoAgwRAQALDwAgACABIAIgAyAEECkACw4AIAAoAgAgARBwGkEACxAAIAAoAgAgASACEJcCQQALEAAgACgCCCABIAIQlwJBAAsIACAAIAEQSQsRACAAKAIAIAAoAgQgARCcAwsQACAAIAI2AgQgACABNgIACxYAQbzswAAgADYCAEG47MAAQQE6AAALEwAgAEGAxsAANgIEIAAgATYCAAsNACAALQAEQQJxQQF2Cw8AIAAgAUEEaikCADcDAAsQACABIAAoAgAgACgCBBAsCw0AIAAgASACEJcCQQALCgBBACAAayAAcQsLACAALQAEQQNxRQsMACAAIAFBA3I2AgQLDQAgACgCACAAKAIEagsNACAAKAIAIAEQWEEACw4AIAAoAgAaA0AMAAsACwwAIAAgASACEMQBAAsMACAAIAEgAhDFAQALDAAgACABIAIQxgEACw0AIAA1AgBBASABEFoLDAAgACABIAIQwQIACw0AIAAoAgAgASACEEcLDQAgACkDAEEBIAEQWgsNACAAMwEAQQEgARBaCw4AIAAoAgAtAAAgARBdCwsAIAAjAGokACMACwcAIAAQmgILCgAgACABIAIQOwsLACAAIAIgARChAQsNACABQeCRwABBAhAsCwsAIAAoAgAgARBKCwsAIAAgAUHYABAiCwkAIAAgARAhAAsKACAAKAIEQXhxCwoAIAAoAgRBAXELCgAgACgCDEEBcQsKACAAKAIMQQF2CxoAIAAgAUHA7MAAKAIAIgBB7AAgABsRAAAACwoAIAIgACABECwLDAAgACABKQIANwMACwwAIAAgASkCCDcDAAsNACABQfzRwABBAhAsCwsAIAAoAgAgARBcCwoAIAAgASACEDULCgAgACABIAIQWQsLACAAIAEgAhCWAQsHACAAEMEBCwkAIABBBDoAAAsJACAAQQA2AgALCAAgACABEBoLBwAgACABagsHACAAIAFrCwcAIABBCGoLBwAgAEF4agsHACAAENsBCwcAIAAQjgILBABBAQsNAEKRuN6i/Jvrr/sACw0AQsi14M/KhtvTiX8LDQBC54bFsIye5t3IAAsMAELJ4Nbe5qrapDkLAwABCwMAAQsL/GoFAEGAgMAAC/EPAQAAAAQAAAAEAAAAAgAAAAMAAAADAAAAAQAAAAQAAAAEAAAABAAAAAUAAAAFAAAA//////////9gdW53cmFwX3Rocm93YCBmYWlsZWQAAAAGAAAADAAAAAQAAAAHAAAABgAAAAwAAAAEAAAACAAAAAcAAABQABAACQAAAAoAAAALAAAACQAAAAwAAAAvcnVzdGMvMDQ0MmZiYWJlMjRlYzQzNjM2YTgwYWQxZjQwYTBhZDkyYTJlMzhkZi9saWJyYXJ5L3N0ZC9zcmMvaW8vbW9kLnJzAAAAjAAQAEkAAABTAQAAGAAAAHN0cmVhbSBkaWQgbm90IGNvbnRhaW4gdmFsaWQgVVRGLTgAAOgAEAAiAAAAFQAAAC9ydXN0Yy8wNDQyZmJhYmUyNGVjNDM2MzZhODBhZDFmNDBhMGFkOTJhMmUzOGRmL2xpYnJhcnkvc3RkL3NyYy9pby9yZWFkYnVmLnJzAAAAGAEQAE0AAABjAAAANgAAABgBEABNAAAAywAAADYAAAANAAAABAAAAAQAAAAOAAAADwAAABAAAAANAAAABAAAAAQAAAARAAAAEgAAABMAAABjYWxsZWQgYFJlc3VsdDo6dW53cmFwKClgIG9uIGFuIGBFcnJgIHZhbHVlAA0AAAAAAAAAAQAAABQAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvY2h1bmtlZF9lbmNvZGVyLnJzAAAA9AEQAGEAAAAtAAAAGgAAAPQBEABhAAAANwAAAEQAAAD0ARAAYQAAADoAAAAnAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2VuY29kZS5yc4gCEABYAAAAtgAAACAAAACIAhAAWAAAALcAAAAlAAAAiAIQAFgAAAD8AAAAHAAAAIgCEABYAAAA/QAAACEAAACIAhAAWAAAABMBAAAuAAAAiAIQAFgAAAATAQAACQAAAIgCEABYAAAAFAEAAAkAAACIAhAAWAAAAAsBAAAuAAAAiAIQAFgAAAALAQAACQAAAIgCEABYAAAADQEAAA8AAACIAhAAWAAAAAwBAAAJAAAAiAIQAFgAAAAPAQAACQAAAIgCEABYAAAAoAAAACoAAABmYWlsZWQgdG8gZmlsbCBidWZmZXJmYWlsZWQgdG8gd3JpdGUgd2hvbGUgYnVmZmVyAAAAxQMQABwAAAAXAAAAFQAAAAwAAAAEAAAAFgAAABcAAAAYAAAAZm9ybWF0dGVyIGVycm9yAAgEEAAPAAAAKAAAAGZhaWxlZCB0byBmaWxsIHdob2xlIGJ1ZmZlcgAkBBAAGwAAACUAAAAvcnVzdGMvMDQ0MmZiYWJlMjRlYzQzNjM2YTgwYWQxZjQwYTBhZDkyYTJlMzhkZi9saWJyYXJ5L3N0ZC9zcmMvaW8vaW1wbHMucnMATAQQAEsAAADyAAAADQAAAC9ydXN0Yy8wNDQyZmJhYmUyNGVjNDM2MzZhODBhZDFmNDBhMGFkOTJhMmUzOGRmL2xpYnJhcnkvc3RkL3NyYy9pby9jdXJzb3IucnOoBBAATAAAAOsAAAAKAAAAL3J1c3RjLzA0NDJmYmFiZTI0ZWM0MzYzNmE4MGFkMWY0MGEwYWQ5MmEyZTM4ZGYvbGlicmFyeS9zdGQvc3JjL2lvL21vZC5ycwAAAAQFEABJAAAAJAUAABYAAAAvcnVzdGMvMDQ0MmZiYWJlMjRlYzQzNjM2YTgwYWQxZjQwYTBhZDkyYTJlMzhkZi9saWJyYXJ5L3N0ZC9zcmMvc3lzL3dhc20vLi4vdW5zdXBwb3J0ZWQvaW8ucnMAAABgBRAAXQAAAA4AAAATAAAAYWR2YW5jaW5nIGlvIHNsaWNlcyBiZXlvbmQgdGhlaXIgbGVuZ3RoANAFEAAnAAAABAUQAEkAAAAmBQAADQAAAC9ydXN0Yy8wNDQyZmJhYmUyNGVjNDM2MzZhODBhZDFmNDBhMGFkOTJhMmUzOGRmL2xpYnJhcnkvc3RkL3NyYy9pby9yZWFkYnVmLnJzAAAAEAYQAE0AAADmAAAADgAAABwAAAAMAAAABAAAAB0AAAAeAAAAHwAAACAAAAAhAAAAIgAAACMAAAAvaG9tZS9uZ25pdXMvRG9jdW1lbnRzL2dpdC1yZXBvcy91c2RwbC1ycy91c2RwbC1jb3JlL3NyYy9zZXJkZXMvdHJhaXRzLnJzAAAAmAYQAEkAAAB2AAAAHAAAACQAAAAYAAAACAAAACUAAAAmAAAAJwAAACgAAAApAAAAKgAAACsAAAAsAAAAYHVud3JhcF90aHJvd2AgZmFpbGVkAAAALQAAAGABAAAIAAAALgAAAC8AAAAgAgAACAAAADAAAAAxAAAABAAAAAQAAAAyAAAAMwAAADEAAAAEAAAABAAAADQAAAA1AAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvbGliLnJzAIAHEABjAAAA2gAAABUAQYCQwAALyERgYXN5bmMgZm5gIHJlc3VtZWQgYWZ0ZXIgY29tcGxldGlvbgA2AAAAY2Fubm90IGFjY2VzcyBhIFRocmVhZCBMb2NhbCBTdG9yYWdlIHZhbHVlIGR1cmluZyBvciBhZnRlciBkZXN0cnVjdGlvbgAAMQAAAAAAAAABAAAANwAAAC9ydXN0Yy8wNDQyZmJhYmUyNGVjNDM2MzZhODBhZDFmNDBhMGFkOTJhMmUzOGRmL2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMAgAgQAE8AAACmAQAAGgAAACgpAAAcAAAADAAAAAQAAAA4AAAAOQAAADoAAABhIERpc3BsYXkgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IgdW5leHBlY3RlZGx5ADEAAAAAAAAAAQAAADsAAAAvcnVzdGMvMDQ0MmZiYWJlMjRlYzQzNjM2YTgwYWQxZjQwYTBhZDkyYTJlMzhkZi9saWJyYXJ5L2FsbG9jL3NyYy9zdHJpbmcucnMARAkQAEsAAADpCQAADgAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUAMQAAAAAAAAABAAAAPAAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAA3AkQACoAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzEAoQAFgAAADSAQAAHwAAABAKEABYAAAA2AEAAB8AAAAQChAAWAAAAOEBAAAfAAAAEAoQAFgAAADqAQAAHwAAABAKEABYAAAA8wEAAB8AAAAQChAAWAAAAPwBAAAfAAAAEAoQAFgAAAAFAgAAHwAAABAKEABYAAAADgIAAB8AAAAQChAAWAAAAAMBAAAkAAAAEAoQAFgAAAAEAQAAKQAAABAKEABYAAAAKgEAABYAAAAQChAAWAAAAC0BAAAaAAAAEAoQAFgAAABBAQAADgAAABAKEABYAAAARAEAABIAAAAQChAAWAAAAFgBAAATAAAASW1wb3NzaWJsZTogbXVzdCBvbmx5IGhhdmUgMCB0byA4IGlucHV0IGJ5dGVzIGluIGxhc3QgY2h1bmssIHdpdGggbm8gaW52YWxpZCBsZW5ndGhzWAsQAFQAAAAQChAAWAAAAJ0BAAAOAAAAEAoQAFgAAACxAQAACQAAAE92ZXJmbG93IHdoZW4gY2FsY3VsYXRpbmcgb3V0cHV0IGJ1ZmZlciBsZW5ndGgAABAKEABYAAAAlgAAAAoAAAAQChAAWAAAAJsAAAAhAAAAV3JpdGluZyB0byBhIFN0cmluZyBzaG91bGRuJ3QgZmFpbC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9lbmNvZGUucnMAAEYMEABYAAAAUwAAAA4AAAD//////////3VzZHBsLWZyb250L3NyYy9jb25uZWN0aW9uLnJzAAAAuAwQAB0AAAAZAAAAJgAAAFBPU1RodHRwOi8vdXNkcGwuOi91c2RwbC9jYWxsAAAA7AwQAAwAAAD4DBAAAQAAAPkMEAABAAAA+gwQAAsAAABsb2NhbGhvc3QAAAAoDRAACQAAALgMEAAdAAAALQAAACQAAAC4DBAAHQAAADQAAAAnAAAAuAwQAB0AAABJAAAAJgAAAEV4cGVjdGVkIGNhbGwgcmVzcG9uc2UgbWVzc2FnZSwgZ290IHNvbWV0aGluZyBlbHNldXNkcGwtZnJvbnQvc3JjL2NvbnZlcnQucnOeDRAAGgAAACAAAAAnAAAAMC45LjF1c2RwbC1mcm9udC9zcmMvbGliLnJzAM0NEAAWAAAAYQAAABgAAADNDRAAFgAAAGkAAAAYAAAAzQ0QABYAAABwAAAATgAAAM0NEAAWAAAAbwAAAAEAAADNDRAAFgAAAJ8AAAAmAAAAzQ0QABYAAACeAAAAAQAAAM0NEAAWAAAAwwAAAEAAAADNDRAAFgAAANEAAABAAAAAY3JhbmtzaGFmdAAAZA4QAAoAAABkZWNreQAAAHgOEAAFAAAAYW55AIgOEAADAAAATG9hZEVycm9yOiBJbygpAJQOEAAOAAAAog4QAAEAAABMb2FkRXJyb3I6IEludmFsaWREYXRhAAC0DhAAFgAAAExvYWRFcnJvcjogVG9vU21hbGxCdWZmZXIAAADUDhAAGQAAAER1bXBFcnJvcjogSW8oAAD4DhAADgAAAKIOEAABAAAARHVtcEVycm9yOiBVbnN1cHBvcnRlZAAAGA8QABYAAABEdW1wRXJyb3I6IFRvb1NtYWxsQnVmZmVyAAAAOA8QABkAAAAvaG9tZS9uZ25pdXMvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzXA8QAFgAAAA7AQAACQAAACEiIyQlJicoKSorLC0wMTIzNDU2Nzg5QEFCQ0RFRkdISUpLTE1OUFFSU1RVVlhZWltgYWJjZGVoaWprbG1wcXJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSssLi9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS4vMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL////////////////////////////////////////////wABAgMEBQYHCAkKCwz//w0ODxAREhMUFRb///////8XGBkaGxwdHh8gISIjJCX/JicoKSorLP8tLi8w/////zEyMzQ1Nv//Nzg5Ojs8//89Pj//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pj////80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABNjc4OTo7PD0+P/////////8CAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG////////xwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJCgv/////////DA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCX///////8mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+//80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ/////z//GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7///8/NDU2Nzg5Ojs8Pf////////8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGf///////xobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wQREADEEBAAhBAQAEQQEAAEEBAAxA8QAEQWEABEFRAARBQQAEQTEABEEhAARBEQAGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWUAPgAAAAgAAAAEAAAAPwAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9iYXNlNjQtMC4xMy4wL3NyYy9jaHVua2VkX2VuY29kZXIucnMAAACwFxAAYQAAAGgAAAAwAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBudW1iZXIgb2YgY2h1bmtzIGluIGlucHV0L2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2RlY29kZS5ycwBXGBAAWAAAALwAAAAKAAAAQAAAAAgAAAAEAAAAQQAAAEIAAABAAAAACAAAAAQAAABDAAAAYm9keW1ldGhvZG1vZGVzYW1lLW9yaWdpbm5vLWNvcnNjb3JzbmF2aWdhdGVhdHRlbXB0ZWQgdG8gY29udmVydCBpbnZhbGlkIFJlcXVlc3RNb2RlIGludG8gSlNWYWx1ZS9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93ZWItc3lzLTAuMy42MC9zcmMvZmVhdHVyZXMvZ2VuX1JlcXVlc3RNb2RlLnJzRRkQAGsAAAADAAAAAQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeUcAAAAEAAAABAAAAEgAAABJAAAAYWxyZWFkeSBib3Jyb3dlZEoAAAAAAAAAAQAAAEsAAABhbHJlYWR5IG11dGFibHkgYm9ycm93ZWRKAAAAAAAAAAEAAABMAAAAL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvcXVldWUucnMAAABMGhAAZQAAABoAAAAuAAAATBoQAGUAAAAdAAAAKQAAAEwaEABlAAAAMgAAABoAAABhbHJlYWR5IGJvcnJvd2VkTQAAAAAAAAABAAAASwAAAE4AAAAEAAAABAAAAE8AAABQAAAATgAAAAQAAAAEAAAAUQAAAFIAAABGbk9uY2UgY2FsbGVkIG1vcmUgdGhhbiBvbmNlL2hvbWUvbmduaXVzLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3dhc20tYmluZGdlbi1mdXR1cmVzLTAuNC4zMy9zcmMvbGliLnJzAEgbEABjAAAApQAAAA8AAABIGxAAYwAAAIUAAAAnAAAASBsQAGMAAACvAAAAJAAAAC9ob21lL25nbml1cy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy93YXNtLWJpbmRnZW4tZnV0dXJlcy0wLjQuMzMvc3JjL3Rhc2svc2luZ2xldGhyZWFkLnJzAAAA3BsQAHEAAAAhAAAAFQAAAFMAAABUAAAAVQAAAFYAAABXAAAA3BsQAHEAAABVAAAAJQAAAGNsb3N1cmUgaW52b2tlZCByZWN1cnNpdmVseSBvciBkZXN0cm95ZWQgYWxyZWFkeWNhbm5vdCBhY2Nlc3MgYSBUaHJlYWQgTG9jYWwgU3RvcmFnZSB2YWx1ZSBkdXJpbmcgb3IgYWZ0ZXIgZGVzdHJ1Y3Rpb24AAFkAAAAAAAAAAQAAADcAAAAvcnVzdGMvMDQ0MmZiYWJlMjRlYzQzNjM2YTgwYWQxZjQwYTBhZDkyYTJlMzhkZi9saWJyYXJ5L3N0ZC9zcmMvdGhyZWFkL2xvY2FsLnJzAAwdEABPAAAApgEAABoAAABaAAAAcmV0dXJuIHRoaXNjbG9zdXJlIGludm9rZWQgcmVjdXJzaXZlbHkgb3IgZGVzdHJveWVkIGFscmVhZHljYW5ub3QgYWNjZXNzIGEgVGhyZWFkIExvY2FsIFN0b3JhZ2UgdmFsdWUgZHVyaW5nIG9yIGFmdGVyIGRlc3RydWN0aW9uAAAAZwAAAAAAAAABAAAANwAAAC9ydXN0Yy8wNDQyZmJhYmUyNGVjNDM2MzZhODBhZDFmNDBhMGFkOTJhMmUzOGRmL2xpYnJhcnkvc3RkL3NyYy90aHJlYWQvbG9jYWwucnMABB4QAE8AAACmAQAAGgAAAFRyaWVkIHRvIHNocmluayB0byBhIGxhcmdlciBjYXBhY2l0eWQeEAAkAAAAL3J1c3RjLzA0NDJmYmFiZTI0ZWM0MzYzNmE4MGFkMWY0MGEwYWQ5MmEyZTM4ZGYvbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc5AeEABMAAAAqgEAAAkAAABtAAAABAAAAAQAAABuAAAAbwAAAHAAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlQWNjZXNzRXJyb3IAAAQfEAAAAAAAdW5jYXRlZ29yaXplZCBlcnJvcm90aGVyIGVycm9yb3V0IG9mIG1lbW9yeXVuZXhwZWN0ZWQgZW5kIG9mIGZpbGV1bnN1cHBvcnRlZG9wZXJhdGlvbiBpbnRlcnJ1cHRlZGFyZ3VtZW50IGxpc3QgdG9vIGxvbmdpbnZhbGlkIGZpbGVuYW1ldG9vIG1hbnkgbGlua3Njcm9zcy1kZXZpY2UgbGluayBvciByZW5hbWVkZWFkbG9ja2V4ZWN1dGFibGUgZmlsZSBidXN5cmVzb3VyY2UgYnVzeWZpbGUgdG9vIGxhcmdlZmlsZXN5c3RlbSBxdW90YSBleGNlZWRlZHNlZWsgb24gdW5zZWVrYWJsZSBmaWxlbm8gc3RvcmFnZSBzcGFjZXdyaXRlIHplcm90aW1lZCBvdXRpbnZhbGlkIGRhdGFpbnZhbGlkIGlucHV0IHBhcmFtZXRlcnN0YWxlIG5ldHdvcmsgZmlsZSBoYW5kbGVmaWxlc3lzdGVtIGxvb3Agb3IgaW5kaXJlY3Rpb24gbGltaXQgKGUuZy4gc3ltbGluayBsb29wKXJlYWQtb25seSBmaWxlc3lzdGVtIG9yIHN0b3JhZ2UgbWVkaXVtZGlyZWN0b3J5IG5vdCBlbXB0eWlzIGEgZGlyZWN0b3J5bm90IGEgZGlyZWN0b3J5b3BlcmF0aW9uIHdvdWxkIGJsb2NrZW50aXR5IGFscmVhZHkgZXhpc3RzYnJva2VuIHBpcGVuZXR3b3JrIGRvd25hZGRyZXNzIG5vdCBhdmFpbGFibGVhZGRyZXNzIGluIHVzZW5vdCBjb25uZWN0ZWRjb25uZWN0aW9uIGFib3J0ZWRuZXR3b3JrIHVucmVhY2hhYmxlaG9zdCB1bnJlYWNoYWJsZWNvbm5lY3Rpb24gcmVzZXRjb25uZWN0aW9uIHJlZnVzZWRwZXJtaXNzaW9uIGRlbmllZGVudGl0eSBub3QgZm91bmQgKG9zIGVycm9yICkAAAAEHxAAAAAAADEiEAALAAAAPCIQAAEAAABtZW1vcnkgYWxsb2NhdGlvbiBvZiAgYnl0ZXMgZmFpbGVkAABYIhAAFQAAAG0iEAANAAAAbGlicmFyeS9zdGQvc3JjL2FsbG9jLnJzjCIQABgAAABVAQAACQAAAGxpYnJhcnkvc3RkL3NyYy9wYW5pY2tpbmcucnO0IhAAHAAAAD4CAAAeAAAAtCIQABwAAAA9AgAAHwAAAHEAAAAMAAAABAAAAHIAAABtAAAACAAAAAQAAABzAAAAdAAAABAAAAAEAAAAdQAAAHYAAABtAAAACAAAAAQAAAB3AAAAeAAAAG0AAAAAAAAAAQAAAHkAAABvcGVyYXRpb24gc3VjY2Vzc2Z1bA4AAAAQAAAAFgAAABUAAAALAAAAFgAAAA0AAAALAAAAEwAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABEAAAASAAAAEAAAABAAAAATAAAAEgAAAA0AAAAOAAAAFQAAAAwAAAALAAAAFQAAABUAAAAPAAAADgAAABMAAAAmAAAAOAAAABkAAAAXAAAADAAAAAkAAAAKAAAAEAAAABcAAAAZAAAADgAAAA0AAAAUAAAACAAAABsAAADLHxAAux8QAKUfEACQHxAAhR8QAG8fEABiHxAAVx8QAEQfEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAhIhAAISIQACEiEAAQIhAA/iEQAO4hEADeIRAAyyEQALkhEACsIRAAniEQAIkhEAB9IRAAciEQAF0hEABIIRAAOSEQACshEAAYIRAA8iAQALogEAChIBAAiiAQAH4gEAB1IBAAayAQAFsgEABEIBAAKyAQAB0gEAAQIBAA/B8QAPQfEADZHxAASGFzaCB0YWJsZSBjYXBhY2l0eSBvdmVyZmxvd1wlEAAcAAAAL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvaGFzaGJyb3duLTAuMTIuMy9zcmMvcmF3L21vZC5ycwCAJRAATwAAAFoAAAAoAAAAegAAAAQAAAAEAAAAewAAAHwAAAB9AAAAbGlicmFyeS9hbGxvYy9zcmMvcmF3X3ZlYy5yc2NhcGFjaXR5IG92ZXJmbG93AAAAFCYQABEAAAD4JRAAHAAAAAYCAAAFAAAAYSBmb3JtYXR0aW5nIHRyYWl0IGltcGxlbWVudGF0aW9uIHJldHVybmVkIGFuIGVycm9yAHoAAAAAAAAAAQAAADsAAABsaWJyYXJ5L2FsbG9jL3NyYy9mbXQucnOEJhAAGAAAAGQCAAAgAAAA77+9AGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWUpLi4AANwmEAACAAAAQm9ycm93RXJyb3JCb3Jyb3dNdXRFcnJvcgBpbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIAInEAAgAAAAIicQABIAAACDAAAAAAAAAAEAAACEAAAAsCYQAAAAAABgOiAAsCYQAAAAAABdJxAAAgAAAIMAAAAMAAAABAAAAIUAAACGAAAAhwAAACAgICAgewosCiwgIHsgfSB9KAooLAAAAIMAAAAEAAAABAAAAIgAAABsaWJyYXJ5L2NvcmUvc3JjL2ZtdC9udW0ucnMAsCcQABsAAABlAAAAFAAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTkAAIMAAAAEAAAABAAAAIkAAACKAAAAiwAAAGxpYnJhcnkvY29yZS9zcmMvZm10L21vZC5ycwDAKBAAGwAAAHoJAAAeAAAAwCgQABsAAACBCQAAFgAAACgpbGlicmFyeS9jb3JlL3NyYy9zbGljZS9tZW1jaHIucnMAAP4oEAAgAAAAaAAAACcAAABy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AQEBAggGCgIBMB8xBDAHAQEFASgJDAIgBAICAQM4AQECAwEBAzoIAgKYAwENAQcEAQYBAwLGQAABwyEAA40BYCAABmkCAAQBCiACUAIAAQMBBAEZAgUBlwIaEg0BJggZCy4DMAECBAICJwFDBgICAgIMAQgBLwEzAQEDAgIFAgEBKgIIAe4BAgEEAQABABAQEAACAAHiAZUFAAMBAgUEKAMEAaUCAAQAAlADRgsxBHsBNg8pAQICCgMxBAICBwE9AyQFAQg+AQwCNAkKBAIBXwMCAQECBgECAZ0BAwgVAjkCAQEBARYBDgcDBcMIAgMBARcBUQECBgEBAgEBAgEC6wECBAYCAQIbAlUIAgEBAmoBAQECBgEBZQMCBAEFAAkBAvUBCgIBAQQBkAQCAgQBIAooBgIECAEJBgIDLg0BAgAHAQYBAVIWAgcBAgECegYDAQECAQcBAUgCAwEBAQACCwI0BQUBAQEAAQYPAAU7BwABPwRRAQACAC4CFwABAQMEBQgIAgceBJQDADcEMggBDgEWBQEPAAcBEQIHAQIBBWQBoAcAAT0EAAQAB20HAGCA8ABBuOvAAAsCaXoAOwlwcm9kdWNlcnMBDHByb2Nlc3NlZC1ieQIGd2FscnVzBjAuMTkuMAx3YXNtLWJpbmRnZW4GMC4yLjgz"; function asciiToBinary(str) { if (typeof atob === 'function') { diff --git a/src/usdpl_front/usdpl_front_bg.wasm b/src/usdpl_front/usdpl_front_bg.wasm index 7bafdb1dd8cf695fbbe3f42a73c1e8726c1286a7..52c1584e18a0f4f4d56cbd7dbb96794e49186b88 100644 GIT binary patch delta 17186 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 z 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 From 5481587167421cdfac1b98f4c0bd4beddc2e9449 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 29 Jan 2023 11:09:42 -0500 Subject: [PATCH 38/44] Fix missing translation for Defaults button --- backend/Cargo.lock | 2 +- backend/Cargo.toml | 2 +- backend/src/settings/steam_deck/util.rs | 10 ++++++++++ package.json | 2 +- src/index.tsx | 2 +- translations/es-ES.mo | Bin 2450 -> 2523 bytes translations/es-ES.po | 5 +++++ translations/fr-CA.mo | Bin 2620 -> 2689 bytes translations/fr-CA.po | 5 +++++ translations/pt.pot | 5 +++++ 10 files changed, 29 insertions(+), 4 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index dac5d74..9416cdc 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "powertools-rs" -version = "1.1.0-beta4" +version = "1.1.0-beta5" dependencies = [ "async-trait", "limits_core", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index edd666a..4d4db5e 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "powertools-rs" -version = "1.1.0-beta4" +version = "1.1.0-beta5" edition = "2021" authors = ["NGnius (Graham) "] description = "Backend (superuser) functionality for PowerTools" diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs index 1d89d1c..def76e9 100644 --- a/backend/src/settings/steam_deck/util.rs +++ b/backend/src/settings/steam_deck/util.rs @@ -1,4 +1,5 @@ //! Rough Rust port of some BatCtrl functionality +//! Original: /usr/share/jupiter_controller_fw_updater/RA_bootloader_updater/linux_host_tools/BatCtrl //! I do not have access to the source code, so this is my own interpretation of what it does. //! //! But also Quanta is based in a place with some questionable copyright practices, so... @@ -95,11 +96,20 @@ pub fn set(setting: Setting, mode: u8) -> Result { #[derive(Copy, Clone)] #[repr(u8)] pub enum Setting { + CycleCount = 0x32, + ControlBoard = 0x6C, Charge = 0xA6, ChargeMode = 0x76, LEDStatus = 199, } +#[derive(Copy, Clone, Debug)] +#[repr(u8)] +pub enum ControlBoard { + Enable = 0xAA, + Disable = 0xAB, +} + #[derive(Copy, Clone, Debug)] #[repr(u8)] pub enum ChargeMode { diff --git a/package.json b/package.json index 847547a..1fad640 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.1.0-beta4", + "version": "1.1.0-beta5", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", diff --git a/src/index.tsx b/src/index.tsx index 04cd538..8dd8cd1 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -263,7 +263,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { ); }} > - Defaults + {tr("Defaults")}
diff --git a/translations/es-ES.mo b/translations/es-ES.mo index 40ddd41615c4c8e89364cbc1524361c36b4d4bb2..ea096f8ec30ae58b4c3e12e03bc29b8d6d651413 100644 GIT binary patch delta 975 zcmZwGKS*0q6vy$C#G1tZu^Q7<`^RYNpNK@dw4#U|q(i3)qJx7C>HlHBSTH#1xjA z<*l2GY6hNS9ABU&n!$Vc&i%fOVfve>33iYi_7gSnAzs5HypI1|KSXx*qs|2KlRd;z z^4lXW^k7$U!0Z`nLA_XpFHs3!qjvNbm3R*8v4DF1E9$uo)CTrZ_y5Lns(ON2sE@%` zEW;4_?J*ac@ClY<4=QmVw&M_L=Znb4miUU{7mVOKD&a2bC=Rd%|GM!6Ss&1E!#MV# z=9|L&EiUq0XaNhT#Gg<*`iv^ws_TDq{Vi0&Jya=wA!liS@CKf`zMm{g97f%rLM^ZZ zb^r4)^;hBn29h|4D)lU?L<^_~H=H|2C5u&1sn0_%t`?%rRM2W@s-!{*6`Dt(m-7xS zp^na9Z?(=bslE#>f?UN_R=F`%M!UHz*ziT@NEF(bs-dH5pef=sRrWTG*TI^!a{bfp z)0$~|<11+@dtG5H@IL4br>90Ib8BaT=|HSMJvyHCa`B0*m+>aO?AXYwbY?ua_9j^4 F{|{JFPRjrQ delta 914 zcmZA0KP+TX6vy$y41*an%wWy>H;jKPLPa*4Z4}B$XjBu4e-VwCh8V>(=rn_ZY$Qk& zB2i33qL8h2yX^#t3hjnQCGq_|w-7h)ywAID?!0sFx$oV^^0C}q)W2=CZlaM$7nu#< zuVPNL1)o_NX0Qdb7{FcRumeuDc!WW`z)t*w8uuSd@CB>z6-zPfH;bF)td@%eH~LWz z7{Mk?zYnl1meb!tJzx)chMl4&R=^NmU?u)_{VUhMcRnMBHycf$gjt2iZy_#pBaY0- z5?FyhPzi@oD;Yy29>+GEL?vEB{V$JNzzJ&n8Ahn)C2FGoNYabfsD3GfeB`$X7ZHr1 z5-0IH_MuijiyW5W6vJgyq778(cd!Rf-TfPEr~ilv43bUH>BTx6L@gwRIVBwBLMut5 zN;v2GORm3)N|;BLa1T|nLk#1w>z|_%U!ul8peFd_eh)AUB@W{^jFwY>mG~z&RGJj( zk6GtBQbF(KY{0LC9;l=VLX%fZ64iuWP&M*-&D(FTv|U)%n!A=ywn`gtnrY(95dr>m)S!DDkoBtJ11fF;&O=u!g1=C+4SSrZ@L}YlVLQ Lim&iH5HEfM4$eRS diff --git a/translations/es-ES.po b/translations/es-ES.po index aef82f0..9477cf9 100644 --- a/translations/es-ES.po +++ b/translations/es-ES.po @@ -39,6 +39,11 @@ msgstr "Guardar perfil y cargarlo la próxima vez" msgid "Profile" msgstr "Perfil" +#: index.tsx:266 +# (Button to reset everything to system defaults) +msgid "Defaults" +msgstr "Valores predeterminados" + # -- components/battery.tsx -- #: components/battery.tsx:42 diff --git a/translations/fr-CA.mo b/translations/fr-CA.mo index caf046af18732111b5fb34f23bd28698dbff11fa..3303e114c921b5f55ebca2c2f90115b49838ca86 100644 GIT binary patch delta 971 zcmZY8&r8#B9LMpuo4RRBOR1Sg1C+`e2W3xMt=5%OBna?3|8<8{zARiRd3dSG1NE-Y{To= zXqLALDi^qM2R(d<8mNGmaMeBEz$V%|r~&qoIqW-X;0lKD7|-H~YX_NK?XWYBJhBmN zWPTf?qK@O$8)lQJ1>M7De1w|t32H|xsEJ=3*fyda5b!?whS_H3Ruk$WyASXD6~O^#!=|w zyhw?wq4U>Qt#cey+l9`XwN!Vh6)TwAE>~-(FWPM_v>}Bus$=Y;Bq$1xqD<=8l(BxT zT>rEl$^b=QyfUEl_pUwmzY1h#(~H@KT=Ad(v%h0Hoy{!H=e)V}yf;&R&!dInr$E8? EACQJkyZ`_I delta 914 zcmZA0%PT}-7{~F48JA(kb;flt?g}Y|vO+0K601qMZG}SF49Y*?l9Ed-ETqJ2EGF3@ zYuU((jg4YqHRby|&O+YKb3W%iopavjdES}TP$C$6De!I^qlpL;(G;@|+)L%enDv-t z;v81tGG^c|a@aAa5T0N*Ca?kTP|tl}8h&FQCNUjzyk@0lF$-}K;YJ(k1A|zB(ccGb z8GX#RP#-uzzG3I6#Nz131P1WlojL7_7Qrm+MlINn zs$>+k@EF$M1Zv@R)O#DK0?ts+U*Ry_ym9A2ZZ>m2j7od}J*;m-T&VRUn1l1E?N~() zJLRMfTw)0(PzgU`3qHI0_^J}<#CGh%MqI!`+(&KI1*(u+jOm33F4Vdw*EdvUU+!G1 zJ9~y|VF)S8%CHC{$fMSUo!Eow;1ULL4aw1VP>CF(o{RhFe*qWo+-SulDxqfH)^Ew=RFJx-#FdP;HlY32-f5^34RWwzqFR%G zL+z|5RFx{JB=lp=B^n4NuY&##ZLQj^4%QLQAFFq2aeQWSdTR5?vmS5rUVGvxnJcM3 DGG#%9 diff --git a/translations/fr-CA.po b/translations/fr-CA.po index 9c38d83..cbc62df 100644 --- a/translations/fr-CA.po +++ b/translations/fr-CA.po @@ -39,6 +39,11 @@ msgstr "Sauvegarder le profile et le charger la prochaine fois" msgid "Profile" msgstr "Profile" +# (Button to reset everything to system defaults) +#: index.tsx:266 +msgid "Defaults" +msgstr "Valeurs par défaut" + # -- components/battery.tsx -- # (Battery section title) #: components/battery.tsx:42 diff --git a/translations/pt.pot b/translations/pt.pot index 44e2e02..be9b1ee 100644 --- a/translations/pt.pot +++ b/translations/pt.pot @@ -37,6 +37,11 @@ msgstr "" msgid "Profile" msgstr "" +#: index.tsx:266 +# (Button to reset everything to system defaults) +msgid "Defaults" +msgstr "" + # -- components/battery.tsx -- #: components/battery.tsx:42 From f4e94d9e7dd2352cb566bf54cb6113d5534c1243 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 29 Jan 2023 11:33:44 -0500 Subject: [PATCH 39/44] Fix auto_detect ignoring persistence bool --- backend/src/settings/detect/auto_detect.rs | 1 + backend/src/settings/general.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index a85e6a5..d048b8a 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -91,6 +91,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa } if matches { if let Some(settings) = &settings_opt { + *builder.general.persistent() = true; for limit in conf.limits { match limit { Limits::Cpu(cpus) => { diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index 9c6afd7..fc8b68e 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -105,7 +105,7 @@ impl Settings { pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self { match super::Driver::init(other, json_path.clone()) { Ok(x) => { - log::info!("Loaded settings for driver {:?}", x.general.provider()); + log::info!("Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}", x.general.provider(), x.cpus.provider(), x.gpu.provider(), x.battery.provider()); Self { general: x.general, cpus: x.cpus, From 11c1fc0ddcd46ebde19762f0e2815f26c5b5bc9f Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 29 Jan 2023 12:00:08 -0500 Subject: [PATCH 40/44] Set settings twice when dirty, to be extra sure settings are set when set and not unset when set set set set --- backend/src/api/handler.rs | 4 +++- backend/src/main.rs | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index f339ff8..dc7d1e8 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -218,12 +218,14 @@ pub struct ApiMessageHandler { impl ApiMessageHandler { pub fn process_forever(&mut self, settings: &mut Settings) { + let mut dirty_echo = true; // set everything twice, to make sure PowerTools wins on race conditions while let Ok(msg) = self.intake.recv() { let mut dirty = self.process(settings, msg); while let Ok(msg) = self.intake.try_recv() { dirty |= self.process(settings, msg); } - if dirty { + if dirty || dirty_echo { + dirty_echo = dirty; // echo only once // run on_set if let Err(e) = settings.on_set() { log::error!("Settings on_set() err: {}", e); diff --git a/backend/src/main.rs b/backend/src/main.rs index 0603a24..f335223 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -69,10 +69,6 @@ fn main() -> Result<(), ()> { //let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone()); let _resume_handle = resume_worker::spawn(api_sender.clone()); - if let Err(e) = loaded_settings.on_set() { - log::error!("Startup Settings.on_set() error: {}", e); - } - let instance = Instance::new(PORT) .register("V_INFO", |_: Vec| { vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()] @@ -225,6 +221,12 @@ fn main() -> Result<(), ()> { ) .register("GENERAL_idk", api::general::gunter); + if let Err(e) = loaded_settings.on_set() { + log::error!("Startup Settings.on_set() error: {}", e); + } else { + log::info!("Startup Settings.on_set() success"); + } + api_worker::spawn(loaded_settings, api_handler); instance From 286ad30378f8577e24bcf7c19f9970ff6237a7ae Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Tue, 31 Jan 2023 20:41:48 -0500 Subject: [PATCH 41/44] Enable auto-detection when loading a new settings file --- backend/src/settings/general.rs | 43 ++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index fc8b68e..42eecfa 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -136,7 +136,48 @@ impl Settings { self.gpu = driver.gpu; self.battery = driver.battery; } + + pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result { + let json_path = crate::utility::settings_dir().join(filename); + if json_path.exists() { + let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError { + msg: e.to_string(), + setting: SettingVariant::General, + })?; + if !settings_json.persistent { + log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display()); + *self.general.persistent() = false; + self.general.name(name); + } else { + match super::Driver::init(settings_json, json_path.clone()) { + Ok(x) => { + log::info!("Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}", x.general.provider(), x.cpus.provider(), x.gpu.provider(), x.battery.provider()); + self.general = x.general; + self.cpus = x.cpus; + self.gpu = x.gpu; + self.battery = x.battery; + }, + Err(e) => { + log::error!("Driver init error: {}", e); + self.general.name(name); + *self.general.persistent() = false; + self.general.path(json_path); + return Err(e); + } + }; + } + } else { + if system_defaults { + self.load_system_default(); + } + *self.general.persistent() = false; + self.general.name(name); + } + self.general.path(json_path); + Ok(*self.general.persistent()) + } + /* pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result { let json_path = crate::utility::settings_dir().join(filename); //let mut general_lock = unwrap_lock(self.general.lock(), "general"); @@ -165,7 +206,7 @@ impl Settings { } self.general.path(json_path); Ok(*self.general.persistent()) - } + }*/ pub fn json(&self) -> SettingsJson { SettingsJson { From e63310f62ebf957c796a13e10622bd8e6f421a73 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Thu, 2 Feb 2023 20:20:16 -0500 Subject: [PATCH 42/44] Add global governor dropdown (hidden for default SD config) --- backend/Cargo.lock | 2 +- backend/Cargo.toml | 2 +- backend/src/api/api_types.rs | 1 + backend/src/settings/generic/cpu.rs | 1 + backend/src/settings/steam_deck/cpu.rs | 8 ++++- backend/src/settings/steam_deck/gpu.rs | 20 ++++++------- backend/src/settings/steam_deck/oc_limits.rs | 16 ++++++++-- backend/src/settings/unknown/cpu.rs | 1 + package.json | 2 +- src/backend.ts | 1 + src/components/cpus.tsx | 31 ++++++++++++++++++++ 11 files changed, 67 insertions(+), 18 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 9416cdc..9115d16 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "powertools-rs" -version = "1.1.0-beta5" +version = "1.1.0-beta6" dependencies = [ "async-trait", "limits_core", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 4d4db5e..72d737b 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "powertools-rs" -version = "1.1.0-beta5" +version = "1.1.0-beta6" edition = "2021" authors = ["NGnius (Graham) "] description = "Backend (superuser) functionality for PowerTools" diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index f70c69a..2107852 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -33,6 +33,7 @@ pub struct CpusLimits { pub cpus: Vec, pub count: usize, pub smt_capable: bool, + pub governors: Vec, } #[derive(Serialize, Deserialize)] diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 0ae3c25..2ae1f5c 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -134,6 +134,7 @@ impl + AsRef + TCpu + OnResume + OnSet> TCpus for Cpus { cpus: self.cpus.iter().map(|x| x.as_ref().limits()).collect(), count: self.cpus.len(), smt_capable: self.smt_capable, + governors: Vec::with_capacity(0), } } diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 038558b..2c7ce0c 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -155,6 +155,12 @@ impl TCpus for Cpus { cpus: self.cpus.iter().map(|x| x.limits()).collect(), count: self.cpus.len(), smt_capable: self.smt_capable, + governors: if self.limits.global_governors { + self.cpus.iter() + .next() + .map(|x| x.governors()) + .unwrap_or_else(|| Vec::with_capacity(0)) + } else { Vec::with_capacity(0) }, } } @@ -358,7 +364,7 @@ impl Cpu { min: self.limits.clock_max.min, max: self.limits.clock_max.max }), - clock_step: 100, + clock_step: self.limits.clock_step, governors: self.governors(), } } diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 8f3f826..3253a8a 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -222,20 +222,18 @@ impl OnResume for Gpu { } } -const PPT_DIVISOR: u64 = 1_000_000; - impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { crate::api::GpuLimits { fast_ppt_limits: Some(RangeLimit { - min: self.limits.fast_ppt.min / PPT_DIVISOR, - max: self.limits.fast_ppt.max / PPT_DIVISOR, + min: self.limits.fast_ppt.min / self.limits.ppt_divisor, + max: self.limits.fast_ppt.max / self.limits.ppt_divisor, }), slow_ppt_limits: Some(RangeLimit { - min: self.limits.slow_ppt.min / PPT_DIVISOR, - max: self.limits.slow_ppt.max / PPT_DIVISOR, + min: self.limits.slow_ppt.min / self.limits.ppt_divisor, + max: self.limits.slow_ppt.max / self.limits.ppt_divisor, }), - ppt_step: 1, + ppt_step: self.limits.ppt_step, tdp_limits: None, tdp_boost_limits: None, tdp_step: 42, @@ -247,7 +245,7 @@ impl TGpu for Gpu { min: self.limits.clock_max.min, max: self.limits.clock_max.max, }), - clock_step: 100, + clock_step: self.limits.clock_step, memory_control_capable: true, } } @@ -257,12 +255,12 @@ impl TGpu for Gpu { } fn ppt(&mut self, fast: Option, slow: Option) { - self.fast_ppt = fast.map(|x| x * PPT_DIVISOR); - self.slow_ppt = slow.map(|x| x * PPT_DIVISOR); + self.fast_ppt = fast.map(|x| x * self.limits.ppt_divisor); + self.slow_ppt = slow.map(|x| x * self.limits.ppt_divisor); } fn get_ppt(&self) -> (Option, Option) { - (self.fast_ppt.map(|x| x / PPT_DIVISOR), self.slow_ppt.map(|x| x / PPT_DIVISOR)) + (self.fast_ppt.map(|x| x / self.limits.ppt_divisor), self.slow_ppt.map(|x| x / self.limits.ppt_divisor)) } fn clock_limits(&mut self, limits: Option>) { diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index da5cefa..47e84be 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -66,12 +66,14 @@ impl Default for BatteryLimits { #[derive(Serialize, Deserialize, Clone, Debug)] pub(super) struct CpusLimits { pub cpus: Vec, + pub global_governors: bool, } impl Default for CpusLimits { fn default() -> Self { Self { - cpus: [(); 8].iter().map(|_| CpuLimits::default()).collect() + cpus: [(); 8].iter().map(|_| CpuLimits::default()).collect(), + global_governors: false, } } } @@ -80,13 +82,15 @@ impl Default for CpusLimits { pub(super) struct CpuLimits { pub clock_min: MinMax, pub clock_max: MinMax, + pub clock_step: u64, } impl Default for CpuLimits { fn default() -> Self { Self { clock_min: MinMax { min: 1400, max: 3500 }, - clock_max: MinMax { min: 400, max: 3500 } + clock_max: MinMax { min: 400, max: 3500 }, + clock_step: 100, } } } @@ -95,8 +99,11 @@ impl Default for CpuLimits { pub(super) struct GpuLimits { pub fast_ppt: MinMax, pub slow_ppt: MinMax, + pub ppt_divisor: u64, + pub ppt_step: u64, pub clock_min: MinMax, pub clock_max: MinMax, + pub clock_step: u64, } impl Default for GpuLimits { @@ -104,8 +111,11 @@ impl Default for GpuLimits { Self { fast_ppt: MinMax { min: 1000000, max: 30_000_000 }, slow_ppt: MinMax { min: 1000000, max: 29_000_000 }, + ppt_divisor: 1_000_000, + ppt_step: 1, clock_min: MinMax { min: 200, max: 1600 }, - clock_max: MinMax { min: 200, max: 1600 } + clock_max: MinMax { min: 200, max: 1600 }, + clock_step: 100, } } } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 909c746..16e5ba4 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -138,6 +138,7 @@ impl TCpus for Cpus { cpus: self.cpus.iter().map(|x| x.limits()).collect(), count: self.cpus.len(), smt_capable: self.smt_capable, + governors: Vec::with_capacity(0), } } diff --git a/package.json b/package.json index 1fad640..75e6fd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.1.0-beta5", + "version": "1.1.0-beta6", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", diff --git a/src/backend.ts b/src/backend.ts index 5bbe0d1..55d05c8 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -72,6 +72,7 @@ export type CpusLimits = { cpus: CpuLimits[]; count: number; smt_capable: boolean; + governors: string[]; }; export type GeneralLimits = {}; diff --git a/src/components/cpus.tsx b/src/components/cpus.tsx index 9089dac..2b9a60d 100644 --- a/src/components/cpus.tsx +++ b/src/components/cpus.tsx @@ -54,6 +54,11 @@ export class Cpus extends Component<{}, CpuState> { label: {elem}, };}); + const governorGlobalOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.governors.map((elem) => {return { + data: elem, + label: {elem}, + };}); + return ( {/* CPU */}
@@ -215,6 +220,32 @@ export class Cpus extends Component<{}, CpuState> { }} />} } + {!advancedMode && governorGlobalOptions.length != 0 && + + { + backend.log(backend.LogLevel.Debug, "POWERTOOLS: array item " + val.toString()); + backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + get_value(GOVERNOR_CPU)[0].toString()); + return val.data == get_value(GOVERNOR_CPU)[0]; + })} + strDefaultLabel={get_value(GOVERNOR_CPU)[0]} + onChange={(elem: SingleDropdownOption) => { + backend.log(backend.LogLevel.Debug, "Governor global dropdown selected " + elem.data.toString()); + const governors = get_value(GOVERNOR_CPU); + for (let i = 0; i < total_cpus; i++) { + governors[i] = elem.data as string; + backend.resolve(backend.setCpuGovernor(i, elem.data as string), (_: string) => {}); + } + set_value(GOVERNOR_CPU, governors); + reloadGUI("CPUGlobalGovernor"); + }} + /> + + } {/* CPU advanced mode */} {advancedMode && Date: Thu, 2 Feb 2023 22:27:06 -0500 Subject: [PATCH 43/44] Update pt_oc to new format --- pt_oc.json | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/pt_oc.json b/pt_oc.json index 410b8fd..3d30b49 100644 --- a/pt_oc.json +++ b/pt_oc.json @@ -6,42 +6,54 @@ "cpus": [ { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 }, { "clock_min": {"min": 1400, "max": 3500}, - "clock_max": {"min": 500, "max": 3500} + "clock_max": {"min": 500, "max": 3500}, + "clock_step": 100 } - ] + ], + "global_governors": false }, "gpu": { "fast_ppt": {"min": 1000000, "max": 30000000}, "slow_ppt": {"min": 1000000, "max": 29000000}, + "ppt_divisor": 1000000, + "ppt_step": 1, "clock_min": {"min": 200, "max": 1600}, - "clock_max": {"min": 200, "max": 1600} + "clock_max": {"min": 200, "max": 1600}, + "clock_step": 100 } } From ec97003e389e5a61ea06291c1d7148b9784cd3f4 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Fri, 3 Feb 2023 17:03:50 -0500 Subject: [PATCH 44/44] Rename 'Persistent' toggle to 'Persistent Profile' --- backend/src/settings/steam_deck/cpu.rs | 1 - src/index.tsx | 2 +- translations/build.py | 13 +++++++++++++ translations/es-ES.mo | Bin 2523 -> 2531 bytes translations/es-ES.po | 2 +- translations/fr-CA.mo | Bin 2689 -> 2697 bytes translations/fr-CA.po | 2 +- translations/pt.pot | 4 ++-- translations/zh-CN.mo | Bin 2274 -> 2282 bytes translations/zh-CN.po | 2 +- translations/zh-HK.mo | Bin 2306 -> 2314 bytes translations/zh-HK.po | 2 +- 12 files changed, 20 insertions(+), 8 deletions(-) create mode 100755 translations/build.py diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 2c7ce0c..2fe0480 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -15,7 +15,6 @@ pub struct Cpus { pub cpus: Vec, pub smt: bool, pub smt_capable: bool, - #[allow(dead_code)] // in case this may be useful in the future pub(super) limits: CpusLimits, driver_mode: crate::persist::DriverJson, } diff --git a/src/index.tsx b/src/index.tsx index 8dd8cd1..ea9eee3 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -226,7 +226,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { { backend.log(backend.LogLevel.Debug, "Persist is now " + persist.toString()); diff --git a/translations/build.py b/translations/build.py new file mode 100755 index 0000000..524bd54 --- /dev/null +++ b/translations/build.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import os +import subprocess + +if __name__ == "__main__": + for item in os.listdir("."): + if item[-3:] == ".po": + print("Generating binary translation file from", item) + subprocess.run(["msgfmt", "-c", "-o", item[:-2]+"mo", item]) + else: + print("Ignoring", item) + diff --git a/translations/es-ES.mo b/translations/es-ES.mo index ea096f8ec30ae58b4c3e12e03bc29b8d6d651413..d6ba246b99a544c2c8d686c3752ea2d25f5a9c48 100644 GIT binary patch delta 455 zcmY+=KS)AR6vy%NdYVuB-dfyF+FINl29WX%hdQ#d^^#JGoB7 T{cybO_Q`SW;ApRN8m&b}HefDk delta 446 zcmY+=ze_?<7{>AUcr|~NX1G&r=iG}jhqipGXZ5{-g`O`^~o zIZIoM1W|(oEz#20_kp`~x!lirU(Pwtx#uICg~Ltfb7pp$GArUartt~`yv7}ja0wr9 z11GqMuc-N-Sa4?Fn4xwwE0{yoHPn6$EMOCr+fJLeI)h^xS-eGF>+xB~dkpaj75IXy z_>Oz{8~1lfDN$E(3)`su&TtJq>Hu9-@Ez)h`WbJQXE2HzkEnWz3Y=jQ=eU4hxQst> zoghWQS=9V})Bz7s^INFkBP?SFb<>xq8|oGrXyGLGIT|GVinjdsLSdI!HA17etHT z*3b}c4gCv3wWN!KgG=;%bW6u^pLg%~?)~2Hnois4#|?K)L~52u7_ZQeT{Q6?Q}}=( ze8CvLVGzGi>!)~Zh|InBJjosMCm6scYQGzdV+U98$uF*K5j>ONmJc2_j&U7l7)6^d zis@ delta 446 zcmY+=u}cDR6u|NK>%7#ubQjs zq^C6T7#~po5u)Iokw>;7;Z4=FCR^d8Z|6`oo(lkIn` KPt(7(9s3`1d?{}L diff --git a/translations/fr-CA.po b/translations/fr-CA.po index cbc62df..bc987c9 100644 --- a/translations/fr-CA.po +++ b/translations/fr-CA.po @@ -26,7 +26,7 @@ msgstr "Divers" # (Profile persistence toggle) #: index.tsx:226 -msgid "Persistent" +msgid "Persistent Profile" msgstr "Persistant" # (Profile persistence toggle description) diff --git a/translations/pt.pot b/translations/pt.pot index be9b1ee..9dc33cf 100644 --- a/translations/pt.pot +++ b/translations/pt.pot @@ -23,8 +23,8 @@ msgid "Miscellaneous" msgstr "" #: index.tsx:226 -# (Profile persistence toggle) -msgid "Persistent" +# (Profile persistence toggle, a bit like SteamOS's "Use per-game profile") +msgid "Persistent Profile" msgstr "" #: index.tsx:227 diff --git a/translations/zh-CN.mo b/translations/zh-CN.mo index 76a86760f612d53ac9768cac51b698d8b98e8a8a..78bd0ade13060e0e3a8c48b74519da37c89555b4 100644 GIT binary patch delta 445 zcmXZYF-XHe6vpwFgqXAnTB}ss!B_-w5F7;Q;2@4Vba0c76$*;zBre$sf?Gi7q@$w{ z+yrszqFWt02qI46<{&uv|LA47-@VJb?=JZ$eUk8ll+~?qY;346u!L?BE1m z;ym_n9CK9vBZi(?AIGR)7%DhG)!z)t`$3)ei^?lTmf9SX3Mpz_Lo#dw)wqdjY~m!g zTz!PPz&S2r7nO61MSMc-dqy2RMCHHXEPlH8e^ELLisI3RvNJ(#SatO}>Oxy?eGe71 z@9GoOA3Q@He1QeL!W!P7F81Kw_fa1(h?%JIJ?r^3Zz;R?7d*>e{hdO>s-ES1C8+vw Q(mXvr=p455?eIGI2cK;$1^@s6 delta 436 zcmXZYJxc>Y6ouitvurjoLQIGlP2mTM3PLK2^cI2GNlFU~3p>dV$Rbz^vW-^S+Xyj8 zsx;cAu?VEF5-U>({(&d@f5f43>Wbl zSMe6}_=M_z#V9ZvV21jgVFib%`kO&{6D;8`D$m81ScOS}6gBQ48CF9z9-SiqLA z&rug><0f`cIgh9h>ZA6(p$`5)<&SU~KmGf^IGG1c{X#xF-&jFy*zxrN>OytDevAq_ z@%07j4_=}UzQP>dU={CB7klyV2dEDiW|^pQoZh=?u#xuMda#?0TvLnx&vth|Tyx!K H^bpPfWw8839*TFkYJ(K!6F6GL2z&oii0}2msBjbI-MFRTDazJpaR;cg&nUCy*@)- zV1TQ5h01xtX?#QN`$8Q&LgoLUa>qVjP4Y=lJ(+B1x$CG6TVC&=4(Ry!F)FC<^*QPf zUZW1aL%sAK7w{Q%u}`1>Mm^v!rIXUJw73l$L92KS7XvFk!rio~VZP;ZC2E98bH9Ij M)H~^x+wm~^2eV)+rvLx| delta 437 zcmXZYze@sP9LMqJ?l?V5L5_m5AdyfE+(c+-YtlKI8lo-eA85G{DQJsZ#NEk7k*Lk7 zB^q-U9D*SC#@?U&-tfGh@AKpHJkLGG-FUp^B^%DUa$Pf5FgmZiX4^H=1qyK-Ehc<$Ys}D^wnv6Sso}QnavYHc$ag)WWva=T_gKE^v!S zc#q1NpdR#&+BZiXyhP=Hp>kI?A4JJIs2Hs`?3;DehL+VQr~}$IeuWCUw)zhB2Om%e z_fan$;vT-DF7|2j3)BOCa&&TZexr2Ym%MWN>>qfwbnbUF`u`nH>p{t%cEVZk2mK2u AEdT%j diff --git a/translations/zh-HK.po b/translations/zh-HK.po index 5c14851..1840a4b 100644 --- a/translations/zh-HK.po +++ b/translations/zh-HK.po @@ -26,7 +26,7 @@ msgstr "其他選項" #: index.tsx:226 # (Profile persistence toggle) -msgid "Persistent" +msgid "Persistent Profile" msgstr "持續" #: index.tsx:227