From 3c3d43034fefa0cc65b9e378b5106099772b1b5c Mon Sep 17 00:00:00 2001 From: Joe Bellus Date: Mon, 17 Oct 2022 02:59:09 +0000 Subject: [PATCH] CI/CD Pipelines (#2) Reviewed-on: https://git.5sigma.io/abacus/abacus/pulls/2 Added CI/CD Pipelines: - Testing during push - Build and deploy binaries during promote Added .deb build during deployment Updated README for core, ui and root workspace --- .cargo/config | 4 + .drone.yml | 59 +++++++++++++++ README.org | 75 ++++++++++++++++++ abacus-core/README.org | 122 ++++++++++++++++++++++++++++++ abacus-core/src/dataframe.rs | 30 ++++++++ abacus-ui/Cargo.toml | 22 +++++- abacus-ui/README.org | 47 ++++++++++++ abacus-ui/src/data/editor_data.rs | 45 +---------- abacus-ui/src/editor.rs | 7 +- abacus-ui/src/main.rs | 3 + abacus_demo.png | Bin 0 -> 43950 bytes drone.yml | 27 ------- 12 files changed, 366 insertions(+), 75 deletions(-) create mode 100644 .cargo/config create mode 100644 .drone.yml create mode 100644 README.org create mode 100644 abacus-core/README.org create mode 100644 abacus-ui/README.org create mode 100644 abacus_demo.png delete mode 100644 drone.yml diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..a31f1c4 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,4 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] +[target.i686-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] \ No newline at end of file diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..7ffd2d9 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,59 @@ + +kind: pipeline +name: default + +steps: +- name: test + image: rust:latest + commands: + - apt-get update + - apt-get -y install libgtk-3-dev libxcb-shape0-dev libxcb-xfixes0-dev + - rustup component add clippy + - cargo clippy + - cargo test --all +- name: deploy + image: rust:latest + commands: + - apt-get update + - apt-get -y install libgtk-3-dev libxcb-shape0-dev libxcb-xfixes0-dev + - cargo build --release + - tar cvzf abacus-linux-amd64.tar.gz -C target/release abacus + - cargo install cargo-deb + - cargo deb -p abacus-ui -o target/release/abacus-amd64.deb + - wget https://dl.min.io/client/mc/release/linux-amd64/mc + - chmod +x mc + - ./mc alias set fivesigma https://objects.5sigma.io $MINIOID $MINIOSECRET + - ./mc cp abacus-linux-amd64.tar.gz fivesigma/public/abacus/abacus-linux-amd64.tar.gz + - ./mc cp target/release/abacus-amd64.deb fivesigma/public/abacus/abacus-amd64.deb + when: + event: + - promote + target: + - staging + - production + + +--- +kind: pipeline +name: windows-build +type: exec +platform: + os: windows + arch: amd64 +steps: +- name: test + commands: + - rustup default stable + - cargo test +- name: deploy + commands: + - rustup default stable + - mc alias set fivesigma https://objects.5sigma.io $MINIOID $MINIOSECRET + - cargo build --release --target=x86_64-pc-windows-msvc + - mc cp target\x86_64-pc-windows-msvc\release\abacus.exe fivesigma/public/abacus/abacus.exe + when: + event: + - promote + target: + - staging + - production diff --git a/README.org b/README.org new file mode 100644 index 0000000..db03e29 --- /dev/null +++ b/README.org @@ -0,0 +1,75 @@ +#+OPTIONS: toc:nil +* Abacus +A scratch pad for calcualtions. + +Abacus is a lightweight scratch pad for making quick calculations. It is programatic by nature and employs a simple custom scripting language designed around calculating. The scripting lanugage is fully features and supports functions, closures, variable assignment, dataframes, sereis, primitive data types, arrays, maps, etc. + +Abacus is similar to a very lightweight version of Jupyter, runs as a single binary, and using only a dozen megs of ram. + +The following prebuilt binaries are provided: + +- [[https://objects.5sigma.io/public/abacus/abacus-linux-amd64.tar.gz][amd64 Linux Binary]] (tar.gz) +- [[https://objects.5sigma.io/public/abacus/abacus.exe][Windows Executable]] (exe) +- [[https://objects.5sigma.io/public/abacus/abacus-amd64.deb][Linux Debian Package]] (.deb) + +[[abacus_demo.png]] + + +For information on the UI application visit [[abacus-ui/][Abacus UI]] +For a scripting reference see [[./abacus-core#headline-2][Abacus Core]] + + +* Building the project from source + +This project is broken into two projects: +- [[abacus-core][Abacus Core]] - Which contains the scirpt processing and calculation engine. +- [[abacus-ui][Abacus UI]] - The desktop application + + +** Rust +Download and install the rust toolkit: [[https://rustup.rs]]. + +** Linux +*** General Dependencies +This is a GTK3 application and as such the GTK3 development library needs to be installed: + +#+begin_src sh +sudo apt-get install libgtk-3-dev +#+end_src + +You may also need lib-shape and lib-xfixes: + +#+begin_src +apt-get -y install libxcb-shape0-dev libxcb-xfixes0-dev +#+end_src + +** Launching + +Run and build via cargo +#+begin_src sh +cargo run +#+end_src + + +* Project Status +Abacus is currently in early development. It employs a custom built editor which can be slightly odd at times. A primary focus currently is improving the editing experience and adding additional scripting functionality. + +** Road map + +- +Editor basics+ +- +Scripting basics - Scripting functionality provided by extending the Rhai scripting language+ +- +Dataframe support - Pandas style dataframe support via the Polars framework+ +- +CSV Support - Importing and processing large CSV files+ +- Editor improvements - Improve editor to mirror basic VIM functionality and fix text/cursor related bugs +- Math functions - Implement common mathmatical functions and constants into the scripting language +- Dataframe performance - Reduce the performance cost of converting from the scripting engine to polars +- Web/JSON support - Add HTTP requesting functionality and JSON parsing/processing to the scripting engine + + +* Shoulders of giants + +Dependencies and technology credits: + +- [[https://github.com/linebender/druid][Druid UI kit]] - The UI for Abacus is built with the Druid UI kit for rust +- [[https://github.com/pola-rs/polars][Polars]] - Dataframes are processed through the Polars data frame library +- [[https://github.com/rhaiscript/rhai][Rhai]] - The scirpting language for Abacus is derrived by extending the Rhai embedded language diff --git a/abacus-core/README.org b/abacus-core/README.org new file mode 100644 index 0000000..82ac0d0 --- /dev/null +++ b/abacus-core/README.org @@ -0,0 +1,122 @@ +* Abacus Core + +Abacus core provides the scripting and calculation engine for [[../][Abacus]]. + +For General information visit [[../][Abacus]] +For information on the UI application visit [[../abacus-ui/][Abacus UI]] + +* Scripting Reference + +** Datatypes +The following data types are supported: + +| Name | Note | +| Integer | Any integer constant without a decimal place | +| Float | Any number constant written with a decimal place | +| Array | A list of values of the same type surrounded by [] | +| Map | A dictionary of key value pairs | +| Boolean | True and false constants | +| Series | An array used for fast calculations | +| Dataframe | A map of series used for fast calculations | +| String | An array of characters, uses double quotes | +| Char | A single character, uses single quotes | + +** Everything is an expression +Everything can be evaulated as an experession. This means variables can be set to if blocks, loops, or anything else; +#+begin_src rust +let x = if y == "test" { 1 } else { 2 }; +#+end_src + +** Returning output +Output is rendered based on the returned value of a block. The final value of the block is automatically returned. The return keyword is only needed if an early return is preferable. +#+begin_src rust +if x == 0 { + return 0; +} + +if x > 10 { + // note the lack of a semicolon here + x / 5 +} else { + // note the lack of a semicolon here + x / 10 +} +#+end_src + + +** Variables +Variables can be assigned using the let keyword. Variables are dynamically typed and globally mutable: +#+begin_src rust +let pulse_rate = 0.8; +let time = 3.2; + +time / pulse_rate +#+end_src + +** Functions +Functions can be defined using the fn keyword. Return types and arguments are dynamic and do not require typing. +#+begin_src rust +fn add_one(x) { + x + 1; +} + +add_one(2) +#+end_src + +** Object maps +Dictionary style data maps are possible and can be index or accessed by a property notation. Dictionaries are defined using a special syntax wrapper: #{}. +#+begin_src rust +let account = #{ first_name: "Alice", last_name: "Allison", balance: 150.32 }; +// Access via property notation +account.balance += 10; +// Access via indexing +account["last_name"] = "Test"; +account +#+end_src + +** Series +A series provides a powerful way to perform calculations on an array of data. Operations performedon the series are performed against all of its member values. Serieses are constructed using the series fucntion and passing an array of values. +#+begin_src rust +let s = series([1,2,3,4]); +// Return an array of values calculated from the series +[ s + 10, s * s ] +#+end_src + +** Dataframes +Dataframes provide an object for working with tabular data made up of several series. Dataframes are initialzied using the dataframe constructor function and passing in an object map container name/array pairs. + +Dataframe series can be accessed via indexing or property notation just like object maps. +#+begin_src rust +let df = dataframe(#{ + name: ["Alice", "Bob", "Charles"], + rate: [18,20,20], + hours: [22,40,55] +}); +df.balance = df.rate * df.hours; +df +#+end_src + +*** Filtering +Dataframes are more powerful than object maps and can be filtered. Filtering requires two parts: + +1. Selecting the columns to be included +2. providing a predicate to filter a column's value + + The filtering syntax is FROM : + +Predicates consist of a quoted name for the series/column an operator and a value. Valid operators are: gt, gte, lt, lte. + +Filtering returns a new dataframe with the extracted values. + +#+begin_src rust +let df = dataframe(#{ + name: ["Alice", "Bob", "Charles"], + rate: [18,20,20], + hours: [22,40,55] +}); +let high_rates = from df ["name", "rate", "hours"] : ["rate" gte 20]; +high_rates.balance = high_rates.rate * high_rates.hours; +high_rates +#+end_src + + diff --git a/abacus-core/src/dataframe.rs b/abacus-core/src/dataframe.rs index c4f6c8e..d8edf37 100644 --- a/abacus-core/src/dataframe.rs +++ b/abacus-core/src/dataframe.rs @@ -37,6 +37,8 @@ pub fn setup_engine(engine: &mut rhai::Engine) { engine.register_fn("-", script_functions::subtract_series_i64); engine.register_fn("-", script_functions::subtract_series_f64); + engine.register_fn("**", script_functions::power_series_f64); + engine.register_fn("**", script_functions::power_series_i64); engine.register_fn("*", script_functions::multiply_series_series); engine.register_fn("*", script_functions::multiply_series_i64); engine.register_fn("*", script_functions::multiply_series_f64); @@ -283,6 +285,34 @@ mod script_functions { Series(a.0 - b.0) } + pub fn power_series_i64(a: Series, b: i64) -> ScriptResult { + let name = a.name(); + let a_series = a.0.clone(); + let df = a_series + .into_frame() + .lazy() + .select([polars::prelude::col(name).pow(b)]) + .collect() + .map_err(|e| e.to_string())?; + let s = df.column(name).map_err(|e| e.to_string())?; + + Ok(Series(s.clone())) + } + + pub fn power_series_f64(a: Series, b: f64) -> ScriptResult { + let name = a.name(); + let a_series = a.0.clone(); + let df = a_series + .into_frame() + .lazy() + .select([polars::prelude::col(name).pow(b)]) + .collect() + .map_err(|e| e.to_string())?; + let s = df.column(name).map_err(|e| e.to_string())?; + + Ok(Series(s.clone())) + } + pub fn multiply_series_i64(a: Series, b: i64) -> Series { Series(a.0 * b) } diff --git a/abacus-ui/Cargo.toml b/abacus-ui/Cargo.toml index e3dbeec..80c4a41 100644 --- a/abacus-ui/Cargo.toml +++ b/abacus-ui/Cargo.toml @@ -3,6 +3,10 @@ name = "abacus-ui" version = "0.1.0" edition = "2021" +[[bin]] +name = "abacus" +path = "src/main.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -10,4 +14,20 @@ druid = { git = "https://github.com/linebender/druid.git", features=["im", "svg" abacus-core = { path = "../abacus-core" } syntect = "5.0.0" ropey = "1.5.0" -clipboard = "0.5.0" \ No newline at end of file +clipboard = "0.5.0" + + +[package.metadata.deb] +name = "Abacus" +maintainer = "Joe Bellus " +copyright = "2022, Joe Bellus" +extended-description = """\ +A programable scratchpad for quick calcualtions\ +""" +depends = "$auto" +section = "utility" +priority = "optional" +assets = [ + ["target/release/abacus", "usr/bin/", "755"], + ["README.org", "usr/share/doc/abacus/README", "644"], +] \ No newline at end of file diff --git a/abacus-ui/README.org b/abacus-ui/README.org new file mode 100644 index 0000000..dea358a --- /dev/null +++ b/abacus-ui/README.org @@ -0,0 +1,47 @@ +* Abacus UI + +Abacus UI is the desktop GUI for [[../][Abacus]]. + +For General information visit [[../][Abacus]] +For information on the scripting visit [[../abacus-core/][Abacus Core]] + +* Blocks +The editor is separated into multiple /BLOCKS/. These blocks can be used to perform separate, related calculations. Each block can have a single output, which is the returned value from the block. + +All blocks share the same global scope, meaning variables, functions, etc defined in a block are available to subsequent blocks. + +* Modal editing + +Abacus's editor is a modal editor that tries to follow VIM keybinds. The editor has two functional modes: + +** Normal mode +In normal mode the cursor is a block and functional keybinds can be used for movement. + +*** Normal mode keybinds +| Key | Action | +| i | Enter insert mode | +| h | Cursor left | +| j | Cursor down | +| k | Cursor up | +| l | Cursor right | +| A | Cursor to end of line and enter insert mode | +| I | Cursor to beginning of line and enter insert mode | +| O | Insert new line below and enter insert mode | +| o | Insert new line above and enter insert mode | +| b | Scan backward a word | +| w | Scan forward a word | +| v | Mark selection | +| x | Delete current character or selection | + +** Insert mode +In insert mode the cursor is a line and text can be edited. To return to normal mode use the ESC key. + +* General Keybinds + These keybinds can be used in any mode + +| Key | Action | +| CTRL+C | Copy current selection to clipboard | +| CTRL+V | Paste clipboard at cursor | +| CTRL+N | Create a new block | +| CTRL+ENTER | Run all blocks | +| SHIFT+ENTER | Run the current block | diff --git a/abacus-ui/src/data/editor_data.rs b/abacus-ui/src/data/editor_data.rs index b057225..09a1e53 100644 --- a/abacus-ui/src/data/editor_data.rs +++ b/abacus-ui/src/data/editor_data.rs @@ -330,48 +330,5 @@ impl EditorData { #[cfg(test)] mod tests { - use super::*; - - #[test] - fn cursor_left_normal_empty_line() { - let mut data = EditorData { - mode: EditMode::Normal, - ..Default::default() - }; - data.push_str("0123456789\n\n1234"); - data.cursor_pos = 12; - data.cursor_left(); - assert_eq!(data.cursor_pos, 11); - data.cursor_left(); - assert_eq!(data.cursor_pos, 10); - } - - #[test] - fn cursor_left_normal_double_empty_line() { - let mut data = EditorData { - mode: EditMode::Normal, - ..Default::default() - }; - data.push_str("0123456789\n\n\n1234"); - data.cursor_pos = 14; - data.cursor_left(); - assert_eq!(data.cursor_pos, 12); - data.cursor_left(); - assert_eq!(data.cursor_pos, 11); - data.cursor_left(); - assert_eq!(data.cursor_pos, 10); - } - - #[test] - fn cursor_left_normal_end_of_line() { - let mut data = EditorData { - mode: EditMode::Normal, - ..Default::default() - }; - data.push_str("0123456789\n1234"); - data.cursor_pos = 12; - assert_eq!(data.current_char().unwrap(), '1'); - data.cursor_left(); - assert_eq!(data.cursor_pos, 10); - } + // use super::*; } diff --git a/abacus-ui/src/editor.rs b/abacus-ui/src/editor.rs index f7b28c7..5be335d 100644 --- a/abacus-ui/src/editor.rs +++ b/abacus-ui/src/editor.rs @@ -1,7 +1,8 @@ use abacus_core::Output; use clipboard::ClipboardProvider; + use druid::{ - piet::{CairoTextLayout, Text, TextAttribute, TextLayout, TextLayoutBuilder}, + piet::{PietTextLayout, Text, TextAttribute, TextLayout, TextLayoutBuilder}, widget::{Container, Flex, Label, Padding, Svg, SvgData}, Color, Event, FontDescriptor, FontFamily, FontWeight, LifeCycle, PaintCtx, Rect, RenderContext, Target, Widget, WidgetExt, @@ -114,7 +115,7 @@ impl Default for AbacusEditor { } impl AbacusEditor { - fn paint_cursor(&self, ctx: &mut PaintCtx, data: &EditorData, layout: &CairoTextLayout) { + fn paint_cursor(&self, ctx: &mut PaintCtx, data: &EditorData, layout: &PietTextLayout) { if data.mode == EditMode::Insert { if data.cursor_pos == 0 { let rects = layout.rects_for_range(0..1); @@ -189,7 +190,7 @@ impl AbacusEditor { &self, ctx: &mut PaintCtx, data: &EditorData, - ) -> CairoTextLayout { + ) -> PietTextLayout { let syntax = self.syntax_set.find_syntax_by_extension("rs").unwrap(); let mut h = HighlightLines::new(syntax, &self.theme_set.themes["base16-mocha.dark"]); diff --git a/abacus-ui/src/main.rs b/abacus-ui/src/main.rs index 0c12354..6dc2536 100644 --- a/abacus-ui/src/main.rs +++ b/abacus-ui/src/main.rs @@ -1,3 +1,5 @@ +#![windows_subsystem = "windows"] + mod app_delegate; mod app_header; mod commands; @@ -39,6 +41,7 @@ fn main() -> Result<(), PlatformError> { AppLauncher::with_window( WindowDesc::new(build_ui()) .resizable(true) + .title("Abacus") .window_size((600.0, 800.0)), ) .delegate(app_delegate::Delegate) diff --git a/abacus_demo.png b/abacus_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..6eca6902f1235f0c7906bcc297f033a50e87a44c GIT binary patch literal 43950 zcmbrl1yEdJxFvWAAy|L}4H8@%3+@`Uae{krCwOoIA-Dw^cY=Gc5Ind$1h>ZB9rotE zd9^b&Gdo+mT~ysFy6?Ted~&|?oj+7rQ5pk{2n_%L3|ScoRRDOF1po+rD9^zEOev70 zgBR3KGTP1n@G1=eupSZ2y=U|QfE3gOSbz7j`q^-WrNEsm1S5~9c=nobfVt^$D( zMSdd@MajmD5YJXFQlpKN%~tMZo1{!yX~cxUik0atIa3-M_yXI>gI|jmB2MgG=#*(d zVAh;Ov~fifJH1@W9AmsBm<=yo6+N3t0VZZRRXVQv^i+him<(8!eVP2(BBW`;NWlqxN!19 z6Z`ZV-IysTR!6hn1Mi$S<$>$JuJliB^R1`4}3n!<`WTDD8dTSB( zk0?jOxYvd$7#|9J=m$Kzp53g7MTyH$+|oP_b1As?>h}pX*bX9l=b$N zHaI}SI9i3<`?C=&5?;~rG3%ig%#1GMz6~cp83OzEM9dK-Y#}BlcD6N=DdP87Qqcm9 zsx63#iNT>${7Qt1g{4W4>vw9;%9_Cx_sq?An!syHj!36dg7*kQl>Aah^$ljqP-} z&_E>}<$W=wDN$_KY)*Zh%wd6DeLg%q3>+_c9U%aYYsr6U1&Mv^U(UV-%mHX1QD`7f>kRH)$2Sb!rq7P4@Y4M999Cv#3=9mK7e#y1 zWr+S$C7S=tPEKAvA~G^EJAcQr5p)Ixd3iz4bNV7detv#t=CZP=&4LCu zd5(0qw|A5K(WA%K@bYjPpH12#;Mh25(mSVQ0Bgku%n=niU3bIO$1%7caN#Kc76q430}n z`)NMpS)^ud8U8qchK`;&FQk*eq%BTeYGJq3l&obiO)5_vb$aR~A|m2sb;f1#e3@Z? zzTN>`Ah@c3SXkH=hkA?649kl^F+IkRQS|tPgvWMd^kpCS=>Q}$38{>yhbs{$=QCcC z;kjBv7VT3NMa6Paa&mj0?cLp<&RZ4BK3B~eC3$0(hTbQxva+E;K{uIxq+tp70ujcecvUWHwQVIf|+&et`6ocW`E*!l4o?z&D~ay zXn^Zm-_+#Y_Z_L)eCThL30(uW_`&}5$@(|lJmuZj*dnbMNxIN#Q^BftQt!7Sp zM`h&}@C1)j3fXaoL2E5WGLn+s0KFq4SI5VnDbV*K4!|jo|B!`)sp4%HIX0Nfg)sxiYhCYSYBCQpUGx&Tdpsnl*XH9F+y5YWW~qV0FdL)yxhY> z+XzBW46!TI7}z>9@U&_wD~nX7udJ$Kpr_~DuUy)6Y7pe%!2(zeB2t7J34`l|ye=!N ztMBg5)B$o_G$@paWR!f;7YxR}w>xykjebv$fYIlh`;E=ba;>VIGL}|rw}9n3yHwCL zlapsP4SkS+)zwuM6%_;o1XjUDL{ZQVSDPBE78Vw^;#M%?o{w160onQV5XkN2eA(*i z`}DN5UwY+vc}PV828Lb}4t{>E>LnVse=GSoI7 zTm7CQiFxV{h%GNsgdvcyU$CJ(xkNBXRJ1<+cHSBW-4ga$w_8QEW6NkPM{>khnjSZ- zF6Gd&HvkEJ>GL|qI`&$E-|=}uGm4O3LPCP`X4CraTqHCP+$0v=I`KSJ0$kj3-K!z@ zWgkZDP)W+M-6_MuDeH9&Fd)3;t$bScBP%N`l$VvIv8S)|d&)K&z*k5l6 zX}O*KK6vg3tpd!w;9fPD^hANPM-Y{f3DGIb5b+ZhY<>~(m-bDLJS~TyV47tB2v;Zq zxBq=Covc!=cTtuG2W`Q$_~pwNxW6nL8=KeVzEx`nj_FJ3W0dUj)z)_bewZmKD=Iw& zYLKC!p(k{uD=`$;k3^CAIXTZVk(WJ(3?!rZnLuojEHA|(iIS}-Nf~S8=77VQ_F{*< zP_0-h7c@CF2%f`L3?6ki|Lk4XfOiw)bG( z9W-k&X#oCGxkDL3XPZOwva)?}PjJ+aZin~TN|{UDG(NX4$E|C>IhASXs;D?V`R+eH z1gom5A{gzA2RSrzEh;}<9yEeBz|}-;YHF&OeoI?a$+fV!D15!r91~;k48d=?B~ax4 z7^k881Bhep!T58w#roTeCxyhu4@|}e1_qktdKAcW%iCkQ7DFjh)fP&%I_XJCpRbQs zK?oDWSj+H5^quFqCGh#~pdN&72;?9pZ2N);d^&~8=BdgSFF&(OTS0o(e$@K3c6gXS zWgQpy;oS51_>=ReO1c@FB17LuX)LQ}1$->wY4IkeVV>MHFS5{Wm$_jb1{ACZ>U9vo_O0vuu8(S3w_B$)9tuk)f z+1Yuq`EKidaMa`Z1S@51h*WN@jo`-K9*6tk{^=>2(~5_7quW82SfD*<^PU&GO-+JM zzZShu`{+RH7jlC4E;V~07~Nl==+@afy1RqHmbk%s-qFp?pvLlbmA;l13ZS8(At5Uz zC1q<{>bQ|$wf?--wC|a_JD8R3u|)LJ5)-iidD_4sbDS{{{^1f3R2a7IlvF%!ZEo@# zwN>M49Y@KBY_C4Ng>CaRw^E#QfCMIqbt7l3}8Tc1S$D^W#a##%W`8`I! zU>lP~4j}LVa{?N0eLjJg>HFLG=`pa`EBN;2#(wek;R|9gurkE6tW{^L;_baws_p#J z0gK}6+(L^FvQj$#dlnxZ#cX8|U@cxPd0mCGYAm<-@Gvmkw0(Ks-Y%A${BKFv)S^Ng zFn~;-OLbXU*#nljKYxPGqRB)~<{et&`mc_b&sM}15}4;h6G6N=k$*wVWB<5ct+c1% z?K?O)2pFxjeIa1c<8|2{1;OmRDY?yD<;RZA;q(%X5_B{)N-8P@a(4DpFi(T;f+{M~ zLg(JAs*YbC%)fp6R(1mk3CZsJVz%8#J4bTFSS}S{bhc?H;f4&rpv>5z7_QzvKE5|* z$k9E`K6m9(xsEP1N6W2-9v&XPzF#skkLs7p-JP5Soi`1EH*ChdW2V=~VCcssy1xDl zh7h24aPYU!oxO&}<;gl7Ku&4=T;+?U!BH#!*H@nQ=bjJc`d(q-;d~^+quGIdt8U#! zqsT9}GePiVGc)YGrD(U@($$qm{92VB7n&FLH(#0F(C4BRM41MyzHy2U>t77f-@SlKy7HX^j>HZh(5Igm`)ID{;I2 zPng0~RDmR3VM&hOk4#KVfYHI613NoA0(iwpWR(UTtGkDeX!rbpnA_8(6ZEJ^f>$mi zb#-;{oJ%nhsW(ndU@1ybREtyfE2Bxn;p0G!SpX{&6Bw2`iH2ro1cZehSK3y+g`Yrl z{sVk_z~AG`%iG&MR#W!bCJ%HFy7SoUNe^}-wk30b(VCds`&v22PbssULu5Io_3_pM z9C=4DmU_vQ|JfNz_Et`|^YM$9FBS&|Z~zb=_Eouo1pq=;PLBCvnmjE|Xy@i8ez$AB zLhA17s_%i$f%le@h>zdV(gT*TmZjPr5{P!6*1}omyi|Pj^cG?$-iN$ya*V34tBVQ` zr&71qz1TeUMAyw{#%U7I{^ci9=dfIPbGF57(4?1F%-1;a%E5sZ0!xXDOHE4ZG_MBB zo0r*zg^VQ{Whj`3V!30T#wQ@EikzDowX6Z!)=ys2^z|_?FcdvLwgAdHI=A91XQC(+ zCNBIwAh@5N)-bNR?vB)je-aoN7>FC#prB}G(f|Dt@D^VF^CwNK+OE=ZJ>ji@8d_mWULcaH%#pAa2 z5IE*ZmE%4B1N9KZuAAa8=tCEQO`d8I7|!DvSP}h8N(S~ST0P;tY#qLHfzUi*C-`5m zgp-3p`v(~DS<*6-lJ2h^UjX}awHz#mV_?P$4-1P(-FCVC^XE@M06#Lq2r}E}$f&4C zun^CjH**3jeTgU$-}~!Yn;D>Oc{#J)X#a0jZZjR$?%UEC-M{Q$=AD=z8%bijd$`&< zKYTk^qN!A*mXh&!z1nf@>1-!1KF->@pTcctU2i|EqM`}rpviLmTIpD@G6KW;OCU{1 z_v!xr@d5ea-a9Zb@czLk)XWF?wEBmJvOQDSr%urhoIY7b1}XU0S$E<|rKE&atD~=@ z<94xI>vM+*dL=?zXXyIv#U3KKr+!^w8wcqt2>%>@Y{v!6tj6qwS4Ta*=VQ>Ev_4bz z}^&v^oMrJHkdyyG8s;WIc99Hag zgS;Zeq*yZaSkoah-1jpg@ZucPy=G4eljn;Uj{|0EY7)LQCg-<~k4hd^##%BVc|k!E zkfGke+t&BNas&On7jt5UJdIGC}OSLbdb^Oi3x$>rZ>}?%i6!Q!e2RK-4 z36r5z>cyHFzcwr^*!ccdYpeW&^;#v^P3g5J*I6elill0gi<7u`=fr5aAC$mKrH6Aq zE8gi)ks1-;U1dwG^0ar9uyfA8E+iN(p8fJI=ke|ZF>`86f$E+%cj3(5#cj9rI+b@C zSz=hm(5S*#Y29nz#ltP!a6HKS&~O?*ox=LobQ+krN0Q<1Ek$Ua{Kv^0F?FYn{O~H^ z)wZQ%6c;{M(%tajq3>g+?@6BC*bg$0UM*a=@d&7|tMR&ur0Ft4@_X{~7yq(~*rVX* zaae&|w|(Imr0TmrNCq6Mc5*i4-2S=vAQ2~3EdczT`+IzI|07<_Da)$PVa~`-Qqf#G z8pJR~6F>e~+|23<_A>i$4Du}WBoAeYu$0X?)A5z)$(L(p=GVJoJ0b2f&qz-X%kn0l zO)G9EexR6jym+l_q!V)09})wjv*+@aG5!k8jtP%Qiqg^1(n>hwLBL4_(Xq zD6!P3a{aAre%pnpsIs_t_@&2tCSG$Ny#psmo^CGbXwhV1ppZu7Zu5184Lj_c-UXq8 z1M%vSDg-9NPPErby2kv$YFctBv4jgyCNF-p@6S>un7`wrsU0FRfqdb?e{h?>0tsp- zk7}j-e*>-5$yiy`_g?#8JZa4Z6G!szFJ`a$F+R3L!$tK)ua?h}lju$4#nr9uk2_|864wc-Mj(1SV$lv?k@#Is8uuXFifMAK^wo|G0#BMcPmoPb)% zq=&jHopZTL*)3P|fvCF|exMtT(6X|4fhwPTH@#n?$|H*uUVGR8yKSogxzP`Y1GBIa z#U>k?3P!`XCK|=(V?o*O^n^IHyYKCQM z#C1=e$JgFY2Ubzyjy3{>pjRi({CSQAB+nLcYg|g^)dr4PSaDjD1}m{}fpzAh-zy&P z-j(VtRvGG{7FEI4EPuU8(`dB*7oT}aq6bE|T>ztDZs%7{id`15#g0iYgLK}f&^bVL zv23ynYL7?$zF8LsLPl7f>sHJ(Ij=u5n)ajRn*3|c6smB7Sl4OxgBm2V2Tu#7%v%U? z2q|IqCK)%Ya0(){jgVE-WNG;{rg+Jsh6Xe1cB|Z*ZtMYyzVk@B={Upr0%WH| zs9DhNs~TF+fazx~bgFy3V%%bgN8ES*U|EaNLNHDmaQ~4jYIsScZc#%z<`Q3NxBg9& zPKn=#8z{GTRcWES^Vu$HTZYjx-YJ& zhoB;pk|l_4)apEhBCcuSA;=p&NY!oSnl*?<;df(rdfAXooFV4!Qu@HE%#ZP=`v5=1 zOhtJ`iWwUldyN3Xk1fJ=n>x*pD!w;QiwZ0y<<1g+I81DlI9Gh#`j#5|x;I9(bTQ)| z&uUib)~ln0KHE+fev69{;F=U@Tlzj=s@4aSmBd5N{gBFQz0BrXh!Jh4_wz>8*2Qh; znb3p^u=0tw(aqa$<2KUpYQL=P-&V$Pz*ffm#G=~{Gg%BTZ{}Qg2$SJ&z^txVl5y9P z{e)}iaMY8WoU{lw)WX|e|0l=u|1Eugz)DT#^z2!0n+WC&hxYzwOp|yGMXhX1gb1@Piec-k1i%BnnV^SC z@paVM0@7~S?89=qiUGVC6<8Q6zx04BY%L9?c5Kq-cf}%>9nXZuZRO?wMr(iB4(;th zRK0h2)U$PRBq1G#n4Slf?cd)NWDeeZq9}S6DV54^cIw~agGDCbb~dc93T9k> z^be>lP(2lza=_nOJ5Y(8tE|xwCAG_H{<)!!hK7#D3&7YBeOcY+<@S8yz=m7i^CJ?X zHh9gu_UdcB@<_?S$B7`+9r#~#F5_)wY3bm|`MOv{ASw#e0|^OO*(?$^5Sy^do zskv-#R|TV@e%oXj94fIq!g(16Z8;o3cT%pjit#@)2ew$SX7{{bzBPO3v z=EcdG%Vqd|x_CQ{s=cMLD$$SO+PaqU#pCDu(mkw@Vrsysd;R6z_S>i+fAQRBZSikQ zLTUY2Z>1_GlI_ufj)ajlEwp4oZs0tV2SzX7_=$0~(+qg?^P1VlK@%t(WQbTgQ~Fz) z7&Kf5DZ0N;Nhiwd@62Ge4qE-_cVL9$cnHUHd; zCeFdRi6HSjTskvhem4V_;77x-!@xLzK>KwkBc2 zSh7(f5(mxeo?7zQ8v=Lshol=PkzIGq%mfE}e?Q|dz2UEHCYEZu1beL%IgE+St}c~{ zGI?~0nXtZ%IJ&4S7k9&-rxV4H*8ndcZ|U8dAD@Q@_$`uuQHA{Uj!Q|4Uhd4E6=zC` z91rmMDP0@e>Y`obiP|kG`Qq!}tcjgg+b0$ZzMK0z`ZA3@__h`ec9)>#cta=|x5Ljm zN+nkkp~tJ`0>wDA%ndH4(w>sspGSiIp;22p$#>Cj2kTzF!Jk#JoFx4~3HfwAYMJ*n|JR6S@dBMAu4}*Lhl9?CY~R|#a2OVQl+Kqeoqh5DCB#xmsqJh7=*kl zwr~%pW($yO>-Y_Uz#y?Q)82I{9UqC!ZOWLKMGWgRdbcTKEhpxG(02dd}Ub~g$hsCGCK;AM9Ik;1UI7L}GH{2Cb4jmmc*m?ajy%UZL$jI7s z^X*{h){pIQs#2U_5^wM^l?rmOnm;iB^hidP+G26iZ*n}#4p%c{JGq0P>QJ)|;gl|; z)S?Y&vxYR>DN?+sIDz=|H(0;`w5Q39k8_ zkpwiMN0t+Pa^6WuPqj!}L=a_)Exlip6VRQ<+HAU;y2a3AvAF0VE1RuUDOZk zF+pe@Irj@}wD9L9(0z6%$h?k!Q>&wpr;L#Gvsj*~$fd?zcBt^}%UUf(MV8n_kiGi( zv+~#9j;UIE*o#OKVJ742cLKV)U_&UUQ;(jL`nu`f`~4vkBP%k1kg3%4679IvW2;;> zk8;xqq)!GIA%csGsqC*)A2VRFH*Z|>pnY` zTpp+k_VI)v0>7}(PTr98S65}R5lW!SwQ>AVozR(>Cf_m;Y$&V}(o75odxpwTIS6=B zoft}z=$)Qn=HXW<8CNb;0}5G6zH5dt>ybp@2xj)gO*-G|Wu_*Qt?Z?yeNTx?oT+y| zN?T~E=^+F>JFWDg%wQ9}@tBa~)uX11&DJf}eUZ}w3Cb$4fNlAN&}Dg&EW^ZYiz6E^o(%x$id&y} zU$1sh{Rt+90RCX5$y{$TKNR5g({B7ZNae1v4a?A4 z&yP_fhK3M2Ax2YVw^u~^dfyn_FB7P%^7W{W9yQPSkN?Q~TxMk>Z=f>2`c>+xRJ{lg zt(dWihX6oxMhMttdy%@qMm=dFQ<%*TR5CyBW=)pgtUe=?BVgKIETOCNF}ia27WwrD z+;!QW)}Z{>GC480=dnYYRM1-@{-1|V{drz7Wj#f75qK?tg?;!YaR6`VO+!lC*2!)Q zJRxB!S=z3*&DY0av7zzk`1KkMOv<2DDy4yI)RGed+dZw_ORO;DVM&DAOcYq@lwF=T z^g0u;Vvvsd-A>Ms>>squpWrm8`sfHsR;U*O{(T>bp>Il4Vp+0vEw7sHLQi^Fu~`{v z%ztc6*Kp zGNbXC1$|i9X_yb1wX4_G){nY6>EX4(-y5I)5{#E@=}s81GOjzNSfv3m z$?4W6W`=6e3>@zKu|kiu6x3sL$DPf=b*H?kDZt3i%*?{Zi(;1@9J3Y^e$`?6D|~EY zTw4im)$i4DCT@x>d`1#^s>z^8fj|~ymN#r>^c!8#52nINY(#yNd zk1sAM@e<+_REyM{v)>)6cst65<^@TLt77lCr>ACSre=zmw)vBO`SPy;nx0`u7ox?nB}oXLTuE1Fo_(T2M*2hd+KgdJdi+AuEa@#0D|vrMOM zrK9ocC=sTK^4#0caM^~(UbwGFpE~K1*Q8$#rze^emJ!>xb@KCPb*Rnp?>q2r44rSDveFLm_bIi*c*4;2d2LV3vNMkXb|?MYi^5(8<*<^s&zjT4 zcN>gz1UW_=_Q{WqTkw=lll9!x?O(HvEXUVjWRF`iQAC?i0Kk{PvYH=yRxV}UHkWBG zySt+s9Ct%LTu)*@OI2;V*R{MFHy1qAV496l6hc%c*D>wgjEtz4ZXhSsQd1h=vyqaD z?tHc@!aZdgI%h&Nq>lRlCqK?|_4#;(wWbfPt zkNcQ7>S}aOsgKxpGTeC%^-ZgPH3uR`z2Owgj(^MhD2IdNZS3S^?9`u@>~Q9B57s_= zzVq@Cn+PlGUEu+N&oH=Vd>%!BU!a~T%Fq|lpQGPyevM(`xah zH(0pzVM?uaK2J#%!kpF^Knw^H;s!3?kj(jvf2x&tJS*ss2ylSTd#V&p%FYW@XmA5< zqh=0>qPJZFCr^`lp)+eji2j9H@YDQdMB0}JC%g2tsd=yD21vK)cQd3s;$uKk&g%lD z#iL;OhDsVaI46fPU2%D6wx}3tdL2$Vwzt>HfdKk6i^6ZrM?T#K+aisU2e-Q`I3TW2 z?b7Zo9NlXE{zLRZ1oO?Omei7g{G&PoJObiFW3c>8S44hW^rqVnrM7L=#Lwe*;|0pT zA|_{hcCH@;9>%;kgSoAHMlT7HOcC-5V^ou}c=&h@%Qqa+x+81tQh138}3OgB>1j9x153dkfNcGFXAZCAAEs|v>@_7QaM{=H*4#ko|Iye=>M!(m`o5(+q+oR zJMHj&B|bt%dtC>IuY9r`v0rPg%B75WPxTE$sK$aPu8%~-bMnh#E8(Hr;aue1`ew{g z%Z_Y;NVCVCXet>`u=mf-iaJNS$BvV>Z>;Y+@?T-5-g7Q( zm1bWpc+y@9n*Vr+PJJ))3U5dH7~_{GkX+?grMsp9A;a&mrms ztw_H^N9Lgz2RAA?+pxs62k&bv(kbCl`ZlF&UOCD*8w?s&iT6hh7xG8idDC`xMZ+I3 z!o&6iKUQ#gUe$mrP=&?V_oX|@cVqyc<&#S#vOj!sl8cy|5NsR{1)#PZ;Njw%nhR0j zh0&;1NuUA7RT7kCK1BS0a#0M7`Rr`7AYZOf?f3+4wxyAp+`J-Y!I*sAR5m%9G0+c_ z>ItV{aSQwf)_j$VKlH>$y0s<*%Vt?LPU-n(3NG1mHB}U#K_pREJm1_Y2MwTD5f!ga$X(ViN6;Q z3f4VPE6zo{%d3hqAQglJeUFFSo@ENgYAJk8@LoAM=tK5T6P(R>(5_x`adv~tlyDi^ z$*2{(0Bz%{a7Qmx})FwEj&z`#A{t2(U@K?+%;K5?OlaXfIJ-?l05r z_g@eLMjt;4e;fo$7N67o*7cqU%pJm}yJ#PK78Y*q=_@ip0CcP1+DyNEWymF&u+x#R ze5-IX^7$UI>qW|ml1263IKvcr{BVcmaBda{G=xkMYl&+RXM`eRnqY^*$6+OavbMVG zMK{L#hK3lv%1l>y-r8}t+l)Qz^3W_B848mzGqZ9#QzQib&i~Y4y8Hlf^-CWNmn%d= zt=nE4Sle7ofyaJlQILPVbG|YcxxPgeqJ%ANzyx7YHx(>;0T4z0gd>tUC>g->a>6yk zIDQrvaYAn=D(1u9qh`@W~xysoZKUUn=DicDpbd%#Vaz+k4 z{5aa5>3%PC1#uXMET(Te<*6b^Uf@MaY1a<67D_nYt39UQ;cehSswDLFim4%ieOC)m z+ROco_A{p~{a<<#*=-X~^xv9_X5PoNuK4Or)#}nPSbYZ!#VnP==dY}XL9aisslAOT z-JQScU({;=U4QW|W1&gc_sqUwbtOxwFfScrU?R|cSFgSKFPaEh`^qDCeeM7TU50#< zMc@)eGe{v!5%csRd{vHf?R+f=Xld*Cw%Gfq!%zST%CY=f8<6hFH8DmIEtw+fo>qgX zQ^uCw*m4DTB=lJ;vSfrt$jd7x3tvpd*PMH?u^pDP__nl2Y}YcxZ8&xDq}KQ2p#k*t zkcFSV`Z6OcNyv^8NWd#O>N9*+b%+i2)R~G-d1>}IJq1#|>$sUbIuk2UA%iKIszib8m_ieZ|ynsFh!kxGwX=q!(IS zf7s1MKK#2X(kl^{?21%Io<}PYs;?Q*m?F20*@YhA|e~5iI$V%-q7p z#@t*g9_+S!dv2(z^8#>cXsRqk0pcNesa=%fVhE2sM+@r3YMp-;*S?RRhM_6ByRSc2 zs^RjzAyEdtt9CVeYW-?F#UvddoE({Zb$YfbEmEjlRNJYu{?kd)4Ax&uJQI`f@^Go5 zx)ci#T=<0+REIR14xbgG%Y#Z7yDl#!#3q7^ZV_`6cnxAFB&Cwwi&vS{Xva8dt$MZ} zhimH1-riSlPQK*Krb7?k_(pga2E_x8Jrr({RSk;d6%q%NHm#k<_BR*VZ^8{GEV5Mh z>h5E#KNpqU-4RYMd-ejvV2q=!HhXZQ!K%fPH7`Xz-P08=+Gx+kVmolTbl zHsUdZab61xQhNUa>qsq~8n|jEcVZHgr$d4TOh&<*0^5=kEmeV-z0JJWpWi}taA@!5 zcWI$&EcBP&Z;81{Gv#ljzSGrS(|Z^7hY48QCO*Q&Aze8)pHJNHFO$@^g1`_nOHRfoZ>A%wl#P_@v$wb6_OK^7s}^5Q@yFO4GCJ}YbyvM-4OMl073WbG42e6aWPimk23UqHG%Vy4EKE>>Lvb+8$M^ zPK*b?B>KzBG`KvoHB?lAvAZ0tm-|ur>2`ji!(=u93;A+yZ|~qOKGEsrInRQgUc{bO zQtH#~L!Bgx2=j*)0dP}9Y;q3ZsEXe#Z%slA1RTy$yjZc8D#f@F@1`@ZgS#)~ ze|glGO8bv4CoTs})PRSF*1zeCJdS>=ccl`9mhMh8L zojV7f?~GjJbgT{+nubd0_ost94xf0_AhGm(TnbD@aW5vVT_w%TJUrysHN5EQ;~nNQ z*grgfZ8P4tP5bW+fnT5Vu8$^eBtmt{?hXrT61({n z->kQ7yfbB2Fn6R;8nu5lQMgpL zh}+%04a;>_&0xC*@yRBsw*wn$p0_R`~Oj%bYwb{5TZMU zJ>TvAvl{->0L=-@v94;ZsuRuCRsjP^yu#Vk{Yh77Y^q_^`uBf2XYV1 zr9t7*`i$5!g6GXD?TXVM-Z$wpc|al$#SC^@ycj4w(&r1VT&sx>j&_avw%%>mSBLrj zx_t#`y__TCpo}PaZEuQ;jhD6PIi6*fIrAJL{AT|A(>nHg^hBXpMikDoMUtQe>%3cY z^VQWPm&md7RfVhSofh`DT-h+89r%i<#VCSkwlaQV{3N$%;l!Wk%a^`O&2&5>6{V$@ zj$DC4Zy)xV9zBy(m=gFzJLoX}xI+lUqRu{k#iXw?Uf^<6z>z zkEhSf86o^=4QDTqZs)Y)Wp-sz^XF48p-Ll;i;GbrgEEXoPPk4M=O-KNgsltm(s0mH58cuRZygk3?M{nO#Xs^H;gADV_v;dXzu@kCLhGV{(N5)JwhR z0L>03pFQ~|-T1kG zDD~JU^zmlqH5bwIk&yVWRVjlBHQ25`YYHUYHGbD#-yHBKV6c>~n}&|eEW&{F1XPM|D9cFnH3$WnE`a5q)-D8wRX&l>GIAi*m9`HcJ&nEyv)#z?l6_dI*Wu3 zrM`hHMsYFyNChA9c%VUf@*SGZM7R{^&`pk=8eIDcTG_+1WkR}{IA!%BYhsV1U!t1^ zQIKR?ZFi$aaLw%Qf;t;C3CJlwp7gR z^KgmwEGB%+_^ovqy-wFh9+82g5#OHfxiDN%RIvLAb*W>~?&c2?K@N)&iNK|-;w7lr z-)a^B&o4MEJ-*j);|9Qxn%EPKe)!td!X#H25~r#PmS8$6+E#x9>kE4JDw@_dcmHHf zfbEPCX-WMi@4V1|3WmSLGv0V-v*M4&H zr|ao+JP7>hxp6Gop4~U7KxwtVat^~Ns(SGJKKgUShA6Rbbnjw(Gm|GkGssw5$%2@&J@xQERuS!BHmKB5hxR18xhUNoB$MHZWs?MH<&Z%QZPYmZnKw`~t9WUP4*6 zzdOu>Yd|y7zx*H~J+$j|(WP@0jQsnwP!srN=2Z!wtdfe~R2WuwqVn1Ap`^95Hkx{KnDadx_7`1#|dz zbLi{b*{+>C6LGX>PgB?!NTeuk@87(UH<_|3P~)srcYT)9ZNXNeo`O%}y5n+d4Vw!v zF{jV|P$Wp(kwh`7HTCD_|7a*?I0u7M3{)n2k01$=h3^7r*yTp?x$ZRqj6st{RBF%km z_OE`Jq5#M>Z7>()_!86JmycC`n;S30rH#}nQ$uW<_j$lZA24x(e)AGI8%*jRLRgtS zs+O8>`QJ(C;1|*wdefiCwgz@?x`X~vTd7kcPv%mq>#DI8`e&GbOd&(NAKa%E_Uj+> z5P-@n#nV>V*>8nNJ*Ckl`igljHj{|_uv@3fo??||f+tsn{PD>{@Z>(_y*@PWR9dO$ z_FyrN`LQYgMEfNu6S~u-;(hsBCj0le`N4)py91 zNiO)!<~2q+nF?319eS6^42i;y-7M6WA2lxlxRb|6mDd2hI)ppiEF|jxZbMe5=$=)4 z`7bTN$FB{_GSt`OKYxPFEstu8`Pn%s{bt&@DQ!J-erxhX9^XF|4gEjD@SYY-*|rZ8 z?iv0=k)@!={~V*9<^`o18cj{AT}BIzIztU3W)$=Vzai zNcNLIFeorFAp=CPKW6OgP)S`@5%L$c(Q=X^&BC^YiE$@l0Pt?729zDrt=nk45f!*H zwE=U1=J@FksB4v0KC+KHa*3?i;o_i&&117PsO&_%n&6ecwJ`An4^+Z5+~4s}DYmi6 z|4H5cPgj0hOZR%WlHW2w69NOWW&(4}-#a9!g`Z8*ZRe)Y^S!D2tJ&t zhT9}!CXFiV)@l@tTOu)Seif}h>*E8(i@*vyAlzvh za~(`TmMZ;O@bd;;^y&0QC7r;9$qlE&9P?#8~gG|0qhKmH2Gj*CAXS`rQ&iu6oD zMCm*)YHxf%y!}1r&~Q%P1xL0T+TxlX3UKH!QNlRMAX>AdUpPN)8)P3VaAh?q(FB#> zsmVbwb{b$CA*x%LbY`(Ey5wNzD;*erb95+7XEHQj052koM`J2-qW(k9N#kZbswgzu zKQhm>lcx?C^_g+ewBy7RF*~+2Wu^+j#ATUE$@>+~Ig<9l$q$c%lP3WupW0?z6`|Q3 z6!i5Ck`1VK8JH<=blbz9D(E=gT=4%(!f28+oP5xVi3) z#O8$#laT}JB2^6F@e+U2mZL+n%qoArdn=Jo_c%o5bF=yR$=k#A`v+JsTLYXUiyFgc zX|ta|Rz$>k=6Jj-K*U0{?Q#I?OcI`^=Afj(IHhNPKqi@=zv)Q*ev=HQ z*=>@;)51pBCy{~wPCIH@pJ98uWhZ3(f06f=QC0PQzwbm8MH;2cAe8Pdk&u$^Qo6fa z0R;h(mX>aiZV>72PU&96q87FPc-_x4_P(EcpY!6pJZmtnYb?fcG3Wf(FTWqLKV?;e zxm7fwL!k25y?R~wO>$Il5bns8Wo@yH1fQ7Pvr#+8#=9x;F@lDJzd{OVo|U|yC|BLn*Q`L;D!!JYSAi&pOU@t|TgW&$)AJ5Cj_WQ!f_^Hgd6| z1&1oW{45Ddb3>(4M=j|%Gz;G@n9j76Z0d!TeTBB5V+Q4 zDn|XVXYwc|N@_KETqI4hLQ2-~!3b>X-Ap?MKly1xKyVOU6mh1!MM@HKCp|&+ma{D&h2wRz zEB?B?RLaoCWP*u4q~(1uRYdjKnV-b9rGC^8)qFZyx}F{j*y{=RTq>2<{A4tDYr%LP znzyZ%*Du=G_hAw=QF-k_RtBg~mn}<2ZS2AmzWRSoPidM&a@{G!Ws$oRzi<*XzjY z`eD$UAZ!4O`}N;m@Y+H&#_>wc3TdIPQ1^h5Jr-89YOK8aHJH_{Z*ZV5t))!;^GP^s z7YBj5|6N#HBIM z$COa-7Qwq_&d3)k2lrMN^xRAnU;fMVw}K_J7aCoK45Eo1oSxFerp7$m6TA5@kC@yh z{=LY*)zz9~?sRdo!{(+cImeIZ^YAZ-oOqLL?k*g7)tFO_dQGCc#}rqcF89h@7Fh~_ zkN)}JJzlmgN87s#F@%n_>FLNNIvN^OG3?dEAfcIRsnLWk%3^ zw`e@&i%M~Ub@ko&ob2%x1s!2PXOY+w>|7=eszAiPrwB> zM|Hls8s@!aEJ9EmP9_jWX=oIs%BOWSzq8h2kZ@zqpQ2cSGuGqO_3JHX{;!J zF_a`QkToY16UCsGoAPI3kISt~pWMXFw5s*@Aq8VAkLE$v=d=CEg2He~QRQFnk$=@n zS9R&hh4Wu4Ey3gKRZ%$Hy1W_^y~zAOKPr_n-%c#39;rKj$i3qfYmGBhslPq&$r)py z^JaaG45`CY^XEW^pI;+4&e0hwu~?I8u+aCgg^N$}bf>h`u24>~&ldp?X55G@r;2!0tc+o6j@{h62Lt3hl*PaMh9*V#wE$V1w-(SB;q2Vud7I<=Y z_|m5RnnM=-5jWDk*Gw!48}~P}fNUl9J8dZfSt3kOlkt~D zy7*f+uR8|_Yv&UJI@K)+HSc3F1-pY7J!jlVXZ?dLiiyi|H)+dDKc%!2T`L;7?~9v% zto!w&qhgZk95+SIjO?AEMSF$`&kNbv!Wp0IGKr>o9%W*N@Hx~md%OfAW3&EYil9s` zmce`(+NNZ!;dc+SgKC5CD%Dn=I$*O9h4_Cg71AHh-y$#QdS^3HXT%Y@dzFyRBfYm{ z=^;?%&kc`zJlZIpI=s<~tldU13`2&(tcpf9GeT{uVv8E0Uh_*k#3&X%E#-rNTZ)xio(B{Z)XqC%af>Avijjw3G+q4>+1WLob+)p0BvCiJ@?Nn=3 z-SF5Bj=hid3a2r&!?wKDdXA+xKcDuG(vA2R-v+4|Qp62^F6w^q)@O!te2 zUXmqR(%h>M^5m1g+OO)>Q})0SVaVd3KI_iQ12yTOWaionAqup?R+^TfZ}G`*MLCEu z+`M}YS*dWls(NDWYGRz6>>)xy!#CnidpPKEt11 zV61b-u;hPcty%MRHx0ZG$}oR+_(k?$U@)v3;)wDD*nenRc7fh~&a!B?@tIKZ{FX zaani+8yYv$_Epo3X3yMczDi)qXn2qsGdlgqQ%sC1(-5@Bz+`-u;WbBfrxa0dDD_Kr zB`A7LAY_OeA0Luex-fmBa5H^50y>8gkw7Hp!f6|DxH%8D1p!pEu zuXM{@84@`9Lv-G{UA~mZ8|^OcqNhgU?Og#kvSfNyIJTxL1uednR8g>+8~)Qwu(z`C zGWU*eZu5LnqLt9qskuthp{RZTO3|(mIqBI{$%dljT(CKlNDfuS38;}(pg7x`OZRZ> zJ=VE6c@!yACP5H(TVuWACqU{`>q^(qI{6x(EA`h`8=jXrR~bJ}4F6ymc$maacwR4XAaXSG zRm{p`_hy^m%+GNHk!%Z9)m|#8YY7qxKK-7+f@i)(v2DiT&;?c$I0xx_`!MHgrK74R z_lt}P1a!AQ^p=`K*azI_W5coK4UbRrGoeM(HY!|C7rD>*Q(`JkAp46%8rZ~Fnr^~{ zb@8Z+hbix0GvG3koAj-U69*3w?qku$n4Z-(Dyk%2M{c_{dWGSkfv^x_%5bSR_kl~t zox%Nj^9o-6!!Mr`v?hLaG(HLYwQ7&|kjHK7NTzCiW2`90c|M<$=;r0D5kW8<5hEeVyD^bCmw zH64+A3flq#&toqQJ&+ciU!AMpRQhO3N7HU2{Tfg(H82ZT6eYX+th}V+4s;morQ3d@ z=sGh63Fof73O4L^C%+iFpV(ns@?EB_rEcS&&9c3>zyGV|Nm_|IeYpJO(7?dN%!R5* zT3(}WraOGGG$B|TmMj1i0q)+p-f#AEKi=qHwI9%_2X~GHG^|1hIiot3bH}zAllVZT zd`QQ#PMux)&m2PNyUZtFCa`^AfjY`x>)9sr_k0oVcqKEBQ3H?>Cn^@~GAPfvfA)ay zbk%0$v5^p3_&NAThB|U!`MlglNPqGhU!03gYkN58ArK)+u-f*qcW?@>aZ_rVB~-oB z{Il8b_w!p}a~@H1ti6fov`} zG$s9~c&a_Y!NT^KLgx6TGedNQ4`;#o^|4)X61T(n*?Mk>hP~hJJ>TENQ%`IN*r=7# z3Qlpg2Dau{_PmLB=!F<2XQtviSh&gv)K4td`CsOEIXWM#_TC?gEolh8?_^iEq62yXR>| zg1RBt=6ITOMEsFmmmVF?D9g>qu;N%y75*rD;L>67i9+d3Ck}Zm-}WvMI!f!p+q07k z3eKzQPl;E+{E3O1>ipC436u0&Y)X^e%n4O6LHLjy0VDdxY*3>1(e4CKo)7$tmfpas zC?suxnW2;n9liD>xSGgs9O&%^)gtXFcPc@zIIs8h&=OOV);W5Lk!hc9#mSvtvo0pn zGeHOW<~Zg_V3aQDz7m!U-ju|}#>!osxRjOYC0U+IRZNVv#q}AZoq3u=Pe;uci99Xd z_v?cUKTdIeUY-RN#=;dS#M>Xqi#{`8dr)Ejw|e&JBhf1qd*EU|i1UqkyPx~_HL7^~ z3jrmDq<;!+@BAbBMg5O7nBl)P!2bI!I;Cs4e5Y|)ZYGvp&1}j0_n;(i6ao&XzwQfU z)a#bh^~+kLBa%pJMPvw)S5sRbtL!TvV#`6g{VNUfD7cqfDdVu|Ixb65QwbqGb94y8 zBo)LRrTS6w;_tUSKt|QgRn`p&95k=^iitT&2tl(iFr-2Iraw&T#PN%j~b{x zzs3N4?4Z1Z<=f(I!59*Bj=U@Pr74MUu;x+Z)P9<%Na|qwbVz`Z7N~Q5P(hl02y~V> zxVW-o1RZJEA`RaES=)+8a7iIXKC^3~MnglZ(SG}{uQWR=Pk8o}$F0*BNvF>7&ynjW zp|G3SJt$DDaujIog383+z1y5K8XIl1&CPLD{Pc7ff#+ab6B`H0lV~X<-;QNPWbgrO z_g5jrX*UZy8l+#_I;3L>qNC&upjN-bhnW$?ph?+(5KVuS$P;W~bVCylzkC7ee;g?9 zsIVblW!iKUaMe%Y9|@xuHRx5nyaX!Xshr8=yh)5)Oku=9&Vf-Je4rsN^cUu(IZ|K+wiSU94($ohQ{7@b{sV zlU~A#P54)CT z5WBrxhxYxWqx2X7IWP$!puKw^%wsT|17H7G+)CJCyKk1miEbO0{WYQFzcO_HJq7=5 zf}-=^mowO_W4k!rl&xocNvCzT8PT!4vH3kN?&@r=Dxj?mv`u8S%b=Yk;#VRPiu-ly zACtQU5W7adD^7ok`>?7=>tbY$q2!>d^Y?nKL>ep-u3%W7MRV5Dan0wli3^30<4m`Y zL=t=V^CHe4o_+kDz?J(U7C*9i@xaxS9E^pp>Z~phks6DjI<?qr$XnP3NHxXEM?4lX^S{ zxLOTUeN~}_6;kOn@jB%+oUb#-zYUoTr)Z^u`zSrMUmDTXqDyU0Zql8rJ94d$-9~<0 ztXr6TGekq&moAuHJXYyqdvo32|JH)j@&^j>XMt>^yZ7%oA0A0d$rh?j9Gzd{w0uHw z+$y*3QH_=oD@5FtmhQ2MVO+Im2qPD=6KeX^-d<}`Wv!SSRq)TEm-Q&F6tbSp;93|t zI6AT~+6kl)BTE)pez94*#CjuVfsoznaSYl9EI~b)(!u15DUR1rJB3 z)OBcXXD4rK3s^nR!gF$}U11+yqjrUTZJX86p^+nmZSVH68&FeH-5d`j=WT(EH|_&f z&yrqMN>(;DWZwp#OYu>khcV&AE3PRtKBFo$^zGAKQI=eVTOBn^ncoxai znoV2K;aclnERQEO>5lO!XhPY;*0P;pV=(-@hsF3UxH>7=*WY)i$o<&U%fI`9Upw<7hm}r1VZL&QLcam#PROI39m@x=^KCW zkYA%gQtwVr^|&-cyn?z`sxM)=u}iO3o6yofmn-ra?Pz zb7Jx*>DfT2M#kvuMMhcK?(r<{lKeXm9wZKsN@v5e#nXG!Bsb17nPSqwmY!a`u&(Dd zH))e!DdGsUz7VIINqX|t%cnwp>c-0wVY(+>9TW^&MM8=bgqez6#$`8rZh7@-V4M3C z@QKmYXHP9(H4+bTyhjx-bxO{!O%oeNB49pr>4p~T`BwYJ*3KT`d=8W=E>m2tA3~AT zAs3EAA2aoQ@<%oeot#LjtnT~r!0H*oyH7|xf4V#oVgL)KYe}rj%xt^La?F$+^zDyv zwCgINVm|b=Y1dk33RnmXcKBJ9BIHsTEi5cvby+$x)m0)lK>pzxiJ~`&%w_vT=ssp` zEjI|z0m&&bBNcaX;{ofZh96yiRvkII2q6|w^$&Xkg1MHK&OEQ9P?x7HPg=O{LO*P5 zoSbAmMV5XwdUf5kF|eBJ&);oNsS?tLl0t<%nSgx9V{&eL_{PC~I^%C)RaM%IO$&p9 z@aQd`XQ_jAI&}*!yU9W(F`w%$zAoH&T8(ys@w2(vbpewCahe%MJPLGS?b2HWFAnox zT_G6ag={vt=vM4o*27Pno$q{j!f}PkvG0F26I2`!3JNw>jM;T<-x1*V@UOKig=rcT zKWBFfy9+)4gz08*m=TzhuP{+G6}&s|Z4iGQVRrHcg~$@eD-81#=AzkzDVbaFQkb5W1|>7F{`9S8INxHQ!rB+J=uC{Z_ibH zm8u8R&F)W5ANTkup8gc(^PV*hv@gu8_Ec+2+bj2}QX=eEX_p=;Dk&Yc0A0`1!)Lf- ztq031_HA1g+kwcLzn9WdR149!aIsysE5*~h8e@?m`v4KzNSxy1Ab$~j1bqCzY5^Ey zNt_ryaX*x{Sy8hlVP~YL=i%5r)u}^z0*WV7<@;0EfTwu^CLWOG``ZOFN@s7Uk#HMSl|>1-W#wHY$jUqoTrDpGDyf^W=PR zER#>^;_GnvH>3$J7&|~srju&q!g~${zb8cTO!@S?Yi-@?{J?}c3HP#3raLB-$nU{P z#o#raaVtY$)7n;XV0(Ie@KglOkmjR@$a%Gjw|f68X&=)Ie&@p|#Y}VCs$DeL%SjayM^l{SUcYZZ(LA%MH%)iqr*YSogSQw`t624`@XXp2|)E@b6lA@&lrmx z-+8Dt-aDQQXcW4sejgbSAZBo%v@r6+-IQ3D6iYea(kMtuYGH+S8Uf{sb+dSn+IZoA;I!K{%cbXVeFW&g=wa2Dwnj;A!3 z;YLORU5<;BJ*S;kNoZrdBL6^|k(MzFABj*%5DU5^sQ1k5EGAPedmUSrAaDp7xHPC$IIx zt^D{ziN{q{ugUm|X6mDfneUv`(g=)^2lcG-PR;~Kh(~a+m6di)^cnvAyK71@a~Uua zV#{YMQhdoK7hn(UdWU`E@_z*EQtDmh7E&rScYC7en%{lQ*0%iCwNaAEj%Vj1+hu)Q_YcsllxZLae7?gC7@0%B+ zDV8B`v%%~`;Jp4ELM-Tcx$)B>_VB$3w+o+y@V}oMc zjs=l2(NjjIJ-|^a-T7m zbNkH}ob;n&E-0134AgMsC0qVOJ5m*R?X{Uc5Ts0t43St^=pP;xHvu!eNAUctL<)k0 zJ#}6A)2~YrAbP?W*=0>5P#ZesI=P(;SN5R%8gP$){@Inqkz8<>XLTKD&0Vq3HEz!)82GLwOk&!rm_!KSNHz8l6X zz}C%e{V||Xp!JmbFsvTed$q)d=ZQ0KJLp`e=}#1J_@lp|E08T4zp=9Mu9wWD0yjuC zA8$j)5d?ls_c_@I`D&gLS=xYj-|2$Kty~TkYEeO+RGq=uo$PQBgbATwo1U1_qI^6) zI!@fQvW7J@G1ldF`H3RZ%gG({&k(PGo#s0*J;1c{B7Ybh%t0*c!Bl)Ug9?3f5u$)I zl59U`9OQg|I#=vcys^#2F6(|5&0{Vy**r{?6lL=^sCaH#-o>2c?Q$RKW=Jq{Uq*BE zyNieO#@?T^kv6SODmgoOMfK+igKa&(XLlA0>qLWsF<|D-L(3KM^M4=C{9Ir3z_O$f zD}+5W4dyMdIo=kIVq<=OJu4yg0QKQ88u7QN_^qv_*~KTQK)q{9T}wgwIA?5YzmtyK z+FA!08MsZ1vH9|y$3o?x`~_GWvHeM3Q+Q>g&fGjA75vaExlYEdD#RZ>UR-!i$&EmS zwx1A$rkdFpsf-o2wgPJ%_3p=PP5W2xpH^(VR8dw%l-o!!-1Ak-T_-d&4Bl9X6+~F( zD(6jVRe{C;kFDABc9a&>R_2O>u8_s8rJc>a#-o9z9HixU#cU|D!JsnCPEs-(lk9CG zk93ryXFLT4P;k*dNDpuNN=BR<+bAY`WXzQULR|@rG_7+sK+f`S%rOhSX@T(t#rDEU zm_@E4*!<3T9$L{eD1OOlA(!1AD2)4Xmr3mfz7O-w+2)80_0e%jv1BIe5-lqPoG=Z5 zw?NV}HE7}FvYBZwtF6td&HBVW+!Pr;RV)W9@ZjO7;CO|EBv2c`U#YEmACuzB_p$&a!Xb z#(*%pmff3)A2hH-?CD8M-HVn&|JD>vn<1tf*h((eTE81GUs$+ozWDzRT5jKx(4dbA zt*9t`a~HB^ECQY);zH1G7dX6jRo0<|yyc&}G2}?KV;|SzLVG@FqhoZ+$S`2IuNxSRy5*;XY>3 znf}y7ijVWoO72pGqF_n~Cs(%W9n=+OnR?Gl{m@TIQ7GzlKr(bQ7Fy?}ryzbg>799@X8XuKkZfOl#+R}x8Y2?lf~NRl_H zC@n35P}YhC==y<>%b?JrIr?!=r*3ZY>#)Xuwj^((y2}gN5(>K^?178N*;U z6S+{J+eCOaG{6WR^N%I%%TT8SyLdf>uf!VrgxBhtnPvcn|K{$R-gx z?P@wCJDHV&tUnN76Ut6W6e+|H>q%m_-YIIh=wjKA@o&Hs&_cO5YEHi)=SMJAl#jLC zy?Ha8#Mgp?K|0!$;yX}W7(E*jw&1akU7<*K)b;xwzNIsemss#PRWM)(aQ*(UK@oUP zWkT9-7_44RZV$4-e_tFqh`3<<c71;M;O>UEF?`e z$=NJ9Noq{}mW$;l{~N7C8-d^TIh*uZXVkglJM>&+#?@W1Wk3UjOp)}k9ge6ufKI}L z)HO;F-8lpS9w?_U^Ws(4dWPER9zQwOKdmu8Vh@QykpE}ZBPHou5d}Cl2q#Ch1=}AU zQsQ>y4F2IKXQJb~7?|@oJPbv=Qv8pl6f3crOd9nY*3Ql|xPiDAsJQ1CVI6Nyv4Ks6F}4o2_$T4uAc@cM z0U7Ixy>gUP=5R6o1`M{bXuEcK?@FXlmECQ*L&i>H&IzuAJ%AFk5&*aNz4LA=_TIZ3;OVn7t*BRXusw9s(L%qZo;;!cZ(oEZP6m4M zk|95*0B$})y*F-^b|(}}x|PxL8a5MP6zP2l1YPavHMaSoJ31k z!OVzi|L7nnq!tKuNsM<@CvbT8ZYZ>THZnFsJG=C#sc8*`gFt4T({B8?M4)leTDkPC z=#^^<+3j5Y2Bt#v|qxqtBN46aI?7r>?)s z9#IGmIkGHjRtjv>H^&j#z*E)LeaiqcizWk9&B($!I%E|OI6n5Q{?4yzlc^ZXnl4&< zQi&>(6YvN7R+;{PBpUxM%k!V#Zn$|3VTdrz^1rn2P6ApKHd7AEh}gnbu2S~&)Ra!WD+?7>0P*Vw4M5BF zdF0q46T7H{#6pe3eTbHp_V%MA=J>$@LgXL5Nt&nL6*3=v!NgSD+4%-w=2GPeA3bV$ z$6V_I(^Xe@-I-)bdTU~0GLfr9qo$@Nm@@E=IWIpyGUE2tN#(dX+%_;UFg+dL{O%29 z1mK!gS92edG;O9cJ;%Zdo6z-;%~T{4^sJUk5q$gh?eXz34-XFx4o<5L@`xpipB4$k z>$ri9jSc8(6`DX^)l5c4=KcGpMr4}F@-IA(`nZB76m#JK!{~>C0k9e%(|mJ%VFNxP zn~&r>u#QE{-r3eBmMRZOI$B_@YG{O`QSjIs0)|azS72bEzyIB(isE7zK;1yMcpHGT zftWo`EHOW)3)L_53brpFpr8{j{`r$C|Ds5*2^1!NLMIZTZ{jJWz8;5c0hZrL81UtGF@TOO6dj9Y&R~;ew!p!Z(O48?d>g<3CJ0^&_)&E zp!M$J;-YSYd-zdpZ7m>t?tv^M6&01?AGFjV(+tIzu{}ntae(!()EWe+Xb`BT4{}O3 z&45LL2vf0W-6(8@k&;}2gYsb1F>0i#2$It+1UXg z6QH1ho5rLNyhLmlBSW!0g#`sNva%KB8hovjD#epk+!;kbD7~sb|&x{{8zP zZ33=U1hLWcHhU!C^XIau9YHSyh*d1+0T-bra*`;9edE{05|)$f31z1o%Ig z*Wj;OTU!In8h~1zZC3KR>|wv=U@vTRJ2D1F5MZJN$pf%UgU2cKqp}ho0jI79qmrs7MMj9kTBKpP7b0jDd3{V?F`*RRdZ&6b=A z1#*cUkg%H@4@>VP;EVu)&(>B^kn&ee4{O{3DI983U@a) zI`vDSUn94#$O1XT4pk}vfhzz3K~S+5Qcnnh3H|&zGE`q*-`R=|0hn!C+Q-?)a+z^n zA=*^{R0q=I$iiT0k&=><=fek;ZueJ!z#N#FnE@9C*8bdFQXsC{?1xI=3E#c|j;9qI zlN_s~{D8rz*W^u#+0oV(0PK$E=PMDQmP9+>6%&LL<-Rkgf_a0uVDc&{DLFVeAPyC$ z#68}fIR$LO&H0A9@S#{8@I412xypB-l1Pr~HdAaDC81o@VE6eKvFICGvX%K+S)W{= zMoUoyq~J!LPfDcUUiEtb6mmPr$TsJIuqD`Js7JtG=l+pfP(V*d2NDtPo12@hFT}v$ z%+1b1!qky~lB%!`a`c(_0)93j!NF*Dyb;OC-TrAG z3H!nAHYqPJtZkG5o;xw=eNJ#`-?EcezR{=ReXUcRe!E~EAo8jns3o?dk%vjtGY8f$ zBy&rF;4PRi2)y{Ij!ut*PN(M*`XCBgh~k@=NE$8GW?ZHNUfSA=@4LBhr=0b*B~k$P z$K$l9xVX5kj?b>-2>@R@l6Da1a0ekJm)4!uUZXvh@o5)xf1#SJH#U@H|969fN! z_3A@$G1CTy#E67!L^FeUdPatS=Y7EL0ah*@6O&2VR4d-n(vrUUZcH0!X|c3SOiBup z1nVwHR8dPyS{pCRhQqC&`0-=PXsLU5kivH#prf=54@b28c@Q9y)(YUmFCLGNjlGPP zVnw<@AY!7T02JmE;mfBSWntl1*#Z9kfba{ZIw0J#PA94&`>N*mb$1^g9UUDXQ(?+? zDmWrkA5pD*P!JaO1)|(sT(MG_U{#8~x3@0^7k*HFkAF24S!AQl91pcICnxX?4*(jr zI&imAYP_Pvb#ry)kH3`ym~HY|_?{!l3LgLH#Ds)|1QsE)FPLZx*5YquWykW5_3xsf zeDe4I7J2>mrJ|w&X7Ziag^aYcc|}E)B_%iy?gC6JIANqR!OdYSP*6}Tz2e3#`38m_ zOwQ=2D4>u7>S`=3wgL5aL+v?xSr{HZKG;mBXJ)jtv_1y}Ao*$*QV)Dj7%>+S7yp!! zLcu}{7QKva#t$0~1x0oBHw6G%D{E@{0%~n-{f3%cKi1#dEAuS8et(@FTcq6rZ(=c8 zYV}~b17x1Y%sK25?6kELy#v6e+1=fZK)4sG(nWTG9Uqg7S2Wpe@Sgz%{LO<~9_7G* zTCQ@dcu#k?`4yMkP?cu(2$_&~eNGMtjf{?tCJK0PQd5iDSn~p*o0YCezyLC@s0BM7 zz(DcyYd47;T}%S=0WiVF%qv8n0rsA`kr5U9p$h+Fcp>%5>T0-}Zt@9CT}{npYxHH> zF8Ie_qo}XfZn|R^MgswkAz|5XAaVHd&-%IqgNHk7oQ#hmJwD0Jy(fX(2kv8)-*YRc zzdN%Kh5)AUp=&)b9{>SSsihG8yb$%`WS5SCA@frxDD!!FALBu4w*DoV7(%lR7*o_X zfc6KhhSs3Esw%DnJF7mIjIt?93k!?zH;+k4(IIfk$@c6435|OoPQcJSHKlQr>Is25 z39ykMs0zQR(^EH+qJk1!Sy9o}Wjk;Ve?}!wjj>(tCnF#rV2tf~#~cU?Z?IbycSs)f znFo<=Fp55TivdFKKVZ9Sx?)_nv90A5ZnBK2CYaa7BNsP6AC-}5aGZI*Y=zE))Yu3As{7e+OKM)0Eo*-i+_t}E#iC?Y zkz1M16KM4j+x)#N%B@c1|1G@oZ_$>2duv{EmkA__E)RYyWq)mJ)2Xxl1E0`iB6w(( z6HWZyc7AcOsLtia?#LLv+OrNYOG;ppUA=((KVkBDoQUe{(WcvJwCYI?2Fvh=x5Nn&bH#h4%dSn28UW;p}^q%gmqZMq>339fU# zzU;b(wpOMd=Ji2kp|K%|oSewbZY&Sa+1c5!^LwG}(G&}z*n&SX>1g z*omHJ3Hy^DN9k>wsVTAZ0O}e>#<$iToe!AYW()HcORWc>Z0Kms>y7B<#MB#5%goHY zxYnl*ZA^2#DO6Rm_)dx_G|zacMD6BQkr^W>N@3MITT`~ymjEo{TAPIr@$vDsygU^s zg~liM<6S5O+(*^)7=pu^06v_BfFPELEsKwvn_dTT4+jH%r_}8TQBbhcm*7)bMIaZ) zIyF-_2k5dOn?^W24NoCMyb#$4u&BA)WYAIUak>Y@O`cI(S&4ylvuw-#FktE63&xKW z7X;jlK4xlX>gXX_u%(rl-+ioy7-WC~{MF;s9s)*kl@06|q)oW__(I9}#BFll+3LE_ zRKY@mYV5W~iS&nm|JH8}{Bv@0l9`$L&NM01@zh!s)Xzfi099~nDp1{Xj7vxWC`*T+<)+Ka zk6}W(XB`wiM#iA_8JLpHalLK9LV!36Y-hiNwFDb(9v*yr{12&xvNuzyVbA<^t7Ayg zii_1EJ-DEE%-;b$K2vd1#q9A_eS`b)8yOjDXLUerybmN`QUtM_7Y+`pfDK;abd$Dd{@&$!^ql`y3!n>ajOH$%>}nP11P2BM&Hj8}n4bQeh?buI*=Y!5d*dw#WD$i3 zZ!+{up3l`p4rK-l0a64DGHb9mJrh3zoNE9OuC4n&=Du%h|m-pKrliL+M)j`aAH=kwD3Ks*Ce;YU+0Hvp?x& zis0<->P{SC>S}zE=CBaPC zbgcdO@lI(*i4&);loV~sfXzfd9rI6Vef_k6fO|w~dR2IIsy^qdRREYvPQI7GRa~5t zGg)qSOP$Qix45m~ygBITmyD!t?O2$vw%g8CG6CpEP&?{8!Y=(*T3Sw88Vil&mGO^X zziy>7Y2*Z@p2}@^6-o^(G>v>`d2cacZOVLqM0B&t)m!izPq=}vCW)YO@PMQx~StT*&Qf4&wG1(7c9-}aZ_!Bqr-E4>PQVOEwo!q ztDQR{spWH6f67gx@RPw5GAMaAn)e9p@L_MQQzoPvUf=;#kHF?l^sJcWIQZXab-)F}ArPvUdln|;Z5 zF~8K762W#y*mUEk^KQNO`RXmyb32yA&$~t&tgR78=EpT5B|^ltD6(yemAW*NdM zWMWY@v)Pa}mhox_ahw3KnjsWIC%I|xnUVSVeqeHRb=kFjQ2}cc5bw3?oR4!9mcegd z^rQ~0Tnpdqv9NFfls%VGckB1>B!I3+;Z+VnogQL6J#>IKTIO*I1N=$I7ZAG*MzRXs zd%XRPEriaeh9oG!ZvFyzIKjcvYXf?%>qo#@W_H;t0OJZc$Lxoc?ThsQ3yOk*Qhz)y zQ>dChWE$uZ7&5w8FGF3XRkb)e>IhPK+KhU2CnX*U z7)52T=wsY0Ewyj1uj=ck=j(|kDlD)StS@VkegSmiOR86|bfCo*N%Ow!v|)8p5ng=OAk?lRPXx|q-t>r*8E0-Ro*N>tA$LgnS<-@F7)7?Llb zF-y7mnWDT)(Jqw%@$;X8f)eNQ-nZcmtSi8E0hSz>`{r-L+Fi~Ax zxb#P-o15o{hDxfdzY9t=34l&Rh?0`>8^O>cTwJ7IeSIp$Mek*|u}~Hos;kdJx#myc zaO_|!Ha3{Mt1BdIw&_QaadWmD0Qj(pEX#APtt)*ARafwl_-MMO8V@eI=g%W^AlYf~ ztj3GMvuZ3Tu!L-#ylgY~b2kP6&KR~Z0AfJZin-cN-j5&&7GX?cqCT^^t%taT9*KZ^RFecpOLg|yVSBrC-hko?ptYj1(4aYoen}xXmsoIxXFap!Uj*fZYmq#KvjQvlW&_isz*pv`q5_Z50^tPS-W*TZn3-)VWjAK(y%mCiRoMQOOu%~90-Ony zxUzAq2TN_XOO~G&VGEM<_#i%q^lSgmYhWzHX1kv3(PXE%%+<>JT-P|#(4<3{L#ODO2-&n3vo1H(Tx`3i5 z*PE*;JiKVDX;=S%P*4ir6XPY@e*tUi0O1fok&U5KD|#5f`H1FgabBLF(^m5?0ZJ8T zpGn8N$4}w<71|#G0(W#{=sEBd`g(hTZR)&pwtEV)m;JPF6mx;s`xp;zo8V)r+tCr) zTJQOS1O-Dpn@No5Gaj&(K4Byrn*hRP(#q?3IyG-(NYC@2uf(7Oqdy@YfN`foY8*^L z$;ph3sKDVU_2vy_6Y^)*(Q1o{Cx`P~P_+}?he@8{Vuz!lf`r1tU0{zza1hXc$AWxr z8WQS#@+vD&`nXIO)tQ^ripf(`U(?a$TQ7Jsr=dYYH}$u+n9YKqfV*RGXsFM2VcciT z-RB}Gu`=8MG5qn~4S-51D4;Mh3k7-S;}UPv^t~z*Kw7-Mx+G$ozt~6*fHj*egA@*@bgo{aux>A-5sLNhmU8RvrMy$pzdrzW2Duug>&Lu`N=CfA21-qxHj-u?3P?HI{=ve^=(f~YRs_x zYxsr=Gr)E8@f}3HjC}sAXhSFvDA?x&fNayia3T*31gQXixar#c-fi|T=icq_6^nI| zb8dTHbnn*xM{o7Vx)VmSD={GvY;0CPYua4Nia=z8>Z8eRAIvvYcU_bHvo@7>500jb zUS%z-yj^ol(gER(fM5R~GF^j5h%^#n;Cuf1;4@uu6wk8UpjBn9)DpTeQ*{dN_N#)I~djEu*nw!o8p{~pj9(C8Q$$MY>d5?@*n`>hpkZfv;j&7xj)Bj$b)%Iea6 zY!;MhS*&N@=6wIVnrk5u#0NDsG~AY2H-RaaKW5GP0GzCqAutQ%<=u;+)iu_g$3=)Qj+URY?lzxXOOwFUUwb}-$q*V-7NBEBTV|ubjPGgPx|hQ-?w7%qe@mxVV^~mzR4{ zD7%vEeR%j2b@f42dwZ@&;2Sq_JWXb#@pW`G_|~6kMf7C$Vg?$$nwaBueZI)+ z^Igf}WJsj`mBr4_L!q1pk-U0>Zp6-HIjV0BhT@J(onKx&YI^BREFCF7zI+Y6H5U=Z zAnv{|l$Qb#8$;T&vfr9sB;Z*jT%YeOIW>1~njNAx6}B)c%*<9~896y!*eL;_p?py* znNO>ATXVCix+4F9oSS|AftACzk4 z{P$e9bWBbAVuW$EwX#6q=mOLlDc_Y(eZs-SFfiSp?WLPaA!w- zC9m_LD$LD={q~GNvr#TY3*cAbh)N2jIYRJB25h!85R^z!w+d5aFGS4?e`Cl~SxL>55P-%@HEU{a6g znJU%Ral$^^_x<|eVtk`BKG{VuRZsPGx36X|l;Tz{k z!hUz0qm{2B&JJ4J9l6wW?pSX;3!OW-EwS%n(XRrWGc84^ygZ*jaRlg6`rAeUG!CEu z{fe{VPFirEcWw4{aeas@F)+;vPf^Zh&HmYJ!e_8Q2+@`w70e*zaZ6YkS5aX!(<%xK zWR+zf1sQRhAO#^)Q5F(JP(MNS(EhAr`r?HEdZ)F}N;`x}c%@l93Rbs{fq@$<20PP?xExFVWqK>UjROHQFvOKmWw#8#i29A}C=`|Apw@ zgi_hhBRWB&@&(5eUCK;BBsDARQxs|p7GO&xr_L=cd3gf-0~m!yxa1X7wWx4mmz9wr ze;_Sgv(Pu@ut*mh=e{~I$vi#X*DySMxHf?~CZR=ycMchk2`RUU1g@N#)xpik=;-KY z*}?v0WtM#*KPf4y4I2E6rgC=t);Q z!k~BA=rjvSCk{;+7=K4H%0779N$xV8q>wbp+sk#bz`7*LuTiLT?#zT*LaSYtaV8_h zyXzJ)Yzpc(7S*M*kvS8U(kDWG^B18mrKoc_<$Ha#GuGJ&PKSDW#~C+K&{gUA4cSE6gM3+7fyxg@!sM~HRBtF*BchkGviM{XgA$|5H z2>4ItEBgDj95Iq%S^^DUWCPuWi)`xtI&<@8OCL^~CiG$AK%S|Uv-3+$&D4c;@dW`6 z9$t591i}m`y}5h$?>RSTs6%S|5QHCL5^#);2I1o>Dk@{>*Sd;|mP$$i*~?_F+B>_u zYe6By3QyeB@)8pbI&R6@ZP*lEO8`;~}3@w#(tl5~DY?pNMlpVc&!6pHcwqJ%e|HZ_|b4yFasgPbE{9KF!1hP`W}ZXilLe2EcG_*NBzw1@dwQW7`Z z(HN3&`}Xa%wWvw>>_xoj5@|^p=Nu^T*>L;puc6E?DA;Nfp})ZL@>*!rScy7t$#O_j z)9DnM5E}JIj~+dHCPo8AL^3j6wpPk(R#v6}?EPaLPg8l+w0`a=uwd&+b6N9d7Rf1h zzzsB-=P1_i1hGr0UM>F+X7|yTiHV7WGx?gbJRD%^hFC*OA)`C^XeB3r6XEA8zdWA? zQgUl_d{)b%uRI8ZrFKp;t&H#+g@$$^O^l6gUS8+nDU(6kx>P<)Y-%ZQz#GqMXlSfS zF*7kWG`xEI<_ju+W~#SWsH!4twna%rMX!)&xXmUIw-_KecdcMmXE1vJvhKz@4_IHaD&3mtrt?4_c zzvJiOp`b$5zb-2cTHlTRLgEci*L_~^{CY_$f#Ii|vg@&R6S>_MB_Qrfay7NJhXw{fAqMdq2_X1!(8e_QWPt4rNS-=FPj4q#JL2*~UuEHW z?CqSZG;prM<4*>fAeMP$96yW3Y~<9WJzd{G<(;t-rdjB6`I zp{gp96gmt$#PDQqgKQbYPi7y$r?~d>HXym;CEYDGdegkT9yK&HoH$Vh$)MQV z$?yf5l+XAXKGQ&FJd4NQ1=C4tcWD;Y zxad+*uBmxKoD^nsrj0p2ze7|kc-*kW#lxc;w4)Z2Jm@CoadgW-Ki1AR$5F-c+H#JW z+!V5>Zy1zWZ4LYU?CiESn^xkwaR|HGjJf^5QKkxR0EV%r3x?6OScMD0Yp|~>BQyO; z+R@N3KL(4HJX|v-H7&6XmG9z!kUl)bv`laF@u|WF10u~7z2lc(Lt73*`z#9=2KJYT z@C>Qc;D8}rb@hqG16lc|?zFT9pokm4Swj_o`>gJ>?IT~m)`P1mfc_YcpO~4L*bJ9M zm!F<4DGM$tK2~x&BwdRnj8vleug{IFt$q3QiMz0{(9cgUDanZV($J7p;qqrqjZ#Hr zrLqcIQ%kGaMAS`jTvGYI>sCOrTy@i`?Oxt3Ztjm`OBHv_yUEGNczAhvuV2^TH7^bV zsh%}0Ee(h(264w$?{kr``GiMBeU;nX#H%E%2$%aj|FVik(jMIQYBgE^44FJ%xQ)@ThMcO zAq~kfVRra{8R6&UOR|FjE#-AIe6{o=|`X{#RI~Fcc;n7I;G{; z;E~uF5OT;KoW4>6)kx+pb2-CvtX{uUk&%7!j3>~Kyh%89YWYYMt*qVgOuOS88Odk- z!r$H?ffsjnd;4*R6g%er?;jS`K{iKM;`x8OIus=#BeSPQK(n$xF1Q+^>^HdpNPy6s z8Ih6_t6SyfZF#nCxD;Qx-CuEnd>?uNvWZ8qFf#))N1XfSw<0Ya;B%g_yR-9sXy_$I z#v@?VBo`LM#Ds)Qn%-ZrEj|3%%$}TN1R=d3P>_LP3pUD@A#_Axp@XKTsimc?z5NpK zmc3bLy=x!&R6%T}I5gS3pD8gW{@IuX-$1CNY z&=9)+v#8~?fyMXmW?0jYd@juQwZILCb8%@@%A&ato8ITfHrAX6yStOJvcxz!?OGzT z0baYE+_~2^7gFfo$X3T1D&Gnw#!SQggJa1h&iv%1^^O$*M_RHnZ2~uOv{J=yZmx?f zTDjrlFeJH7!eTSa5{t=F zhkhofs2txb&cZUF>H7Mo<4}=I)6*^R#wvf`a+Q!BRqa=Py?;k^D4rqt%*EbgSx0!irRKW^i`{oNq zu*Ru;e4M)_;v|Tf+*~Yx0W0aT51nbH2BfQQuWh-R9_+9}MDAuV4G0*Dj&tX`G5>q< z4TPVeyTf0AICXUyQF6EL>J=@;1qOchyEw8}n+_Qh!il3JB0k>mm~?j`^|&ht-vzKt zujtm?*FPUE5?*VBSmYTuYM;Kq0!U=?Zd+SD&W6rvHr_=DtlM?kvT+ zPd9yi!FpEO20lxkkKg4&EKA!U#h>}9KW%6q!B2I?k~8V-MYeQ3$M9e2?zeiIqv^Nvj?`ed_RBc%gYadWN_?$P*wG2A~L~4aiu4{xU>`;mq+FuY2xDIlx&B; zY4cv2eFv$lhm-e10mr4NZ{Nsg+f6-oM`|Kb@vT1bB2v{Npg_#D>A7xE$3$;;_4GW& zcjZRVorEtYucp=se&pfdR-3%WvjTVr^Jg;80$(gMGBC8pFWaq8a`T{MExev_(?O0&YZ*@ryviUFU`haFUXSG&JgJSSk$#u9*lP z;znAUEc!q?Gjm?A=o_0@_}t_qEpxf|>!BZoi^uCB7{gNAzV>!-R^>rYS~0PmpUqGE z`h+PdgM6qk%pl`JHG}aQPc1ytpG z3Rg^ULcuSV+oA+2)e=Vi{Knq?ZDukxN|iSbr~@!r{sqXZf>hL9C{KMV~GEqygY z51H!1_K&bQ_gCM;6-cD+r6oHUhGAOMj(CaEmo6^#Nix#w>*b&$DU*3_jm%P(Db0o;>X#avJ~y++NT$?}(SOy9!$9G4Wj?ktmUc&B>W6)$5Llkqe;b=jM3& zv?pEy-QU~mwpODEFe@jswA2OuR8={FE(q{{Rdq~KB%J|>I2^t@^!m6EzW#{$no%w= zGyXm49n@W(r%e;wHg-WacylMW1M4k=f@^vleeTaOxQ6f>bum{*e%sg0H|(+9?*HS& z5r%jr)E96o$mADT?lt)^OnC_zEUFgy3kAIZvP}VpvjTUOd6k#DiLAyH(R`OdoPum5 zXA$A{F97C!(y4$K|1GBMn-W)r?*hgcPFjkosa>>l#eIwia1MzJKSgQUV&_FI!&}~+ z3;;?Qkl&9xGmgpsgqvf_9rz&I;rR$*Oj~IU;m5^ci1+f>-PwevzqCJy=q={UlIJ=}JrouG{uHDjZ6&31G==D&=Bk+*h)|H& z$9kGfM3F+zA7J_{&r?!T4mX|&`=Hv}d*5|;S3UOwW6~BRg;&F4h*O?UA5lle0`5g zMu0Ce$-5~ks_mBnBOoZ~TI=NnPBnvSk4OIl{$0w@H^e`_zOj+BJdhi3AQSuRKFl9I zsv8*K1(gBPjo6rdVnn3xseb{>`B2@Auw%A%RMXMzV20B|)qTP$f3${XOgwo;fOu|d zN~Iaewr8=7DAkd7(y@;uge;-{CE znha1YQ{I5DwQ>C`_XGq5v+(#?k&)qs_uqd%WgPpmqW@WuqLNzh3&Zl+`e=zE9K^uG zjWS1p;Ne%{0wljdW2V35P<%D7M=Nr3a&j`}%=GlI*r6y$6WFBUKSzuM@cSn)TPn}> ztZXaJ-~YR`=Tb$58Po%GCr&iFZ5^zJoI1_#7cdkPA8%pSFUR9v35o5E`E}zBBJs#> z#u+I6CE&kub(U87kM?G1S6;~)+i%Xy!8ud5`$QGn4ZjZ`P8;P$=jT6tSbOEw_F$QV z)yPOA94%`8`pE~sI(4w&L)G&1$rFG98j;d(aS`na)kKXklg9Opm`o5HEi9skxqt$p zzb}E>gS-St0_@$kx`u`rJj6U7Dt1d78#uD^0Ew>>c4_25 zQ$az&gH%1e;Yv@R4le}}&D4xkD>FFd<(^$=afumy-cC%6KUhPoIBmwMW%1sB$>O+) zfq}OG(F6BnV`BsSnQpn`Q7ETWMqlQCKwmlvZxZPVIl1S?#>P}*Sk<9z%UN_`YxuaYa26siKAft-RdHDR@zX7qN73u&0 literal 0 HcmV?d00001 diff --git a/drone.yml b/drone.yml deleted file mode 100644 index 0a80e56..0000000 --- a/drone.yml +++ /dev/null @@ -1,27 +0,0 @@ - -kind: pipeline -name: default - -steps: -- name: test - image: rust:latest - commands: - - rustup component add clippy - - cargo clippy - - cargo test --all - -- name: deploy - image: rust:latest - commands: - - cargo build --release - - tar cvzf conductor.tar.gz -C target/release conductor - - wget https://dl.min.io/client/mc/release/linux-amd64/mc - - chmod +x mc - - ./mc alias set fivesigma https://objects.5sigma.io $MINIOID $MINIOSECRET - - ./mc cp conductor.tar.gz fivesigma/public/conductor.tar.gz - # when: - # event: - # - promote - # target: - # - staging - # - production