From 750379202ecb8c04316ff17b8bae4ff92759caed Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Wed, 29 Sep 2021 21:40:35 +0200 Subject: [PATCH] Initial parser for butlerdb --- Cargo.lock | 2 + Cargo.toml | 18 ++++--- src/defaultconfig.toml | 3 ++ src/itch/butler_db_parser.rs | 73 +++++++++++++++++++++++++++ src/itch/itch_game.rs | 35 +++++++++++++ src/itch/itch_platform.rs | 86 ++++++++++++++++++++++++++++++++ src/itch/mod.rs | 8 +++ src/itch/settings.rs | 7 +++ src/main.rs | 11 +++- src/settings.rs | 3 +- src/testdata/itch/butler.db-wal | Bin 0 -> 593312 bytes 11 files changed, 236 insertions(+), 10 deletions(-) create mode 100644 src/itch/butler_db_parser.rs create mode 100644 src/itch/itch_game.rs create mode 100644 src/itch/itch_platform.rs create mode 100644 src/itch/mod.rs create mode 100644 src/itch/settings.rs create mode 100644 src/testdata/itch/butler.db-wal diff --git a/Cargo.lock b/Cargo.lock index bc03c9e..b23f2ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,6 +1092,8 @@ dependencies = [ "failure", "fl2rust", "fltk", + "nom 7.0.0", + "nom_locate", "reqwest", "serde 1.0.130", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index fd88dde..a7ee26a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,16 +5,18 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -steam_shortcuts_util = "1.1.4" -steamgriddb_api = "0.2,0" -serde = { version = "1.0.130", features = ["derive"] } -serde_json = "1.0.68" -tokio = { version = "1.11.0", features = ["full"] } -reqwest = { version = "0.11.4", features = ["default"] } -config = "0.11.0" -failure = "0.1.8" +steam_shortcuts_util = "^1.1.4" +steamgriddb_api = "^0.2,0" +serde = { version = "^1.0.130", features = ["derive"] } +serde_json = "^1.0.68" +tokio = { version = "^1.11.0", features = ["full"] } +reqwest = { version = "^0.11.4", features = ["default"] } +config = "^0.11.0" +failure = "^0.1.8" #https://fltk-rs.github.io/fltk-rs/ fltk = { version = "^1.2", features = ["fltk-bundled"], optional = true } +nom = "^7.0.*" +nom_locate = "^3.0.*" [build-dependencies] fl2rust = { version = "0.4", optional = true } diff --git a/src/defaultconfig.toml b/src/defaultconfig.toml index 6d6d461..b9f58c2 100644 --- a/src/defaultconfig.toml +++ b/src/defaultconfig.toml @@ -6,5 +6,8 @@ debug= false [steam] +[itch] +enabled = false + [steamgrid_db] enabled = true \ No newline at end of file diff --git a/src/itch/butler_db_parser.rs b/src/itch/butler_db_parser.rs new file mode 100644 index 0000000..15f8e36 --- /dev/null +++ b/src/itch/butler_db_parser.rs @@ -0,0 +1,73 @@ +use nom::{ + bytes::complete::{tag, take_until}, + multi::many0, + IResult, +}; + +pub(crate) struct DbPaths<'a> { + pub(crate) base_path: &'a str, + pub(crate) path: &'a str, +} + +pub(crate) fn parse_butler_db<'a>(content: &'a [u8]) -> nom::IResult<&[u8], Vec>> { + many0(parse_path)(content) +} + +fn parse_path<'a>(i: &'a [u8]) -> nom::IResult<&[u8], DbPaths<'a>> { + let prefix = "{\"basePath\":\""; + let suffix = "\",\"totalSize\""; + let (i, _taken) = take_until(prefix)(i)?; + let (i, _taken) = tag(prefix)(i)?; + let (i, base_path) = take_until(suffix)(i)?; + + let prefix = ":[{\"path\":\""; + let suffix = "\",\"depth"; + let (i, _taken) = take_until(prefix)(i)?; + let (i, _taken) = tag(prefix)(i)?; + let (i, path) = take_until(suffix)(i)?; + + IResult::Ok(( + i, + DbPaths { + base_path: std::str::from_utf8(base_path).unwrap(), + path: std::str::from_utf8(path).unwrap(), + }, + )) +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn parse_itch_butler_db_test() { + let content = include_bytes!("../testdata/itch/butler.db-wal"); + let result = parse_butler_db(content); + assert!(result.is_ok()); + let (_r, paths) = result.unwrap(); + assert_eq!(paths.len(), 6); + + assert_eq!(paths[0].base_path, "/home/philip/.config/itch/apps/islands"); + assert_eq!(paths[0].path, "Islands_Linux.x86_64"); + assert_eq!( + paths[1].base_path, + "/home/philip/.config/itch/apps/night-in-the-woods" + ); + assert_eq!(paths[1].path, "Night in the Woods.x86_64"); + assert_eq!(paths[2].base_path, "/home/philip/.config/itch/apps/islands"); + assert_eq!(paths[2].path, "Islands_Linux.x86_64"); + assert_eq!( + paths[3].base_path, + "/home/philip/.config/itch/apps/overland" + ); + assert_eq!(paths[3].path, "Overland.x86_64"); + assert_eq!( + paths[4].base_path, + "/home/philip/.config/itch/apps/night-in-the-woods" + ); + assert_eq!(paths[4].path, "Night in the Woods.x86_64"); + assert_eq!(paths[5].base_path, "/home/philip/.config/itch/apps/islands"); + assert_eq!(paths[5].path, "Islands_Linux.x86_64"); + } +} diff --git a/src/itch/itch_game.rs b/src/itch/itch_game.rs new file mode 100644 index 0000000..25cb5c2 --- /dev/null +++ b/src/itch/itch_game.rs @@ -0,0 +1,35 @@ +use std::path::Path; + +use serde::{Deserialize, Serialize}; +use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut}; + +#[derive(Serialize, Deserialize, Debug, Clone)] + +pub struct ItchGame { + pub install_path: String, + pub executable: String, + pub title: String, +} + +impl From for ShortcutOwned { + fn from(game: ItchGame) -> Self { + let exe = Path::new(&game.install_path).join(&game.executable); + let exe = exe.to_str().unwrap().to_string(); + let shortcut = Shortcut::new( + 0, + game.title.as_str(), + exe.as_str(), + &game.install_path, + exe.as_str(), + "", + "", + ); + + let mut owned_shortcut = shortcut.to_owned(); + owned_shortcut.tags.push("Itch".to_owned()); + owned_shortcut.tags.push("Ready TO Play".to_owned()); + owned_shortcut.tags.push("Installed".to_owned()); + + owned_shortcut + } +} diff --git a/src/itch/itch_platform.rs b/src/itch/itch_platform.rs new file mode 100644 index 0000000..01d0fa5 --- /dev/null +++ b/src/itch/itch_platform.rs @@ -0,0 +1,86 @@ +use super::butler_db_parser::*; +use super::{ItchGame, ItchSettings}; +use crate::platform::Platform; +use failure::*; +use std::path::Path; + +pub struct ItchPlatform { + settings: ItchSettings, +} + +impl ItchPlatform { + pub fn new(settings: ItchSettings) -> ItchPlatform { + ItchPlatform { settings } + } +} + +impl Platform for ItchPlatform { + fn enabled(&self) -> bool { + self.settings.enabled + } + + fn name(&self) -> &str { + "Itch" + } + + fn get_shortcuts(&self) -> Result, ItchErrors> { + let itch_location = self.settings.location.clone(); + let itch_location = itch_location.unwrap_or_else(get_default_location); + + let itch_db_location = Path::new(&itch_location).join("db").join("butler.db-wal"); + if !itch_db_location.exists() { + return Err(ItchErrors::PathNotFound { + path: itch_db_location.to_str().unwrap().to_string(), + }); + } + + let shortcut_bytes = std::fs::read(&itch_db_location).unwrap(); + + let res = match parse_butler_db(&shortcut_bytes) { + Ok((_, shortcuts)) => Ok(shortcuts), + Err(e) => Err(ItchErrors::ParseError { + error: e.to_string(), + path: itch_db_location.to_str().unwrap().to_string(), + }), + }?; + + let res = res + .iter() + .map(|paths| ItchGame { + install_path: paths.base_path.to_owned(), + executable: paths.path.to_owned(), + title: paths.path.to_owned(), + }) + .collect(); + Ok(res) + } +} + +#[cfg(target_os = "linux")] +fn get_default_location() -> String { + //If we don't have a home drive we have to just die + let home = std::env::var("HOME").expect("Expected a home variable to be defined"); + format!("{}/.config/itch/", home) +} + +#[cfg(target_os = "windows")] +fn get_default_location() -> String { + let key = "PROGRAMFILES(X86)"; + let program_files = env::var(key).expect("Expected a program files variable to be defined"); + format!("{}//Itch//", program_files) +} + +#[derive(Debug, Fail)] +pub enum ItchErrors { + #[fail( + display = "Itch path: {} could not be found. Try to specify a different path for the Itch.", + path + )] + PathNotFound { path: String }, + + #[fail(display = "Could not read Itch db at {} error: {}", path, error)] + ReadDirError { path: String, error: std::io::Error }, + + #[fail(display = "Could not parse Itch db at {} error: {}", path, error)] + ParseError { path: String, error: String }, +} diff --git a/src/itch/mod.rs b/src/itch/mod.rs new file mode 100644 index 0000000..2e2b7c1 --- /dev/null +++ b/src/itch/mod.rs @@ -0,0 +1,8 @@ +mod settings; +mod itch_game; +mod itch_platform; +mod butler_db_parser; + +pub use settings::*; +pub use itch_game::*; +pub use itch_platform::*; \ No newline at end of file diff --git a/src/itch/settings.rs b/src/itch/settings.rs new file mode 100644 index 0000000..2115f89 --- /dev/null +++ b/src/itch/settings.rs @@ -0,0 +1,7 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub struct ItchSettings { + pub enabled: bool, + pub location: Option, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a354ea2..63ace47 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,10 @@ -use crate::steamgriddb::{download_images, CachedSearch}; +use crate::{ + itch::ItchPlatform, + steamgriddb::{download_images, CachedSearch}, +}; use std::{fs::File, io::Write, path::Path}; mod egs; +mod itch; mod legendary; mod platform; mod settings; @@ -84,6 +88,11 @@ async fn run_sync() -> Result<(), Box> { &mut new_user_shortcuts, ); + update_platform_shortcuts( + &ItchPlatform::new(settings.itch.clone()), + &mut new_user_shortcuts, + ); + let shortcuts = new_user_shortcuts.iter().map(|f| f.borrow()).collect(); save_shortcuts(&shortcuts, Path::new(&shortcut_info.path)); diff --git a/src/settings.rs b/src/settings.rs index 7d9f916..f769274 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,4 +1,4 @@ -use crate::{egs::EpicGamesLauncherSettings, legendary::LegendarySettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings}; +use crate::{egs::EpicGamesLauncherSettings, itch::ItchSettings, legendary::LegendarySettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings}; use config::{Config, ConfigError, Environment, File}; use serde::Deserialize; @@ -9,6 +9,7 @@ pub struct Settings { pub debug: bool, pub epic_games: EpicGamesLauncherSettings, pub legendary: LegendarySettings, + pub itch: ItchSettings, pub steamgrid_db: SteamGridDbSettings, pub steam: SteamSettings } diff --git a/src/testdata/itch/butler.db-wal b/src/testdata/itch/butler.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..2f735526719de833c2953f1b038bc81cbe638002 GIT binary patch literal 593312 zcmeFa3w#_`dH267$-3`O99vNw#bm7DCW?2pJA2h`ViMU_9L2i$vWjDcu#9#`+ObD7 zo1Iz7vSX<1B#;96mjETS1qx}Plu{^fp@rT&M8y3C$AXXc#moH;Y+InO2e`qq=4;6GpP@m%6zpSy;QXW#SSHx~Z- zj$QZs_?5r=SxWLc)1UbJ#lJZ93pW=J>>HB}iJ#R<^P<5=sdQ75=O&(~yiN4m%*s?g ztbB|8h5nnzb9`^K+2k4A`KXV3&eP;idHgBv3ym@%4Fo^{1V8`;KmY_l00ck)1VG>% zCU9!Kx2?Cg*L$DW5N8xACoV|3`KM{;{*mF#2%j0=F*d@RN&K~Pp3jWjp5Z4Z>33>u zEWpo+^HP?QM<+5PyGQm1c4XvCjtlXnZIZe&$*-}}pRZ~|r z?bynk3sNaB=M1xr0ls!3T|Oq&idNFIik1@%SyNey7?o;??5w8brBYTUHkCcOvTkVe zS-Yr}p|Wr9{?YN_{fGEHBZnB_fq{Xh*52*CUXQHirK9>?3eD`ZV%gBl?^*LwWCimd zo7cBjdKa7LSLFpi`jGhK*M9rMZ}721OO(L2@Bsl3009sH0T2KI5C8!X009sH0T8$_ z2{0K!v#m#vX)@k<9qAhZtzKmY_l00ck)1V8`;KmY_l z00c||Z0&!YEf@HcM>h5U-Qj;7haCZW2MB-w2!H?xfB*=900@8p2!H?xToeRcb_B-m z#jh;?_g{T`4LgEX2N~v{;H>Qk)^#VUb_BGE4+ww&2!H?xfB*=900@AeU?3IVzSF9ADa@FTkSCLtmh`*L$DW?B_XgLDJ1XO|HIeCN*-42z>!HTe*`1yzSO; zR#Qla#i{g?E0apiJPjbaAu6^)!D{X#2bx-YxA(4gH=CCtE13V7?!P^^Z(}2;tuOH8 z!cC72effrU&=)vIo+qdV2!H?xfB*=900@8p2!H?xfB*=*xCEGdpxu@W^!~-cKiA|h z{TO}+UtH)oItYLO2!H?xfB*=900@8p2!H?xoFfEWb_CtOe)rSzyIz}E!;Zid8&vAg z;u)N^9YIIu(h56*&ZVx)&k-`H1_*!v2!H?xfB*=9z>7~{`O5aT-mP1`%g0SU*40#U?d+_!S;6_O6LtjfJ6Pw8(AC%E{J;SG4#JM$T(KkQV1vD_FYq^i{M1h$ zJHAbV9l?wL2*epc00ck)1V8`;KmY_l00ck)1VG>%Ai&oCJ8ikZm6w-)D!=-+KZ6~? zIdElA1rPuM5C8!X009sH0T2KI5C8!Xc<~9i> zgwG7`7#raop8gS!pyF$t8I`EwylwQ6m-V6|E;&85>+&(F)=_f>QB@_ynPH|ZD|tsp z5Af9>4*|YdlC%=}e&=^gPL7QXPXze9G_TdZEy`+MThuGHQDn7zw6d+~_7>t1ARa+x zbbKVhFG!`loHHstq!K)U0))8xs2x;5(Q+aiX3vp$1YPVgYwHXA$3*L0e-pXlf5DF6 zB7ONlvq1m^KmY_l00ck)1V8`;KmY_THUezzzuT4zynl)t_~<`;>4&f*xY)V@+6w|8 z00JNY0w4eaAOHd&00JOzkrHs(5xnCg+c*4J`p)(>>M{Vy86snIqV2( zu?Y~5U}7@EPfU%C1$b@dF!ecG``BR{Vj3cl+OlXkx}&RGRf;l2ddG1F2I6h4y`xvJ z7Iwj5;E)v@U)oQ;YF%4zU!V7$1LoaTF>Lq z9i&S%%;)uNsqC<<(p616wle2=ZAZZ7_&!@-VExR2cYWAs=h$mqwQ~X zoCljA00JNY0w4eaYZ6!<^R@Lxqu!G@I#>>eA((2 z-<+2eeh2dbo>W7~pJK=9{3+VqFfSTnt^cuaoy*%=+j_6Q+Iw=dc{@5**&Um0uG`PC z1AYf9S~>7LC@MQ(0DcGk>=nb-7YMb!rEkxBkM=-cV9ggVWB>sW009sH0T2KI5C8!X009sH zfeV2ETl?p1xj^sizxVy&?(c=*ckn{Ev}gkefB*=900@8p2!H?xfB*=900^u}z-349 zPycn-Lwo+`@a{G22rh9PwS%_L+KzxDuZ8{;_XXdg??>Hs;!(yyNYiH?=>- z>y~QopH3?J$&B5S6lhW4dl6y9>#%Bgl$n zLzC6KbTsQQaDd;zqZOrmO}Dqsd}w#|HKxdaqPeX%6!I<)n8qe`TKaVfup`Jj%%TE3 z{0?RUd|j^^Xlm`<-n*K4i0J|{E13V9>HUiN1z;aG$G^nZ7kFdO$Q9rIQugDpBQV+E z4+ww&2!H?xfB*=900@8p2!H?xT<8Q``U1cHd*ArV{^BF|uAwim-T{S~9Gtbjz$LBI zYv>D527EvO1V8`;E&u|{S6^Z}COWy*ie*Ky*>tx0t*>{jzMDy_th=*)Dy^bdR%-IH zUR1=TtRtyhQYt%h8U+i=*1qe8OpcpYrq+qrp)W8tQuX`iSa65m!CFWy#3|(Wj2z;x ztppGY@KxW1ych==Z|e)Bm#=-rXC8eW;uKy0Z{TPG2!H?xfB*=900@8p z2!H?xfB*=b0Rfl3z%B26aN*GYuRODczQ6{@al2^ytn~#hZF&Ei`T{NQZ@tEGK5T*j z2we08PBpD>>%HnK@4W}ig(Z^WtBNM(_3Fl@uJz|?vbhGG8M!^+U&`7EAKA<&oKvq!(&m z>z37pOIv$Ku3F70$gAx%}@~8j%x<}>DAx`1Naq-bg z5C8!X009sH0T2KI5C8!X0D+61fXj|REI#{q-uJ^lS;LNCqk~#EZJ)Ir!G`8%&&ZB| zvf%>)An@W5SPpDx>)p1^dy=cEsY>%Rq$$rFJ(Y9vC>#)7m>XyqY+F z^=4;<)%RTneF4i`U%i(t_#K=a8yTJm@UGs-7Ny~La5yuu zQoG-0OOjrweXUbGgdG9w2v{&_=i{iN?R|#NDp!}PnPO0{bU#;MM*uql*b!uzhd^_< zcHD7Qe}OA^nEnA*nkBhzIQShL*&pDmP}z_pY4ivz)t-5IXe6?O#YjL-oU0Ra#I0T2KI5C8!X z009sH0T2Lz7n1;6`@h_l3;e<7-+Rv^pZU()VMp*{BFC{o00ck)1V8`;KmY_l00ck) z1VG@NA>gtjC_nJTvwy$!?#VUm2>Kkg=V<$^>++7bciz%P(FJIYiHgfs6%OsQHbcnXqA=^eg0>mRg zJOaJNb+6lYgSLsF_55T;g3g;6@d#AaX)9Tww$cV*_1Aa3QS`A3$Buxe)>km!0Grqx z+twGj^?z{#cRVV+A9e(c3O*nJ0w4eaAOHd&00JNY0w4eaAaKDGxPrCNmJ9s#Q`dgA z^qtwy`)FC--}dP9^a*$_uI0ZJ*RRR&cERr;t?>*DaL=u~|1A9uQqhUt;bHHoL)IFd zxFBT3ZmzT3KPPUmep8u~ZjUepXgZ zr<_^Q8L?I>m9$djK;||rP3NUrPqEUd59{Kbz25EYiUIyCd*FHFcaVF|Tj=fW^`6{n zUN=)O!2Gk`b-kc3kQvF0j*nO!qRxvf!{Zu)T1Getv4F=p1jfIY%jLfmgMyY zNq*NgXpn&h&Z_E!f`O&&VM*W|0mH z^aV_{MCc2+SAgMnFzZki)8%81=Ph~ErqyA^nW6sm4SokJBg}A1YwuKOH7%byb%d-? zm$dHGdT$$hyx-?FA3N;b#(ZDbn_Q0;GriHPSl#Q7bktzlfl9V+&l$a%&ugV(fjlzT zTt^mV=nF_$v21AMLsL4MH7`Y0F#k2vY`MKMV`er1eYRZSZ8zTb3s>*?^8HL-ptJ3V z9`05ChkP5lzuql$wRL{HF z6dkv~ZeCWiMG`PO=M18nosqILTA7(L?UvlqJ79~+$R$tN$X}*^A zOuUn?Ey4MDOz#i~Nme9tLE=D9Ywz6fYI7R)*4ucI!FnTZyzerENIKJ{isitDw)1FJ z;Vc5_oN8L%hJ^^*0F>5BUXB1r%U54wKBBOyAl9u^m5U@XU1<(sKCD-Upj-QyL@zZi z{{l~cXzAWJyz`Rh*6=TIrQ>Dj6557;0mLb^9?w6|OU^YL+n_Jtew}qMr?HnCwsQ2M zyaSzQPj)<}Yb&x8Cg)pKB z_8U=AZm?A+be~HAV((o=1|k;a>=9|HBI+>J!*Uv}Mdj$_jNe58EG>PHx|guLv>+*3 z(HRVl!lRMcf#s|T9b7{{^abEwfI1f96p|Rop&US=byvEUfxbW%{sn6KXwVlJ7#L`3 z?cLscI+3aF&=;WTyy;)S^dV^L3+x%X=i|4Z`rb9R009sH0T2Lz z=SyI@XOp$)(P6I3>!QN!O6bp(u4$>6w91^cPN}j)O9lM?k>N2@MntRgZ0*1?JC#(^ z9>|$gH}QnN0Q3bY7`M~zqas?Vi6EUj>x@DcWNER^G#mJ7V=qrcnI z|I}qU_#J${FMG%j0w4eaAOHd&00JNY0w4eaAOHgAB>|Tm!Hpki`L*xP|DS(f!;WCH zqowO<8+HV+BY+)2wp4a_)H>h%4#JMWvTcUn!P+w2Ea^8FYG3PCm|;gi>f(IHjI8KT zS6^k3-)V9WJAx5fnhv<5@zoHLxs-c3c*Nh@dnme^E~M@3uyz2_jBJnyJA!%kn6}ky z9gF{UPP`oZ>PJM^Ku}%2uO0(&3JtN=|Cpb|&gE^bR^ZdkrjF38WaJ82S)J8%$7Y*L zU&yh8zqaCBur;RIteg{dq z)?hem6lDEHT&g(FRu#@dpba~Mnm`eD1f^`v#curr{zlFc0*;ukDh_G2WAhT%ON(R2 zDsL_?>8b*~(y_Jw&9)uE|L|}7_e*ohR@f1|G%ve23kZM!2!H?xfB*=900@8p2!H?x zyvzh#b_9zMGjnl_L)fKzx4=i0{v0*#(}1UK-Cqh(`cBg0T_a z94{>efBkgha@7XF9*Z4gHtYzPRSSilAp3}p*4{l^*D_~emIJUOkSg7-@~_pkK3eUP zwWpY)$LWSv66b7{qJpN|0ZwNTk3dmsh5{`vrm{*(Z_eH3$}>}MbD%AX^!{b3yw$C9 z54W`TPK8$M-F1i03Ux{APObNvK6UT&T1({=LQ7{sLiHwBRn4SE)m!oA7~mC@7sQSrlYhfIKKL;)<7<7B$G`3itJ)E)`$FrOLpFd-5C8!X0D*In zz==LHwDhuIKC1OxL7Eq{6|H!E#n)H39^Wf=HhPfT+Vxe@PTkwa_A6U^_ibD4ZDYkL zvcif4CW3BfRAEQpc)P26NkTk=N?5?EGkbTy*LhjZ7E5wYvgf@NDpFLlGg5X&D>KpL zj>*Zf5yT@vJc6tl`Oc8%CH*qQBS1U?#3N`l-+q|_BV$$JrCC*=_pMj3moD3mK>n*e z*S|6T@n3@-0i%Ks2!H?xfB*=900@8p2!H?xfB*NTg#h*Ri};An=i80c*4-MZC#vd6RsG6#x^nYMGg z%Vi1V+ynmt0luHy1oWFjt)tH_h)UTuW_OuE)jBi$3y5VylhwR*H0ubUm=zpf+E2b} zU0ZKopZA^vW)H1&&dNXd7ciu}+qlWq*Vrw7qPeX%6!I<)nEdLj_v;eiUm))YyV}U! z0saME5dQ)nKlIKmw{L!35A!d;t=o87{{pld9}oZm5V$A^EGIUb(!Z12%%^rYH30+Duv{m{KixlQXQ6UeHQL)*u&B72#Jk3_Dr*Q}8rh zo|SW=!9qh;fj$x(R}-5T8MyuftSp`08cOV zylqGD2mg6c`(yva_u*gQqL}KSksts9AOHd&00JNY0w4eaAOHd&;Ibq5P5xt%M|Lb; zy@nk@zXKc78h{-E>d%wudVC8M$76H->>0%xmc8$u24nAfz%!hS}IpnDM$Lk{I056Mp<8> z&y$xHBt}YhMvTP53t(~voMS~r|{?YN_ z{fGEHBZv5FwVA`zU9(JmC%{*}u&x$wYwaDqdNt(>hv@+92#!|ne@(Zy8mcjsi_|$` zM=-)?hIdf-RKzK)#l=}^9m149Ewwp&&#b28=^>($?w+ksS0>e``K&ubWnbNcW1y+E zcYE(@ce8mZEUhWM*_zj1;ivz7Y}?is*fO?d^#2=t-!Cycg7wXxU&D@|`SUGLSVzKN z5CDO5lfcQASG4s8gWgluoA1K4*JMlIbmjLgu2-&=d--b}DGlGeDq5cQxaTnAtXDie z^GE26QZCI@2EMvCZP!TXs$akg;LYB3ZoI0s_dsyf(NR+rdPO2tW{V09lq*vDVMl;C zg$`Bsl2reqcV=&Y%RQS+ef^Ui<_)Qf3iCHXf39@hdS=opbJ7(zS%62JLc}SQ>>06X zI^g;OI|B0I0y_dGyE3#gMXFt4>AuQ?Sb-fu#ad9`aH?s2Tklm@dGEEHCsZZf)s0JC zqjxpA(L1~Rux{FRRx;KY+q0w3w-p}zaGEowTIrx z^aZ@!e|YEz9}oZm5C8!X009sH0T2KI5C8!X0D%jG0OxJq+`_!G%usxoJAROzqh?)2 zzg2yK_urb^^^KjWKV|v?UhW4T`oRYTKmY_l00ck)1V8`;KmY_l00cnb0wU1Wyt%`c z4N$YpSOT`bz<>VR?ym{=-ha^27x+gH_m3A)!_gEF009sH0T2KI5C8!X009sH0T8$- z2wdxJ?i&@0EHs7~Droaks92B{xfmLxKsvMXTu3%@g%D-X3CBA6t?CQh^-toSgKzKs zS4&^uhaT>S7X>gh5(Gd11V8`;KmY_l00ck)1V8`;E*=7%&3zpesR1?G3_W1$3mn{} zw2$`u!2wHO;KLs7!xs-0v=jtD00ck)1V8`;KmY_l00ck)1kPasdzT;i)WJ5-oukbi z?YGYFR0^^EnT0ud;g$o5^3cuuQ^}nNQ+ra{QDM3`zJG6gTFV@qi-aRWFq{fTQW+td zjt-^c@xfF~hzQAKI5j=+>L;na>*=?uFYwy*`+Ki@+on-VF7T9xd+Hn}f~tW42!H?x zfB*=900@8p2!H?xfB*bhj;L1B-Xh2KqS z{IHqE3z2Xj91d^eSw`N<$j@pezN|~Utny1*xn%Csx8$W+v8)(Y9{a5F{G4^lW11?3 z#Dju5c5GCb+_f(};Yd(OWQ1fo z7E24lv@?y?08{B$axg3;qA_8*`Cm@9-uva(ZuHzK%=PswU*n6%2|)XX4I8QeW@YuT zTy4K9&lQZItOkvO6kOD_ygtEFSeqz?Kgd#s4Rc#k^Sn08OAAtI$tcL`T!1fV3Zn3p{O!FQvs0( z3gKWRkqJlAk$5^h#6VbS$xJwr4hzI*y6sD%qF6sC0}nr1?D0(AxV*dXn&tHt3s+|_ z+jM>2gj~vZsYeJ!pJ!a@Tltl6sJ+?r`;>nb3|s!v*!o;Nc=$H4X>E(O@{95fW)3 zmX0KdoHH$!O2?zq>%Ox5n&1C%c%x^sPo};@H&48s`i}GFQ6+6&JS-m(tFX$dZj{xz zDeK=(>I)@J;d5m}A{LU)`q6FsxA52AO!vxUuB?=GeqUMA4N4t2ldeLoJhVvnNO(Mx ztG`c*`}W;h+GTYQYLF0N-6IlB3q$E}#A+lfgd#!hIw-HuSkYg?4PqPxG-eiDzQu?oMu1f zt&*yAf=DDCqkfQ>_OfULJpESn1=d~mC;$1xyB~eZlneO3>G6M)yONvY9^gKE-i-gK zCbL^lFr57W}8>ORa(}-DPKflk%Toxb{gF$2BXn|Sr($i~ZO+^!l z*lF`_Yia4(WafW_rx4T%< zW@SanYKy9r&mNJM^hi<&Cu7mmmZi(tPQO)sfxr9yTfY~7c)Y;k5wvpe@Nn3{f;kBh0t$q?znBPo6#X628 z2If~w7SU4uZiyS3tKTh&Lepjv8g#5GG$1q`43DiZaMRO|eB?ii-_Kiq2XFFlH?h6= zfB*=900@8p2!H?xfB*=900@8p2s9$FyxqI5dCSQhspQ|pT=|8_$AEskKUXf5B-Q9o z_sgnm$f6RY^!`Aeb0u_0tB+`yRKl!nc zXvZD>x}2A0#L}R>>&_E*2JEwrs(I;Xe>xoK*Tn@XKX#fjC#X$KHK3|5U=%;vJbSe1 z2A1gMzUQGId_VvMKmY_l00ck)1V8`;KmY_l00b@w0_$6vw{*Bf7}PALFHn^Wyz})B zEU*9jFK11C0sqfD^n(uwfB*=900@8p2!H?xfB*=900>;D1eRaNmitdhuDSBdvfLjy z-rq<^AY{4=Xrw7n*`bydrGc`5u$r=fyBO0KaQPjK|I3qKSlsZAyO~^|&Hr02zk~D@ z9}oZm5C8!X009sH0T2KI5C8!Xcv%SC(AE;|8@0{kbDE+^IYZXe#?JL(6qJy>_{G9Q z;aE7CoQB`Q@G5Q=>0-M44u0r;k39FcPrW-Y1g;_(hj(=uN83y9cd%+lF!6;`(Kl$H`mAL~aKFcY|Ahu0?EwK0 z009sH0T2KI5C8!X009sX_M**7i=SpNvksUm&rXXyA1E0=}p3{lV0;;eaI$Rdss{of00JNY0w4ea zAOHd&00QSffqRazY5o0oVp@MOPwQ986KvywGtwTY*B3~xCKOmhU*Ocq^vtfm`tv`x zU~7oPonvK%hTYE|nzJ7*+Gq(f;(%YNiB^ zGAtee69H7?6mI#^mg8^yr9bv8LTMY&`p(2fwj!*B^i6pVmG5 zm!D#Cf%dlF@N_=W_8T2fbv@Dk1^+YMU-NS;FFqgu0w4eaAOHd{4}p`{o_hN79?$6J zWx20sne)ZtO&#s+8#ZicFBnEqC&R>9Sv@QdGAqSFSqo_kQb`fj{AA_-Ft6WL7W2Uw zQJ3<(UM?-j3!=j7MoBcJxg~y1oR|1T*(mVEl9rS5<&vl=tD&e6KN^XLw??A5P$G9%>elFBQKeTJArTD6fEID0G zOJ%~5bSy!yIn!-lq8eL2CtDx*tDzpx+TdM-Pk* zPwYC7rfaJP_bOse(y14*r6}q+MoBL6MxmsY=L+;+qQ4>IKPQB%BEg>3B39jat1x5Q0LIz3d7} z)-$}%R(rwn-47ny=*h*!zD?|g*-1A{htJUmj!3F1Emd1>eGRfc8x(cw=Xy}sV`kxZ zvzuesOyh+}I1mnpw^?_Lm64y-N_<(D*qy>E?eq*?RAnU%SzBr!cq5rFV}Q zsytUPg0dQw7fpSQdpbV^*zW^h7EIDqRy_(@-!lpmW+a|&IR~_rcjznU0zhJ zv@;q6%&st*8IMdH-bYOHx&oyo zS^uXV5{tP8guug(7HL4Zad~&&HOuR*+rZTs40*m#rm>S6qgT6xv7{|z3R+obclRMl zEb)`n%G<>GqFj>p?z-8$>u(v}ziY?v&ON-iAj*n3qtGzH5A!sflnr^dtOR&n%+nuD z(fIv)ck|+mR<Ykp>>;Gv9P4mc&cRA8cD|&CwGlUC#eUm95`k| zJN670)XGg13A2$S9M1?eO2pEU1d(&5#Zq){O|SdP@@szo$Kj2h$v*pO(@swt=gp%^ z+PrvJJ|b3Ol~vs+t8-JFS60e8zppIm z2Bi+1$*4iki$jZakI<-*tG`c*`}W;h+GTYQYLF0N-6KMy!caOKu^P$JsC$H2!(&6! zCp+Hu`KgVbBca7rx&-UqRKKEJJR;WyM|OA2(XglHgR;Sf`3&70yUhfC)Jz!W4b}?` zt;jEGC54{3Wm(Bn$Epk&=JhX{<0;P`)8^%`5IExtJ{2F|m5WXs8*gyIchAmb_Rm!x z73@}tWg_7;`!R2oRHYL{%x9;NnD+jF-fDRIt?CPGc;~lYIsDbP?=|HD{*=f6P3}r= zihF?jtUu*1`Jp}V^1KG(tRMgaAOHd&00JNY0w4eaAaL#xi2d5TKd`se(;SaCd!Bj7 zy)GRk`6LtHIoGPKG+Lo%1@~J8n;#yk%M@!+kkTpzGgd+Gb-!3wFmB2^9INAWMoOcC z(KkHzvsboyny9KB$EY01ND@IIoFUmkERq(?6V|1%6TaampE+1L;r!R#1>>~z9=GHU z)q`1Stl*p9`Db~nVEZ?Uc0rQok{B}@ONW^}*Q$jxjTLw-OA&sXgHFH3#1efXlm)%G|Chaq7gv| zr%s=HTW3p8ubDd$5yG+4XAX4OhmJ&tqN&K~b8l<651mZJgv9AH-_X_)tu;Aksc(@| z*D7r$<$%OsG!`BT$HK|vH20Wipl3I0b0ij7ai%CK+)&}iDV?ULVB_?H}%9D`gWgTcW^Z~ zK22rY>9?vcF!|nlLtpcJ`(HXKv6I{F;cnyJ!9C7>oZHRKa*uKkb7k(IX%{{q00JNY z0w4eaAOHd&00JNY0w4eaH3EJT5qO#0!IYkKax|?szgqHab5%CqtqpbkJ{AE^y0D z$4X=G{oVbh-@)!b^w1AJAOHd&00JNY0w4eaAOHd&a844qZ-hkwc(YEb&^IyPDj~A% z){omB*_mH>RW@W%2~s-waVIAs^Ll^!j^q7uzHVnh)|oR9b9cF<)H#(uy&w41yvLhU zutr5IJJhnG+*#+s-!V%JH7e}b-ydjvh>E-UhQ({H=zp$ilc)O}c@a=DTCqPJzAzi{ zJTcmSL{|6PLYI^L7LXf~oJ3uW2@&*=DJQ61=l%x1UHF+LerMGg3_muuv;V}MD`O9& z+_4AF_&6*cK`Xn#Z99U8e(%%wKKij=*v#Yt&HgWYxc73eqJQ{+00@8p2!H?xfB*=9 z00@8p2!O!(M&LEeZ~2`Y*LybkLcSJXdms5v+(3>e3*OfI&) z?=QwHJ^;yqDQWqW!-04(N=^tYcdiv5hLtpO^chZ**MnCtzxgLe*(tVFPO-sPcZ!4L zypWw>%h$eFe}c#m^KuYQrsK>ppmowpn(0H9PVnr0=Lvki4J+F)F6PV=?0e|jjZY9u z$K&ZJ^V(Z~0=lSO?84e|fy4)|x$CjcZ@%4>3veVC_yPBC^ba2p009sH0T2KI5C8!X z009sH0T2Lz^NT=Nb4zoxms~VnecO#qolW$mgMGQ-xlS)_x3lfkX`mNd#eD)K| zZQ&0YzsCFvG;?3|a6ja}P5HKOFaq6%Z4{3n+SRhv3LTNPdaK?z&V#EfQCU|!f=Bzhk`Im@ zdxGf;`29bwk4F$@5ec}>Tqo_s2LwO>1V8`;KmY_l00ck)1V8`;&QAiDk|f6KlJ)pq zNv1T%=T2hsn(oVJ?rnw&aLv8Dsxbr3_jm+|2!>O^NGc;l(=j0(i4VqN(Qr&i#imoKWGWR)MuTE5nGeQh zV!5Cw#G=835YDHPxm->Rhb>Qmp@KFqg^C4Pk&B^05-!Zjb0IS#r&uiNp*#tOm}QF| zs;kEuC1ooV105wV8X`4m1N~P04u1Tep6~y@@e@C@Bk*$H@z4)GAOHd&00JNY0w4ea zAOHd&00JNY0_Q)0jm@EYVFop;i8amE7kFd$-+up@TOay0Q(wUUH4pvZ0|Fob0w4ea zAOHd&00JNY0w4ea=P7}cS9vd;YHn|CZ*SjC{`F3lTl)HZXTD}%=U*}w8x&IUSa>Kp zG=02(M%1OfqER3-fiqj9?+^4F8tD`qkdI0I=?M9w6vDAsEYP15)x1p0_mbY9zT-CU8yjRL7YJKnM}@FHn^WeE+tmx<0*GPFVg0T0LCrMGO&5 z2LTWO0T2KI5C8!X009sH0T8%I2rMsJ9t1|Iy+5Z1fmL)2Qi-^bN}QAa1=^_5Rk^@t z_ny4^ncqB^@%g{y@%#GM`9A4;mU|C(7dOIP;r}iF-Tn#x7VdMtdwd6c{TE5+Kr=xA z1V8`;KmY_l00ck)1TK04AwR{m8+FCBtDF0|Lc)i9&H`q{yEO`Qy9%&)c&9JmPkUPg zidbLLW@Sannz0G8N2Db^k`%(pSae0{p>#MgI22FDhr+S=w0~PuOV6g=bK<-djR-U6-^{!r)|i#78_A~C=w2bPoKHj&ODSzMq*ST;`C|gu0^zqVknw* zcg0X#QHJ~=Mh3&lcr+0kibWWi4*IRi1^(_YUjG|y|26oK6{m2!r+fQFKL7v#2!H?x zfB*=900@8p2!O!p2)yAYGYX-MD1?YYNM`LXLMTN$EF;;@E8>i#kokSTF6X5gu{2oO zci}}L3>@z-m#C>LfS#Vgo#dsUTq;SbF{2c^Fu?fW0|Fob0w4eaAOHd&00JNY0w4ea&xgR>Z~n|> z?Vc?I!^`V^IkBY7luL%D?yPR{V`DoDhEdehp-^rAAQP<&%9_1Lo}aUlj%lhC5)TUM z*s-al@x$Xw6NiV(qPjy33E}Wj`rR6dhKglzYvkqw6N86~b5}1v@~MMuo=v`#&v#HP z$>n+bn2Y8&`%KiPP4rvU7kJf2w+f&9y=P{99Zz}MTi@^Le4_0)THoLGMEe)~&vbvy z&pjUo$O{4>00JNY0xvv)<)wT6!L!k`FS@Uo~vhh_UQAEKbjC55~jPged@d+#cX`5^P1oM&xckQb=&x=|wU$8$?O zYbL)a8wH+pG;>nET%uD`vZP8ZN1j(C3e&9fx@7RO$`>`=2#Q55Cn`%tL(UP|5|tgE zmr8O@96S?t^lCF2p4c@K9^ZASoZB5&UAz*xyHdAC2a9TjS1c$bGD3>QfhIN{IIE_%J0|a%90`*(jdRnQe5SCO$_t1C2gK3KJ&7q^Msl@jzOsSC9Pc2C1sX3 zG=4$O8Cq#+%NYV0iH#p7Acv={cRgnZ3h&t~9h|9jprK$m8jQp6g>u`=?rT8S^~61y|l)i?L)_C>ey*tcoj z7{cxYVRF~L$arR|{ys2no}VZrEB8Sx7>=0t0Syqbv>>p{UQHu4XzC5gK^k77F=4v- zUrx5(`{mbe^xP@Txd+VZrFV}QsytUPg0dQ<`y#lgX?cBurLZ=!QSl&488*yqi8{MB z%hQNZS~3c(#~iQFbB}d%y?wt@ID$q$77S3BhfK+N4ahQojDX$ zre~@Hf)EZy671%W#M9xS$^c4fN!I^qT#dzC147{8M~gHd+_=2E?;4t+nGX+FXE5aX zLYXFG)EK?mC5$C)Ayd%GI=j0MNn(kgq*mT0&KKp9w0GCd=3Rfw@cvyphIj7a#RXBO z#cYL!34WNT;iPQHvt=c~>tde%Xo|+~-@BU^XSA|~F;^<<1qPB%E}6$#unw);?23gY zoyJood)lWE^`P;^$z9{oN$Nr7B+)T&%!GFA87`=mM^7ZoMvibiBhV-jBUkuD&Y2cV z(GzKU-B*@h^ZP#zZ}d#|*-x8xde}N|9#zuj#l!Luu?nlK>PA_eo3j4xq`pwn6h2p` z5phPM5t91RZTq+I*WOI`%4Dvrly!bzS<($k9XP|`@z5gOBlN7z)!!$@efw@L?XtQD zHAslC?h&D9De2fptVXgl>Kfgd#!hIxba0z)hEi&{ycXKq0bIQ3_DXRe98&F8jdCm;KlMU zK(6fqmg|C-z`sBn`3l&^92%Gw_zg}NC!tb&FqupZr6P%VWcuRtFEH`V*dH|A+S+XT z7wCGOhkoz@0T2KI5C8!X009sH0T6gm3B2+3%s~IGb1=|{fqtDmdC2r9*vP89vO_H^ z3YnGbIa;7sGFq`e9sYSS+S)CvYZFm@Xf>UbV{#JJnCUaGFvR~UkyU7hA)qkf)}yH_1*;p zw|9X?*QEc1>0iKQM{x7serNls55498GPyu|+i#e51RYPoj^IUo4B+4(00JNY0?&g0 z8M^&XBaLX-5m?rVZmnS05x|as8CEPWG`7B}DwD7N=HKA0{=BljfgJ(t2r7nHCt*im zsg*lz24F`3I|62d*U*mO*Y{ud$-le2=NEjwPkQ{_Pd9Zx?H~7F#l4#=`ktjYh2Ql( z=0A=&h0o*l6NrXQZxs+Zo0wq^#R4gNQZb6mDZ74b4W^Wv#D5 zfW;j z1m1YUv?R#El3+FM@6Z{lf4>M(@^Y59QCU;R! zFR3NLnZ_yXpz*aDkKmE7{r2!Lf2`*_mR#TwPuC+C^5~1UfdB}A00@8p2!H?xfWWyz zpye0I!@%j~0&l$C6dr7X@ZcPrcRPdw5FTiDC?J{vUnFh_8r$(TYQL!#QIm4@+cATf z?}eLLRG|QWizHIugA%`&0-^-?;k-D{9}pEopBGi~1`z1av0zH7F{_#D*upi``IR2cuX!`5`R!u^V*`$)7~Ajaow|f{@c#l^7vd{ znib26K`}ogVIdI=CxhW=Mo6&;Z{eZoNSH$Z3E^NQl@W&0ks%6WF#WnWefn0jDuPuN z--f!XD6(2U+NdgHY)3$T@;*C9%j2^vYY+kgvtp&T7D} zM?upKDL<++Ie?xuv9o^B_P)Oucbj#5zSKjd}rHhUoOGm*4!8 zqwEyhDyJ}epZgSq)jYwLuYIrn1d$=ueZt9fywV0bK_!h&nqnt-cE9rkCPnuN2$y++ zeGh%R@d;w-csw1gT%{E!pmCv#jSaS3pl{tzPaQh;+4q=o0q#Q{?g!kzabM=X#C?YQ zBz?sP1V8`;KmY_l00ck)1V8`;KmY_l;N>9D)z;G7?DahJQ1gSo+T7Jz`O@^&Tbnx9 z(U%U|)AZH*I$LPF-P}Ib)yy(^ulvQTZ@aOnvx#M5Uv7A=)5|ik?bPGcly24>TP`qv z?<0Tkce}3(bW&Oy_Yn{GDemvNzvMo`{gC@M_f?h?9}oZm5C8!X009sH0T2KI5C8!X z0D+f3C|T;eu&LLS<)bWmDdshGnA-%0{QDY`#`D>Aj*+S+ZPM zQ5VxKPlcmH;c#kt@X}g-VJMl5MApc^ z-kpDFt^Aj`^C!vJ|8(`a-rFMdjTTGVtgJ{`ZBdo-*(1`D9!Uz}WGq@&IFc9?;_--( zh^2<6L;jXcebvSb@u4W2C{|k^O~=T@J~9|i#-oYYP%JV{=Io9F;Z!u?!quQax2wQV zJmG48eF4A!TONPkZo5H&j+UNHqjTcC6p6ChIjd)099Mh%*R{6v^jO(rk;LgU2b%3e z4<(Y3n5!Z6hYmE^xuX$52)j7d=ib)Y($j0!BM}k8vC~)NhPIYy?GifNMmD&H1T35u z5`)oLcqkkTCzI3M6`r=9-E-U8?K375F=36S(@npH$}p-cFwyZz4v>g)EnBVnXRTX9 zZ`=;ot+8#LT?OhFi8UG>Xt8<5iF~-em%A=(v}RMUfm8g~N^jp;zc=}gA`@RR( z-}OdjN3g;FkcYdCdk6P8_i=7FH_JWBJ?#HF7v{>`Kl^{%|3&{FbDOzN|BopfJ|F-B zAOHd&00JNY0w4eaAOHd&@PZOxk|M8D61BmRV#%5=U6C>rS-&DB8NTE)nk#$R+!piOlgkKoy6od-F3$^=iXg@n(dpXF+~HN9L?v=ua=;uqq^J7-F_9x zIJ~x0r(VX<<|Dz4Rh%Ret<}P&Bw=0k*p{rIrTX2H+%#9eTe6v^%_I}+uuoPe6QhgP zLBCbG!2J4m1s?4C+yo zyotqw3mM{!e!M?dE|nzp{#Nh0<}Gh6H{5Bki1w;%$f6RYLKHnsHl%sIKYhpXemP&a zvmon+R$4N5mrDxUPp6}p@QOTB5@|=EUlC^{+Hps}F6X5gu{3D!y7NTfcz>fpA#(=N zsAy$}T2_?$(vC?^s8M0ZegrZ6`Pc{g^;}6)l#EvFPls1MR->!X;OZ9)qo`A#$%!Rp zri>tlay5pd9oB+CmLy#(mvR!_VocPahfFCzjc|W8+QrNgf3vI}mIM4Pl4um962Dhc z)c`-77w7o{qGIUtqDlp4#RWO1sdPa50?6}o)~SzasuU6r3hLOg(eT8sk?{DgL*?A= zxEhK^jz%L}Bhk>Yy|?C!LxV+iuK&cHfy&TgjH-F*Xn$G=Qx6drr2N?GH~*a{Xi#>^ z1^)hlo4@$3_h0ryOD+)cbVV+@VH*tw0T2KI5C8!X009sHfioa*{~k7_fAIB~(*L}3 zQMdTw%p?(O%!VCuhx1o1QJJ3SL0T2KI z5C8!X0D%jGz;g4uK9FRwvqy%l_}`A;-1TqVR+M-aNV~yXYLJDBk4A2dPyLZI#J0d< z!jqXgi{TxQT4CX>G=Tz#$I=lBPo9`w?tJGnJ6R-jsza8;^gH^7-DhEg`rG1mX4;<(b)8I%R8Uh!KyR7y=8+t zFnfdQX!_ArD?@?DU%lh)bChM>rGI?7iU<{VV`k;T0yA%p#ixrOez4!f;7fXO4xeWb+$+)XRQ8FN>J~O@C_P`@ounHx2 zwrplsqej7A=(T!ga8_hBsjleGY9-bwSq=DTB)CI1u6uURf16||Ys=$vuDT?GVb)h! z&xj?gj!F^kg|O*hVJICj{m#AaO`pEitcqY&#aHd8)vB1?u2EIYjv0`jywA?j^7!n^ z8pMJ^A`=OxW8`fvUg;9f8Za7f`lHshX(VEes$kQgy+mW%mZvAo%VN^VH?B)0El{^e zuB?mc4e!L8K7EW;C7Nv6B<+uFKjcoiPhY!AX>Kf+tC}_GN7rBDC;tc4H0lL(8KTp#UVigWjPnCx{HOu`irV$1821 zlUCB`q$zfSXZJf#;Pa6~M0XnqmwAGH4}H7w31aCuIRL3#r4=WjM^zVlT-kDgVAMB} zd($1CHsu1`VGs8M?%%jCb6?^=M#@BG(W4TiR)Y34ef7T17FNRCKGxODGFf2?n>w3VCidlq z=Q_PC6Wcc96n3*l*m8l`zOn!RQy)yclKCC%=I-)vpW^HgE0GK{iHWBL+a{u#W}3;+StE8)&odjESDcl~36}PKttPg$3l&{oE&4B?>t9in zES8d%UVW{oZI?3iw%?p%MVqLtEuTw!{_jwXgS}H3e%e3ozl!V!ioR$4zvcg~?=k;z?sL9-d`23iUNAOHd&00JNY0w8c95r}M}aAsz#ayy(^77R(+(6k!ol)cJ>h22CK1c!H?EF?txi#{$_;Quwv;0Gm zHS%BL&Y!Grt*buQdns1i=&G^W>Q3eg3m@`ROuK61&6sx10`(!`$(-F$z>IjeMuBcu z0TvJM^acF>Z+ZNEyX^)AI_xm_R#-e|VY6eo+T*{jmBQeSGKcyR3WIn0%z)AcGt=&GO886UTrk)dxZ(FEL159*$k^>~791R*~{p~@caXVaHaoak( z3XMk?*QE-y*gUP6gr~1?v}RMUfS*exn^jp;z_^W^K_g#K@u7lYTZ1P{@;cnyJ z!9C7>oZHRKa*uKk`@hbG{nv11?w|d??f;_xkGaiUr~k+Phy3^XXZ(BpukssI5FZc# z0T2KI5C8!X009sH0T2Lz3yr{KH0AWNIkG(kHfOb)m^{bp6pdZ(NU@|}y(?3~mpM`_ z8CH)Y#S&9(bfiS0F(Ep%!I5Ignl4?DG89?AA|)BVq^{!T+?^xARbQpzk*F!_@w<{t zX^zjG#N;*Ib;mR3-d%p0?VEhe!*_BtpEti+f|`!%ZZmiLRV3r^+ESf*8AqFs1UFW3 z65O;_3!BW>RgZ1S3REMJ|R0a~g#KoC~pV zmLaiN)I$_JLRB;|uZLEt(i-LK<8;tr^P(XxFM2nG`Z{*AhEu!Sm%WFm-3kRxpjOY6 z#04p+8|8eZ#m)v>EAa8bSS%Wj38@%U^sj0GnLA1GMo7g|2~sFZOs7)GR4SH?2E|-5 zAB@e!azRmuMS~QSFrP~1ayc;^wj2Vi(UcmBx>~MLQno@dR9a3A-oUQ5Ef+Yx_w~W4 zYd&!g(-&yszT}}u1m9u%@c{u4009sH0T2KI5C8!X009sH0T4Ln3G_8z?_EV^(zLNT zR4?kF7PVwk)o(ws<69qQashAG?H>BU2LwO> z1V8`;KmY_l00cmw0fCk;Hg9?G^#iYd@+MQo*$`*+10#s{y@KMNb`Ds`i|rMa^5~fb!S1=4Xw0f?k<-Uwx3k1)1iY5thN68$5#sq12eqMVXY$h|~k%`0mh|PFx zGIJz4rtT=a*@TZJ$pB%ns1lhw1NIO!s^+Dm{b?agcL7;I>`UKzevetK+y2ogqm=1>rg`pG+s6jsZkN3}ry0lj`3N(9P!zR7q)Y;Jf zUwh{t+s1j`@uMl*lqHHzB_;9HAZMkS<5)-D?<1LHDJ|KuY)i6i%88k!?(uje&pz^K z9*_Eww3(E+OMxLs;%(?MWGIky8#W9XhIYV!VZ*wu>6WGe5+rkxHt3qA{bT#1OM?Xi zifqq&$D>G*lI6fy9PbhI!+!bRz3=;ZpZ7WP?s=atq!&14EW=#{nNuW4)h8$-d^%Oj zIRiHB>)w5?iq}Br$LQ!{Ts|v{@Ig7JS4bx~xSe3Cb*l>fF^#gb2rsEsjdV{f<=mRK z+nT@$pr9d(UxJUdfy(acmm7QKJA1i$d%$HF3WX+t;i}U!G7{eU9{*N=Ex7_f=0J#F z6~DDRFD=k`InHyeC~nAX%F6_B_Bes@@p18r1oO?u0axUg&-6E7HM#_b9fY4|yg;$8 z-#hzvFHCs(1zw^eFGVhY0>+O`A^{|T1dsp{Kmter2_OL^fCP{L5dml(1S_(#qzI@-aNX+>>;zkG-WT}OOS_%v z|C#yyaQH8&J$*ZR`+qtxGeAfFAaWu6!N4C!BH@1=cr@}#_=)hT@Mz?o{%`eP?4R$y zv+uw9Uhex^pV61>+wo~#8Q5*)!-%(wVqH!s~3UQWAWTGJa?$`IU=C4qn=*~CJPwL0{E7afJUSH{i)7GDGG5{j( zlN*Y-x3@+D?zt#0#w9@(w7|Ve3Vt7x)>MvOf1}b0EE{=y!d+Y zI==0I{#xpRme@D;ouvcB= z<<`D+Rz48)PaT&PU~+}p+x*%B&v9&G^V)as>KXP{olFAiH?4f{&K_Z8%AdiO1Q4Kg z$SR`HdN2TElbjqCAmATvPr#lD@NoNK#0Nsq;1pTrZr+5}W5gsZZ(hEe)Ns*ssj<#5 zga|kd_iSgqrD1m&2As9c6sfzn`z^Q`3)=gzt_A8qkIz#A^6WY@Usqe`Ti>6KF?5;| zkhzKYe?Py#?F-N3ii5WnNW4IB;2p>>5P1-H5)eZ8g#?fQ5kAt@T~Soy|ZJ+PD76HbJ~52#hcDf#DIaR2AG1arCv zewy(DH@&;~(ecW6Um*7dLOY+QcD=Fl`QFQYZ-ibQc)$Ohfyk%N2C&CS00|%gByeL9 z=)FvRL=91M!raL4%D%89ZR-t%1_uX&{)Mjdvg&78?vgz@McX8CxN6e1s!@St!d1&D z6y2o4C8wNI%X&`FtBzSCPZj(YIxf#w$fe9li@ZeMC}^>%?4i@jd2*%ZSx#nHh2hyW z%OxctDF_+2jN=$iNpnJyQ<9>R3H(AeP49d4z~k@TI!sO7wqn58BVESco>|$d>s1rd zKFv1%!eB2rYK|cZrgCK9b)ya=w`)~M3sqR6$r$McqgJHhL5!y7oGP>n#d=vMHFC76 z*LBmTZQaehT(RsLqgE_UHJ2(iLxZH$RX8?P(yNB1Mz;bE-q%dAGZTl{>4`IrHYt^3 zLJKTeyO204khfJHERo^lG?z$<90AiTOQcyoDauKBGP(1$CM@cA|9o}FQ{RaXQ?q+k zVy(Qw;gCO*C97;f0%_>H|Hdem)m6xxeeh6fe0JuPW-xh!PH8p6D$^&ef}@*|NIFW7 zLvnLntI-oPDLP-ZN;DuU8IX({XwxO92DIoUNabzoW}dEDG-Tr@DdhKVk;x%(`W!Gh zH}AdIYh}V7JE1?2Z5U9TVFiYl(yYsb6A2S26B%AevvLwp@eL*`^(Wr!wrZLrZroL~ z^60b6LzE_|BYVi283%vS8*Z_I^Ln|gFE!`i`!7S*0;Aes>Ndk2bF0vkWPPOEGMeMr zF?eEkz*{t4MLKU)X~)({T5>Y`?rXL`>0TY*@;ZD7Sqj|j#2i1Jp6^@=wZo;EqS9Cj zBE$0TQUC`5k90XQ?ai`yQUYsGqTpTxk;??%UEOiwOC ziQ1A?PZur6Cae35u2$(;80BfTR57ahiHXDRsy~uCIdL#GevDS@ssVZsCb$VYMT0wW zYDV5M$7oy4!7t0S=#wWVX*Fv(9!9O|*hK;o8rR)()xA^OKD$bB$p)8dp562+1Qs;C zFgr0V%z_2E9}-&}M>clwSgKfVTzYtxcn(%dbKoUJcrXs+TFb-)T#+){f4K66Z+^%Q zQL`id1t$a-+t$TX)~%9y&N#0&VL4^H=9CNb-k))>1yF*ZH3vLmRtFCWYvc6Ez4Tp& zVXe$+j_KI+oTJ+{DBZtB_jqOj)(GepXr1e%GB&8zdmfHw=}9Angon@@ud!K7P2 zPq_st8ni_~$*mwHze_j6TUvu{n?D|2M zeFVFHfcpq;tasQr8YF-OkN^@u0!RP}+|UFLkRW9@%C{rBSB8%V@X;s=8v+DDR+K~r z_Yt(mGq2k+f%^!qw|xYU-U#~$U^m1V?jztihD|VhA`Q1K*6j@Vzu8C73)g{Wyg<)` zPyg&U550Pb#0v!aG8BB{7ZN}MNB{{S0VIF~kN^@u0$m97d_TDN*~j+(`oDahD8R?y zDWUy{FCGq}YDBBtps26j5!ep(Vw=}fO$Lq!MK%aaDS66nM$SJ;^TncJlkk(#m z2z=2%dvKJ*D%df1kNR2*qg`U~={Um)$!xwP(QCi%#>Az^Z4y{M9f?v z>W*I&coLj%n{(+q`GW>|5I)*5lm0-vn6dv-iz)eiX%Ct4q!7lYT%{$no{-${cJL}(g zc?U6GfNbl6&0h9(op-R)6tBa)gG8sWnRoEXAH`pO@>g&BLpSdr{31GqL+A(INkd_ZoMCB~}gWhQGn zdciPF12)k^LX%+Yt_%0GpTI>$j+f;G3%5mtgskcbNn>QtdSFB?D>GS0&dU zSy|Fm>iw^6`_a*!*YmNWRnlXXqG1}9SQMVH=Z!+ljYCl@6+4!L=m^tNb9QW_K3(Ai z{|-Jr6v5EzV&^iDR^8$&CBGhhWKumcOoR^gF614$Gh zSAaYHt+VfC_?M!hD6k@zAQ@lQ?#H<=UiUhMgT(fIJ%SJa<6B?-z0V#P-UVgB$X`&A z*CPK8fA9+lAOR$R1dsp{Kmter2_OL^fCP{L61Xl1d^UJrV556P!I9uS0kv9iAOYeM zqeE^`NM6a<>O$UJ+BOu7b>8ZLA>9T)&HMuYbj#m9b?AZjgmC0I6$-ya4ZJxpGVomF z$;dy1--_%WID1_nz)m0mB!C2v01`j~NB{{S0VIF~kiZoPq%OUf4^hF}w+%{C&npSd zDpep+zMcyV$HfFZ(T2qRkgOh3-I4s8M2TQs86@);GM~Tr^cXow08T=^KhQkMUXhhO z9TbV-;%Qb)3M|ovSyz@w3Svh2?Qh%*=LnN?1de>}b0VvFO@Y1!Pjq=iDalEV=9^`4 zD9$JspXU8TsrLti>sp25K-I@hvk!_aUQeVX&n0=D9C}mp(05-MU3aLEWR;}g3fwdg z1qA~aMEuf=1#+lIE=m1oS72nYZ4d#NL^AZbgKbd1D%j9&ZmnG<@GITg6+0$MN%Bet zj@8$Wjc;%)LDkl0VBq$78!;w7Uf?b3`H}lxzQnrw2>R>Pz&qjR;17Nw0VIF~kN^@u z0!RP}AOR$R1g*sijF2?1vvIvLg^a^PZlELLowQg0RZPEW%4_RU=(dOF6fu?Y041<3)iNA*Bd*(-g~+4jnJzD@Atnm5NYW&{u2ox0VIF~kiaKEp!YKM5j8~3 z33DUEEBnHdw5>N38XO!9`kF%<>n?TCR7%k{k@`_hx>hwRbgfvmoI(-)>U7B|=TuPc z((|fg)`&`z-@?@@EOF8zFR`Gpq{XJPhfXW!iNq3wS;`EnFg#1*CnX^%kf=Z?<2Z&> z(i}uGDoIhv1bzXTt-NoL5MI6O@%L^WrlxLNF<|(Swc&^S&UKeu@}FkGcrQ3=jv>#_ za%AjvqYi_&YgKsuRam0QFzE%OR-`LcOVe{s6`F=(y{wZOIoi}A`I1fBdW|;9G;D0F zF>1wvZHr5lnxWA%Ruzs-mGmlXWsGixT^CWN7GAP;A#qe7x=bD~k>TVtmq>~ba_UBY z0z)WEq**>G$|QVs=W9(~t2>_hPJEb}-Ln#Fg%u7rVU?`11#=BOkCNP8QNxO5brrIG z9Xym8pPf0S8BE@wQ*Nqj`lMBGbQ1*RqVzaOo91^F`9b%`?%{yxOU^ynV0AY`v&>zS)3<$zr1%{W> ztP6xAS*|!J6B%AevvLwR@eLp=^(Wr!wrZLrZroL~^60b6LzE_|BYVh#83%vS8*Z_I z^B^atFE!`i`!7Ql0;Aes=QhI~bF0vkWO1b2GMeMrF_vWycq_)MNaw98?bte58D#d| z*KB{%y*mCf?eHOF9dNS~bNqCA-q9wd_GzyjF3l8`#ySug7GkVn9e{&?2frMd_GVc; zDSuI{+__7{h!hq*$#!)#7{yT|B!%G&vCH&t^zqz=Yz zjNLSe+LBdI7cIvotNVUXj{#}FUz#(lP4x=HETH@My=}DMFJ8U*WGi~y;IvhyGn7%CR@YLZh930 z3z}Y-otPG8!GhL1j%@7Uu~f0#xb#2(Id~3MN<*|fC&K0dFQ~j(1_2kan_&A7SHAGg z57{AVcErEhgy3S^x_HXERZ`Cx=hY@G2a@qQ<-)x8XB=z+^dV`@0gsr~!9&8@IDK+2 zeb-@FE3=woIyOD$=ynZC_ixcXo>_o3!cM2P&UI3mn>$*a@XUim$@9cKc(|5AWIyi> zl9YjYuw>w3JhR$+>3j1-)cM%L1|~tw8~RrO5W3B2vYCXoOVKmter2_OL^fCP{L5