From 57b58f5e7a89dc1d9e5c4c0c1c6211fe135a0e5b Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Mon, 12 Feb 2024 15:56:09 -0800 Subject: [PATCH 1/8] doc: remove comment #417 --- R/methods-epi_archive.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/methods-epi_archive.R b/R/methods-epi_archive.R index 4bcead66d..213cf1b17 100644 --- a/R/methods-epi_archive.R +++ b/R/methods-epi_archive.R @@ -470,9 +470,8 @@ dplyr_col_modify.col_modify_recorder_df <- function(data, cols) { #' @noRd epix_detailed_restricted_mutate <- function(.data, ...) { # We don't want to directly use `dplyr::mutate` on the `$DT`, as: - # - this likely copies the entire table # - `mutate` behavior, including the output class, changes depending on - # whether `dtplyr` is loaded and would require post-processing + # whether `dtplyr` < 1.3.0 is loaded and would require post-processing # - behavior with `dtplyr` isn't fully compatible # - it doesn't give the desired details, and `rlang::exprs_auto_name` does not # appropriately handle the `= NULL` and `= ` tidyeval cases From 0dcb5a6489ecbdc8c03ebb8f5bf715c8ca708502 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Thu, 8 Feb 2024 18:04:37 -0800 Subject: [PATCH 2/8] wip+feat: refactor epi_archive to use S3 * A/B testing branch * make sure the parallel set of tests pass --- DESCRIPTION | 3 + NAMESPACE | 26 + R/archive.R | 3 - R/archive_new.R | 1115 +++++++++++++++++ R/grouped_archive_new.R | 456 +++++++ R/methods-epi_archive_new.R | 830 ++++++++++++ man/as_epi_archive2.Rd | 142 +++ man/as_of.epi_archive2.Rd | 33 + man/epi_archive.Rd | 106 +- man/epix_as_of2.Rd | 96 ++ man/epix_fill_through_version2.Rd | 48 + man/epix_merge2.Rd | 73 ++ man/epix_slide2.Rd | 283 +++++ man/epix_truncate_versions_after.Rd | 10 +- ...ate_versions_after.grouped_epi_archive2.Rd | 11 + man/fill_through_version.epi_archive2.Rd | 21 + man/group_by.epi_archive.Rd | 23 +- man/group_by.epi_archive2.Rd | 147 +++ man/is_epi_archive2.Rd | 35 + man/max_version_with_row_in.Rd | 9 +- man/merge_epi_archive2.Rd | 30 + man/new_epi_archive2.Rd | 69 + man/next_after.Rd | 8 +- man/print.epi_archive2.Rd | 17 + man/slide.epi_archive2.Rd | 101 ++ man/slide.grouped_epi_archive2.Rd | 24 + man/truncate_versions_after.epi_archive2.Rd | 19 + ...ate_versions_after.grouped_epi_archive2.Rd | 18 + tests/testthat/test-archive_new.R | 173 +++ tests/testthat/test-compactify_new.R | 110 ++ .../test-epix_fill_through_version_new.R | 109 ++ tests/testthat/test-epix_merge_new.R | 228 ++++ tests/testthat/test-epix_slide_new.R | 810 ++++++++++++ tests/testthat/test-grouped_epi_archive_new.R | 104 ++ tests/testthat/test-methods-epi_archive_new.R | 138 ++ 35 files changed, 5420 insertions(+), 8 deletions(-) create mode 100644 R/archive_new.R create mode 100644 R/grouped_archive_new.R create mode 100644 R/methods-epi_archive_new.R create mode 100644 man/as_epi_archive2.Rd create mode 100644 man/as_of.epi_archive2.Rd create mode 100644 man/epix_as_of2.Rd create mode 100644 man/epix_fill_through_version2.Rd create mode 100644 man/epix_merge2.Rd create mode 100644 man/epix_slide2.Rd create mode 100644 man/epix_truncate_versions_after.grouped_epi_archive2.Rd create mode 100644 man/fill_through_version.epi_archive2.Rd create mode 100644 man/group_by.epi_archive2.Rd create mode 100644 man/is_epi_archive2.Rd create mode 100644 man/merge_epi_archive2.Rd create mode 100644 man/new_epi_archive2.Rd create mode 100644 man/print.epi_archive2.Rd create mode 100644 man/slide.epi_archive2.Rd create mode 100644 man/slide.grouped_epi_archive2.Rd create mode 100644 man/truncate_versions_after.epi_archive2.Rd create mode 100644 man/truncate_versions_after.grouped_epi_archive2.Rd create mode 100644 tests/testthat/test-archive_new.R create mode 100644 tests/testthat/test-compactify_new.R create mode 100644 tests/testthat/test-epix_fill_through_version_new.R create mode 100644 tests/testthat/test-epix_merge_new.R create mode 100644 tests/testthat/test-epix_slide_new.R create mode 100644 tests/testthat/test-grouped_epi_archive_new.R create mode 100644 tests/testthat/test-methods-epi_archive_new.R diff --git a/DESCRIPTION b/DESCRIPTION index 71d959690..538fd0232 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -73,6 +73,7 @@ Depends: URL: https://cmu-delphi.github.io/epiprocess/ Collate: 'archive.R' + 'archive_new.R' 'autoplot.R' 'correlation.R' 'data.R' @@ -80,9 +81,11 @@ Collate: 'epiprocess.R' 'group_by_epi_df_methods.R' 'methods-epi_archive.R' + 'grouped_archive_new.R' 'grouped_epi_archive.R' 'growth_rate.R' 'key_colnames.R' + 'methods-epi_archive_new.R' 'methods-epi_df.R' 'outliers.R' 'reexports.R' diff --git a/NAMESPACE b/NAMESPACE index 03e0e41d9..51c4091cf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,40 +6,57 @@ S3method(as_epi_df,data.frame) S3method(as_epi_df,epi_df) S3method(as_epi_df,tbl_df) S3method(as_epi_df,tbl_ts) +S3method(as_of,epi_archive2) S3method(as_tibble,epi_df) S3method(as_tsibble,epi_df) S3method(autoplot,epi_df) +S3method(clone,epi_archive2) +S3method(clone,grouped_epi_archive2) S3method(dplyr_col_modify,col_modify_recorder_df) S3method(dplyr_col_modify,epi_df) S3method(dplyr_reconstruct,epi_df) S3method(dplyr_row_slice,epi_df) S3method(epix_truncate_versions_after,epi_archive) +S3method(epix_truncate_versions_after,epi_archive2) S3method(epix_truncate_versions_after,grouped_epi_archive) +S3method(epix_truncate_versions_after,grouped_epi_archive2) S3method(group_by,epi_archive) +S3method(group_by,epi_archive2) S3method(group_by,epi_df) S3method(group_by,grouped_epi_archive) +S3method(group_by,grouped_epi_archive2) S3method(group_by_drop_default,grouped_epi_archive) +S3method(group_by_drop_default,grouped_epi_archive2) S3method(group_modify,epi_df) S3method(groups,grouped_epi_archive) +S3method(groups,grouped_epi_archive2) S3method(key_colnames,data.frame) S3method(key_colnames,default) S3method(key_colnames,epi_archive) S3method(key_colnames,epi_df) S3method(next_after,Date) S3method(next_after,integer) +S3method(print,epi_archive2) S3method(print,epi_df) +S3method(print,grouped_epi_archive2) S3method(select,epi_df) +S3method(slide,grouped_epi_archive2) S3method(summary,epi_df) +S3method(truncate_versions_after,grouped_epi_archive2) S3method(ungroup,epi_df) S3method(ungroup,grouped_epi_archive) +S3method(ungroup,grouped_epi_archive2) S3method(unnest,epi_df) export("%>%") export(archive_cases_dv_subset) export(arrange) export(as_epi_archive) +export(as_epi_archive2) export(as_epi_df) +export(as_of) export(as_tsibble) export(autoplot) +export(clone) export(detect_outlr) export(detect_outlr_rm) export(detect_outlr_stl) @@ -47,24 +64,33 @@ export(epi_archive) export(epi_cor) export(epi_slide) export(epix_as_of) +export(epix_as_of2) export(epix_merge) +export(epix_merge2) export(epix_slide) +export(epix_slide2) export(epix_truncate_versions_after) +export(fill_through_version) export(filter) export(group_by) export(group_modify) export(growth_rate) export(is_epi_archive) +export(is_epi_archive2) export(is_epi_df) export(is_grouped_epi_archive) +export(is_grouped_epi_archive2) export(key_colnames) export(max_version_with_row_in) export(mutate) +export(new_epi_archive2) export(new_epi_df) export(next_after) export(relocate) export(rename) export(slice) +export(slide) +export(truncate_versions_after) export(ungroup) export(unnest) importFrom(R6,R6Class) diff --git a/R/archive.R b/R/archive.R index ff3bc20ce..a530cc058 100644 --- a/R/archive.R +++ b/R/archive.R @@ -514,9 +514,6 @@ epi_archive <- fromLast = TRUE ) %>% tibble::as_tibble() %>% - # (`as_tibble` should de-alias the DT and its columns in any edge - # cases where they are aliased. We don't say we guarantee this - # though.) dplyr::select(-"version") %>% as_epi_df( geo_type = self$geo_type, diff --git a/R/archive_new.R b/R/archive_new.R new file mode 100644 index 000000000..bcfa84c3d --- /dev/null +++ b/R/archive_new.R @@ -0,0 +1,1115 @@ +# We use special features of data.table's `[`. The data.table package has a +# compatibility feature that disables some/all of these features if it thinks we +# might expect `data.frame`-compatible behavior instead. We can signal that we +# want the special behavior via `.datatable.aware = TRUE` or by importing any +# `data.table` package member. Do both to prevent surprises if we decide to use +# `data.table::` everywhere and not importing things. +.datatable.aware <- TRUE + +#' Validate a version bound arg +#' +#' Expected to be used on `clobberable_versions_start`, `versions_end`, +#' and similar arguments. Some additional context-specific checks may be needed. +#' +#' @param version_bound the version bound to validate +#' @param x a data frame containing a version column with which to check +#' compatibility +#' @param na_ok Boolean; is `NA` an acceptable "bound"? (If so, `NA` will +#' have a special context-dependent meaning.) +#' @param version_bound_arg optional string; what to call the version bound in +#' error messages +#' +#' @section Side effects: raises an error if version bound appears invalid +#' +#' @noRd +validate_version_bound <- function(version_bound, x, na_ok = FALSE, + version_bound_arg = rlang::caller_arg(version_bound), + x_arg = rlang::caller_arg(version_bound)) { + if (is.null(version_bound)) { + cli_abort( + "{version_bound_arg} cannot be NULL" + ) + } + if (na_ok && is.na(version_bound)) { + return(invisible(NULL)) + } + if (!test_set_equal(class(version_bound), class(x[["version"]]))) { + cli_abort( + "{version_bound_arg} must have the same classes as x$version, + which is {class(x$version)}", + ) + } + if (!test_set_equal(typeof(version_bound), typeof(x[["version"]]))) { + cli_abort( + "{version_bound_arg} must have the same types as x$version, + which is {typeof(x$version)}", + ) + } + + return(invisible(NULL)) +} + +#' `max(x$version)`, with error if `x` has 0 rows +#' +#' Exported to make defaults more easily copyable. +#' +#' @param x `x` argument of [`as_epi_archive`] +#' +#' @return `max(x$version)` if it has any rows; raises error if it has 0 rows or +#' an `NA` version value +#' +#' @export +max_version_with_row_in <- function(x) { + if (nrow(x) == 0L) { + cli_abort( + "`nrow(x)==0L`, representing a data set history with no row up through the + latest observed version, but we don't have a sensible guess at what version + that is, or whether any of the empty versions might be clobbered in the + future; if we use `x` to form an `epi_archive`, then + `clobberable_versions_start` and `versions_end` must be manually specified.", + class = "epiprocess__max_version_cannot_be_used" + ) + } else { + version_col <- purrr::pluck(x, "version") # error not NULL if doesn't exist + if (anyNA(version_col)) { + cli_abort("version values cannot be NA", + class = "epiprocess__version_values_must_not_be_na" + ) + } else { + version_bound <- max(version_col) + } + } +} + +#' Get the next possible value greater than `x` of the same type +#' +#' @param x the starting "value"(s) +#' @return same class, typeof, and length as `x` +#' +#' @export +next_after <- function(x) UseMethod("next_after") + +#' @export +next_after.integer <- function(x) x + 1L + +#' @export +next_after.Date <- function(x) x + 1L + + + +#' epi archive +#' @title `epi_archive` object +#' +#' @description An `epi_archive` is an R6 class which contains a data table +#' along with several relevant pieces of metadata. The data table can be seen +#' as the full archive (version history) for some signal variables of +#' interest. +#' +#' @details An `epi_archive` is an R6 class which contains a data table `DT`, of +#' class `data.table` from the `data.table` package, with (at least) the +#' following columns: +#' +#' * `geo_value`: the geographic value associated with each row of measurements. +#' * `time_value`: the time value associated with each row of measurements. +#' * `version`: the time value specifying the version for each row of +#' measurements. For example, if in a given row the `version` is January 15, +#' 2022 and `time_value` is January 14, 2022, then this row contains the +#' measurements of the data for January 14, 2022 that were available one day +#' later. +#' +#' The data table `DT` has key variables `geo_value`, `time_value`, `version`, +#' as well as any others (these can be specified when instantiating the +#' `epi_archive` object via the `other_keys` argument, and/or set by operating +#' on `DT` directly). Refer to the documentation for [as_epi_archive()] for +#' information and examples of relevant parameter names for an `epi_archive` object. +#' Note that there can only be a single row per unique combination of +#' key variables, and thus the key variables are critical for figuring out how +#' to generate a snapshot of data from the archive, as of a given version. +#' +#' In general, the last version of each observation is carried forward (LOCF) to +#' fill in data between recorded versions, and between the last recorded +#' update and the `versions_end`. One consequence is that the `DT` +#' doesn't have to contain a full snapshot of every version (although this +#' generally works), but can instead contain only the rows that are new or +#' changed from the previous version (see `compactify`, which does this +#' automatically). Currently, deletions must be represented as revising a row +#' to a special state (e.g., making the entries `NA` or including a special +#' column that flags the data as removed and performing some kind of +#' post-processing), and the archive is unaware of what this state is. Note +#' that `NA`s *can* be introduced by `epi_archive` methods for other reasons, +#' e.g., in [`epix_fill_through_version`] and [`epix_merge`], if requested, to +#' represent potential update data that we do not yet have access to; or in +#' [`epix_merge`] to represent the "value" of an observation before the +#' version in which it was first released, or if no version of that +#' observation appears in the archive data at all. +#' +#' **A word of caution:** R6 objects, unlike most other objects in R, have +#' reference semantics. A primary consequence of this is that objects are not +#' copied when modified. You can read more about this in Hadley Wickham's +#' [Advanced R](https://adv-r.hadley.nz/r6.html#r6-semantics) book. In order +#' to construct a modified archive while keeping the original intact, first +#' make a clone using the `$clone` method, then overwrite the clone's `DT` +#' field with `data.table::copy(clone$DT)`, and finally perform the +#' modifications on the clone. +#' +#' @section Metadata: +#' The following pieces of metadata are included as fields in an `epi_archive` +#' object: +#' +#' * `geo_type`: the type for the geo values. +#' * `time_type`: the type for the time values. +#' * `additional_metadata`: list of additional metadata for the data archive. +#' +#' Unlike an `epi_df` object, metadata for an `epi_archive` object `x` can be +#' accessed (and altered) directly, as in `x$geo_type` or `x$time_type`, +#' etc. Like an `epi_df` object, the `geo_type` and `time_type` fields in the +#' metadata of an `epi_archive` object are not currently used by any +#' downstream functions in the `epiprocess` package, and serve only as useful +#' bits of information to convey about the data set at hand. +#' +#' @section Generating Snapshots: +#' An `epi_archive` object can be used to generate a snapshot of the data in +#' `epi_df` format, which represents the most up-to-date values of the signal +#' variables, as of the specified version. This is accomplished by calling the +#' `as_of()` method for an `epi_archive` object `x`. More details on this +#' method are documented in the wrapper function [`epix_as_of()`]. +#' +#' @section Sliding Computations: +#' We can run a sliding computation over an `epi_archive` object, much like +#' `epi_slide()` does for an `epi_df` object. This is accomplished by calling +#' the `slide()` method for an `epi_archive` object, which works similarly to +#' the way `epi_slide()` works for an `epi_df` object, but with one key +#' difference: it is version-aware. That is, for an `epi_archive` object, the +#' sliding computation at any given reference time point t is performed on +#' **data that would have been available as of t**. More details on `slide()` +#' are documented in the wrapper function [`epix_slide()`]. +#' +#' @export +#' @examples +#' tib <- tibble::tibble( +#' geo_value = rep(c("ca", "hi"), each = 5), +#' time_value = rep(seq(as.Date("2020-01-01"), +#' by = 1, length.out = 5 +#' ), times = 2), +#' version = rep(seq(as.Date("2020-01-02"), +#' by = 1, length.out = 5 +#' ), times = 2), +#' value = rnorm(10, mean = 2, sd = 1) +#' ) +#' +#' toy_epi_archive <- tib %>% epi_archive$new( +#' geo_type = "state", +#' time_type = "day" +#' ) +#' toy_epi_archive +#' @name epi_archive +# TODO: Figure out where to actually put this documentation +NULL + +#' New epi archive +#' @description Creates a new `epi_archive` object. +#' @param x A data.frame, data.table, or tibble, with columns `geo_value`, +#' `time_value`, `version`, and then any additional number of columns. +#' @param geo_type Type for the geo values. If missing, then the function will +#' attempt to infer it from the geo values present; if this fails, then it +#' will be set to "custom". +#' @param time_type Type for the time values. If missing, then the function will +#' attempt to infer it from the time values present; if this fails, then it +#' will be set to "custom". +#' @param other_keys Character vector specifying the names of variables in `x` +#' that should be considered key variables (in the language of `data.table`) +#' apart from "geo_value", "time_value", and "version". +#' @param additional_metadata List of additional metadata to attach to the +#' `epi_archive` object. The metadata will have `geo_type` and `time_type` +#' fields; named entries from the passed list or will be included as well. +#' @param compactify Optional; Boolean or `NULL`: should we remove rows that are +#' considered redundant for the purposes of `epi_archive`'s built-in methods +#' such as `as_of`? As these methods use the last version of each observation +#' carried forward (LOCF) to interpolate between the version data provided, +#' rows that don't change these LOCF results can potentially be omitted to +#' save space while maintaining the same behavior (with the help of the +#' `clobberable_versions_start` and `versions_end` fields in some edge cases). +#' `TRUE` will remove these rows, `FALSE` will not, and missing or `NULL` will +#' remove these rows and issue a warning. Generally, this can be set to +#' `TRUE`, but if you directly inspect or edit the fields of the `epi_archive` +#' such as its `DT`, or rely on redundant updates to achieve a certain +#' behavior of the `ref_time_values` default in `epix_slide`, you will have to +#' determine whether `compactify=TRUE` will produce the desired results. If +#' compactification here is removing a large proportion of the rows, this may +#' indicate a potential for space, time, or bandwidth savings upstream the +#' data pipeline, e.g., by avoiding fetching, storing, or processing these +#' rows of `x`. +#' @param clobberable_versions_start Optional; as in [`as_epi_archive`] +#' @param versions_end Optional; as in [`as_epi_archive`] +#' @return An `epi_archive` object. +#' @importFrom data.table as.data.table key setkeyv +#' +#' @details +#' Refer to the documentation for [as_epi_archive()] for more information +#' and examples of parameter names. +#' @export +new_epi_archive2 <- function( + x, + geo_type = NULL, + time_type = NULL, + other_keys = NULL, + additional_metadata = NULL, + compactify = NULL, + clobberable_versions_start = NA, + versions_end = NULL) { + assert_data_frame(x) + if (!test_subset(c("geo_value", "time_value", "version"), names(x))) { + cli_abort( + "Columns `geo_value`, `time_value`, and `version` must be present in `x`." + ) + } + if (anyMissing(x$version)) { + cli_abort("Column `version` must not contain missing values.") + } + + # If geo type is missing, then try to guess it + if (missing(geo_type) || is.null(geo_type)) { + geo_type <- guess_geo_type(x$geo_value) + } + + # If time type is missing, then try to guess it + if (missing(time_type) || is.null(time_type)) { + time_type <- guess_time_type(x$time_value) + } + + # Finish off with small checks on keys variables and metadata + if (missing(other_keys)) other_keys <- NULL + if (missing(additional_metadata) || is.null(additional_metadata)) additional_metadata <- list() + if (!test_subset(other_keys, names(x))) { + cli_abort("`other_keys` must be contained in the column names of `x`.") + } + if (any(c("geo_value", "time_value", "version") %in% other_keys)) { + cli_abort("`other_keys` cannot contain \"geo_value\", \"time_value\", or \"version\".") + } + if (any(names(additional_metadata) %in% c("geo_type", "time_type"))) { + cli_warn("`additional_metadata` names overlap with existing metadata fields \"geo_type\", \"time_type\".") + } + + # Conduct checks and apply defaults for `compactify` + if (missing(compactify)) { + compactify <- NULL + } + assert_logical(compactify, len = 1, null.ok = TRUE) + + # Apply defaults and conduct checks for + # `clobberable_versions_start`, `versions_end`: + if (missing(clobberable_versions_start)) { + clobberable_versions_start <- NA + } + if (missing(versions_end) || is.null(versions_end)) { + versions_end <- max_version_with_row_in(x) + } + validate_version_bound(clobberable_versions_start, x, na_ok = TRUE) + validate_version_bound(versions_end, x, na_ok = FALSE) + if (nrow(x) > 0L && versions_end < max(x[["version"]])) { + cli_abort( + sprintf( + "`versions_end` was %s, but `x` contained + updates for a later version or versions, up through %s", + versions_end, max(x[["version"]]) + ), + class = "epiprocess__versions_end_earlier_than_updates" + ) + } + if (!is.na(clobberable_versions_start) && clobberable_versions_start > versions_end) { + cli_abort( + sprintf( + "`versions_end` was %s, but a `clobberable_versions_start` + of %s indicated that there were later observed versions", + versions_end, clobberable_versions_start + ), + class = "epiprocess__versions_end_earlier_than_clobberable_versions_start" + ) + } + + # --- End of validation and replacing missing args with defaults --- + + # Create the data table; if x was an un-keyed data.table itself, + # then the call to as.data.table() will fail to set keys, so we + # need to check this, then do it manually if needed + key_vars <- c("geo_value", "time_value", other_keys, "version") + DT <- as.data.table(x, key = key_vars) + if (!identical(key_vars, key(DT))) setkeyv(DT, cols = key_vars) + + maybe_first_duplicate_key_row_index <- anyDuplicated(DT, by = key(DT)) + if (maybe_first_duplicate_key_row_index != 0L) { + cli_abort("`x` must have one row per unique combination of the key variables. If you + have additional key variables other than `geo_value`, `time_value`, and + `version`, such as an age group column, please specify them in `other_keys`. + Otherwise, check for duplicate rows and/or conflicting values for the same + measurement.", + class = "epiprocess__epi_archive_requires_unique_key" + ) + } + + # Checks to see if a value in a vector is LOCF + is_locf <- function(vec) { + dplyr::if_else(!is.na(vec) & !is.na(dplyr::lag(vec)), + vec == dplyr::lag(vec), + is.na(vec) & is.na(dplyr::lag(vec)) + ) + } + + # LOCF is defined by a row where all values except for the version + # differ from their respective lag values + + # Checks for LOCF's in a data frame + rm_locf <- function(df) { + dplyr::filter(df, if_any(c(everything(), -version), ~ !is_locf(.))) + } + + # Keeps LOCF values, such as to be printed + keep_locf <- function(df) { + dplyr::filter(df, if_all(c(everything(), -version), ~ is_locf(.))) + } + + # Runs compactify on data frame + if (is.null(compactify) || compactify == TRUE) { + elim <- keep_locf(DT) + DT <- rm_locf(DT) + } else { + # Create empty data frame for nrow(elim) to be 0 + elim <- tibble::tibble() + } + + # Warns about redundant rows + if (is.null(compactify) && nrow(elim) > 0) { + warning_intro <- cli::format_inline( + "Found rows that appear redundant based on + last (version of each) observation carried forward; + these rows have been removed to 'compactify' and save space:", + keep_whitespace = FALSE + ) + warning_data <- paste(collapse = "\n", capture.output(print(elim, topn = 3L, nrows = 7L))) + warning_outro <- cli::format_inline( + "Built-in `epi_archive` functionality should be unaffected, + but results may change if you work directly with its fields (such as `DT`). + See `?as_epi_archive` for details. + To silence this warning but keep compactification, + you can pass `compactify=TRUE` when constructing the archive.", + keep_whitespace = FALSE + ) + warning_message <- paste(sep = "\n", warning_intro, warning_data, warning_outro) + rlang::warn(warning_message, class = "epiprocess__compactify_default_removed_rows") + } + + structure( + list( + DT = DT, + geo_type = geo_type, + time_type = time_type, + additional_metadata = additional_metadata, + clobberable_versions_start = clobberable_versions_start, + versions_end = versions_end, + private = list() # TODO: to be encapsulated with guard-rails later + ), + class = "epi_archive2" + ) +} + +#' Print information about an `epi_archive` object +#' @param class Boolean; whether to print the class label header +#' @param methods Boolean; whether to print all available methods of +#' the archive +#' @importFrom cli cli_inform +#' @export +print.epi_archive2 <- function(epi_archive, class = TRUE, methods = TRUE) { + cli_inform( + c( + ">" = if (class) "An `epi_archive` object, with metadata:", + "i" = if (length(setdiff(key(epi_archive$DT), c("geo_value", "time_value", "version"))) > 0) { + "Non-standard DT keys: {setdiff(key(epi_archive$DT), c('geo_value', 'time_value', 'version'))}" + }, + "i" = "Min/max time values: {min(epi_archive$DT$time_value)} / {max(epi_archive$DT$time_value)}", + "i" = "First/last version with update: {min(epi_archive$DT$version)} / {max(epi_archive$DT$version)}", + "i" = if (!is.na(epi_archive$clobberable_versions_start)) { + "Clobberable versions start: {epi_archive$clobberable_versions_start}" + }, + "i" = "Versions end: {epi_archive$versions_end}", + "i" = if (methods) "Public R6 methods: {names(epi_archive$public_methods)}", + "i" = "A preview of the table ({nrow(epi_archive$DT)} rows x {ncol(epi_archive$DT)} columns):" + ) + ) + + return(invisible(epi_archive$DT %>% print())) +} + + +#' @export +as_of <- function(x, ...) { + UseMethod("as_of") +} + + +#' As of epi_archive +#' @description Generates a snapshot in `epi_df` format as of a given version. +#' See the documentation for the wrapper function [`epix_as_of()`] for +#' details. The parameter descriptions below are copied from there +#' @param epi_archive An `epi_archive` object +#' @param max_version Version specifying the max version to permit in the +#' snapshot. That is, the snapshot will comprise the unique rows of the +#' current archive data that represent the most up-to-date signal values, as +#' of the specified `max_version` (and whose `time_value`s are at least +#' `min_time_value`). +#' @param min_time_value Time value specifying the min `time_value` to permit in +#' the snapshot. Default is `-Inf`, which effectively means that there is no +#' minimum considered. +#' @param all_versions Boolean; If `all_versions = TRUE`, then the output will be in +#' `epi_archive` format, and contain rows in the specified `time_value` range +#' having `version <= max_version`. The resulting object will cover a +#' potentially narrower `version` and `time_value` range than `x`, depending +#' on user-provided arguments. Otherwise, there will be one row in the output +#' for the `max_version` of each `time_value`. Default is `FALSE`. +#' @importFrom data.table between key +#' @export +as_of.epi_archive2 <- function(epi_archive, max_version, min_time_value = -Inf, all_versions = FALSE) { + other_keys <- setdiff( + key(epi_archive$DT), + c("geo_value", "time_value", "version") + ) + if (length(other_keys) == 0) other_keys <- NULL + + # Check a few things on max_version + if (!test_set_equal(class(max_version), class(epi_archive$DT$version))) { + cli_abort( + "`max_version` must have the same classes as `epi_archive$DT$version`." + ) + } + if (!test_set_equal(typeof(max_version), typeof(epi_archive$DT$version))) { + cli_abort( + "`max_version` must have the same types as `epi_archive$DT$version`." + ) + } + assert_scalar(max_version, na.ok = FALSE) + if (max_version > epi_archive$versions_end) { + cli_abort("`max_version` must be at most `epi_archive$versions_end`.") + } + assert_logical(all_versions, len = 1) + if (!is.na(epi_archive$clobberable_versions_start) && max_version >= epi_archive$clobberable_versions_start) { + cli_warn( + 'Getting data as of some recent version which could still be + overwritten (under routine circumstances) without assigning a new + version number (a.k.a. "clobbered"). Thus, the snapshot that we + produce here should not be expected to be reproducible later. See + `?epi_archive` for more info and `?epix_as_of` on how to muffle.', + class = "epiprocess__snapshot_as_of_clobberable_version" + ) + } + + # Filter by version and return + if (all_versions) { + # epi_archive is copied into result, so we can modify result directly + result <- epix_truncate_versions_after(epi_archive, max_version) + result$DT <- result$DT[time_value >= min_time_value, ] + return(result) + } + + # Make sure to use data.table ways of filtering and selecting + as_of_epi_df <- epi_archive$DT[time_value >= min_time_value & version <= max_version, ] %>% + unique( + by = c("geo_value", "time_value", other_keys), + fromLast = TRUE + ) %>% + tibble::as_tibble() %>% + dplyr::select(-"version") %>% + as_epi_df( + geo_type = epi_archive$geo_type, + time_type = epi_archive$time_type, + as_of = max_version, + additional_metadata = c(epi_archive$additional_metadata, + other_keys = other_keys + ) + ) + + return(as_of_epi_df) +} + + +#' @export +fill_through_version <- function(x, ...) { + UseMethod("fill_through_version") +} + + +#' Fill through version +#' @description Fill in unobserved history using requested scheme by mutating +#' the given object and potentially reseating its fields. See +#' [`epix_fill_through_version`], which doesn't mutate the input archive but +#' might alias its fields. +#' +#' @param epi_archive an `epi_archive` object +#' @param fill_versions_end as in [`epix_fill_through_version`] +#' @param how as in [`epix_fill_through_version`] +#' +#' @importFrom data.table key setkeyv := address copy +#' @importFrom rlang arg_match +fill_through_version.epi_archive2 <- function( + epi_archive, + fill_versions_end, + how = c("na", "locf")) { + validate_version_bound(fill_versions_end, epi_archive$DT, na_ok = FALSE) + how <- arg_match(how) + if (epi_archive$versions_end < fill_versions_end) { + new_DT <- switch(how, + "na" = { + # old DT + a version consisting of all NA observations + # immediately after the last currently/actually-observed + # version. Note that this NA-observation version must only be + # added if `epi_archive` is outdated. + nonversion_key_cols <- setdiff(key(epi_archive$DT), "version") + nonkey_cols <- setdiff(names(epi_archive$DT), key(epi_archive$DT)) + next_version_tag <- next_after(epi_archive$versions_end) + if (next_version_tag > fill_versions_end) { + cli_abort(sprintf(paste( + "Apparent problem with `next_after` method:", + "archive contained observations through version %s", + "and the next possible version was supposed to be %s,", + "but this appeared to jump from a version < %3$s", + "to one > %3$s, implying at least one version in between." + ), epi_archive$versions_end, next_version_tag, fill_versions_end)) + } + nonversion_key_vals_ever_recorded <- unique(epi_archive$DT, by = nonversion_key_cols) + # In edge cases, the `unique` result can alias the original + # DT; detect and copy if necessary: + if (identical(address(epi_archive$DT), address(nonversion_key_vals_ever_recorded))) { + nonversion_key_vals_ever_recorded <- copy(nonversion_key_vals_ever_recorded) + } + next_version_DT <- nonversion_key_vals_ever_recorded[ + , version := next_version_tag + ][ + # this makes the class of these columns logical (`NA` is a + # logical NA; we're relying on the rbind below to convert to + # the proper class&typeof) + , (nonkey_cols) := NA + ] + # full result DT: + setkeyv(rbind(epi_archive$DT, next_version_DT), key(epi_archive$DT))[] + }, + "locf" = { + # just the old DT; LOCF is built into other methods: + epi_archive$DT + } + ) + new_versions_end <- fill_versions_end + # Update `epi_archive` all at once with simple, error-free operations + + # return below: + epi_archive$DT <- new_DT + epi_archive$versions_end <- new_versions_end + } else { + # Already sufficiently up to date; nothing to do. + } + return(invisible(epi_archive)) +} + + +#' @export +truncate_versions_after <- function(x, ...) { + UseMethod("truncate_versions_after") +} + + +#' Truncate versions after +#' @description Filter to keep only older versions, mutating the archive by +#' potentially reseating but not mutating some fields. `DT` is likely, but not +#' guaranteed, to be copied. Returns the mutated archive +#' [invisibly][base::invisible]. +#' @param epi_archive as in [`epix_truncate_versions_after`] +#' @param max_version as in [`epix_truncate_versions_after`] +truncate_versions_after.epi_archive2 <- function( + epi_archive, + max_version) { + if (!test_set_equal(class(max_version), class(epi_archive$DT$version))) { + cli_abort("`max_version` must have the same classes as `epi_archive$DT$version`.") + } + if (!test_set_equal(typeof(max_version), typeof(epi_archive$DT$version))) { + cli_abort("`max_version` must have the same types as `epi_archive$DT$version`.") + } + assert_scalar(max_version, na.ok = FALSE) + if (max_version > epi_archive$versions_end) { + cli_abort("`max_version` must be at most `epi_archive$versions_end`.") + } + epi_archive$DT <- epi_archive$DT[epi_archive$DT$version <= max_version, colnames(epi_archive$DT), with = FALSE] + # (^ this filter operation seems to always copy the DT, even if it + # keeps every entry; we don't guarantee this behavior in + # documentation, though, so we could change to alias in this case) + if (!is.na(epi_archive$clobberable_versions_start) && epi_archive$clobberable_versions_start > max_version) { + epi_archive$clobberable_versions_start <- NA + } + epi_archive$versions_end <- max_version + return(invisible(epi_archive)) +} + + +#' Merge epi archive +#' @description Merges another `epi_archive` with the current one, mutating the +#' current one by reseating its `DT` and several other fields, but avoiding +#' mutation of the old `DT`; returns the current archive +#' [invisibly][base::invisible]. See [`epix_merge`] for a full description +#' of the non-R6-method version, which does not mutate either archive, and +#' does not alias either archive's `DT`.a +#' @param x as in [`epix_merge`] +#' @param y as in [`epix_merge`] +#' @param sync as in [`epix_merge`] +#' @param compactify as in [`epix_merge`] +merge_epi_archive2 <- function( + x, + y, + sync = c("forbid", "na", "locf", "truncate"), + compactify = TRUE) { + result <- epix_merge(x, y, + sync = sync, + compactify = compactify + ) + + # TODO: Use encapsulating methods instead. + if (length(x$private_fields) != 0L) { + cli_abort("expected no private fields in x", + internal = TRUE + ) + } + + # Mutate fields all at once, trying to avoid any potential errors: + for (field_name in names(x$public_fields)) { + x[[field_name]] <- result[[field_name]] + } + + return(invisible(x)) +} + + +#' `group_by` and related methods for `epi_archive`, `grouped_epi_archive` +#' +#' @param .data An `epi_archive` or `grouped_epi_archive` +#' @param ... Similar to [`dplyr::group_by`] (see "Details:" for edge cases); +#' * For `group_by`: unquoted variable name(s) or other +#' ["data masking"][dplyr::dplyr_data_masking] expression(s). It's possible to +#' use [`dplyr::mutate`]-like syntax here to calculate new columns on which to +#' perform grouping, but note that, if you are regrouping an already-grouped +#' `.data` object, the calculations will be carried out ignoring such grouping +#' (same as [in dplyr][dplyr::group_by]). +#' * For `ungroup`: either +#' * empty, in order to remove the grouping and output an `epi_archive`; or +#' * variable name(s) or other ["tidy-select"][dplyr::dplyr_tidy_select] +#' expression(s), in order to remove the matching variables from the list of +#' grouping variables, and output another `grouped_epi_archive`. +#' @param .add Boolean. If `FALSE`, the default, the output will be grouped by +#' the variable selection from `...` only; if `TRUE`, the output will be +#' grouped by the current grouping variables plus the variable selection from +#' `...`. +#' @param .drop As described in [`dplyr::group_by`]; determines treatment of +#' factor columns. +#' @param x For `groups` or `ungroup`: a `grouped_epi_archive`; for +#' `is_grouped_epi_archive`: any object +#' @param .tbl (For `group_by_drop_default`:) an `epi_archive` or +#' `grouped_epi_archive` (`epi_archive` dispatches to the S3 default method; +#' `grouped_epi_archive` dispatches its own S3 method) +#' +#' @details +#' +#' To match `dplyr`, `group_by` allows "data masking" (also referred to as +#' "tidy evaluation") expressions `...`, not just column names, in a way similar +#' to `mutate`. Note that replacing or removing key columns with these +#' expressions is disabled. +#' +#' `archive %>% group_by()` and other expressions that group or regroup by zero +#' columns (indicating that all rows should be treated as part of one large +#' group) will output a `grouped_epi_archive`, in order to enable the use of +#' `grouped_epi_archive` methods on the result. This is in slight contrast to +#' the same operations on tibbles and grouped tibbles, which will *not* output a +#' `grouped_df` in these circumstances. +#' +#' Using `group_by` with `.add=FALSE` to override the existing grouping is +#' disabled; instead, `ungroup` first then `group_by`. +#' +#' Mutation and aliasing: `group_by` tries to use a shallow copy of the `DT`, +#' introducing column-level aliasing between its input and its result. This +#' doesn't follow the general model for most `data.table` operations, which +#' seems to be that, given an nonaliased (i.e., unique) pointer to a +#' `data.table` object, its pointers to its columns should also be nonaliased. +#' If you mutate any of the columns of either the input or result, first ensure +#' that it is fine if columns of the other are also mutated, but do not rely on +#' such behavior to occur. Additionally, never perform mutation on the key +#' columns at all (except for strictly increasing transformations), as this will +#' invalidate sortedness assumptions about the rows. +#' +#' `group_by_drop_default` on (ungrouped) `epi_archive`s is expected to dispatch +#' to `group_by_drop_default.default` (but there is a dedicated method for +#' `grouped_epi_archive`s). +#' +#' @examples +#' +#' grouped_archive <- archive_cases_dv_subset %>% group_by(geo_value) +#' +#' # `print` for metadata and method listing: +#' grouped_archive %>% print() +#' +#' # The primary use for grouping is to perform a grouped `epix_slide`: +#' +#' archive_cases_dv_subset %>% +#' group_by(geo_value) %>% +#' epix_slide( +#' f = ~ mean(.x$case_rate_7d_av), +#' before = 2, +#' ref_time_values = as.Date("2020-06-11") + 0:2, +#' new_col_name = "case_rate_3d_av" +#' ) %>% +#' ungroup() +#' +#' # ----------------------------------------------------------------- +#' +#' # Advanced: some other features of dplyr grouping are implemented: +#' +#' library(dplyr) +#' toy_archive <- +#' tribble( +#' ~geo_value, ~age_group, ~time_value, ~version, ~value, +#' "us", "adult", "2000-01-01", "2000-01-02", 121, +#' "us", "pediatric", "2000-01-02", "2000-01-03", 5, # (addition) +#' "us", "adult", "2000-01-01", "2000-01-03", 125, # (revision) +#' "us", "adult", "2000-01-02", "2000-01-03", 130 # (addition) +#' ) %>% +#' mutate( +#' age_group = ordered(age_group, c("pediatric", "adult")), +#' time_value = as.Date(time_value), +#' version = as.Date(version) +#' ) %>% +#' as_epi_archive(other_keys = "age_group") +#' +#' # The following are equivalent: +#' toy_archive %>% group_by(geo_value, age_group) +#' toy_archive %>% +#' group_by(geo_value) %>% +#' group_by(age_group, .add = TRUE) +#' grouping_cols <- c("geo_value", "age_group") +#' toy_archive %>% group_by(across(all_of(grouping_cols))) +#' +#' # And these are equivalent: +#' toy_archive %>% group_by(geo_value) +#' toy_archive %>% +#' group_by(geo_value, age_group) %>% +#' ungroup(age_group) +#' +#' # To get the grouping variable names as a `list` of `name`s (a.k.a. symbols): +#' toy_archive %>% +#' group_by(geo_value) %>% +#' groups() +#' +#' toy_archive %>% +#' group_by(geo_value, age_group, .drop = FALSE) %>% +#' epix_slide(f = ~ sum(.x$value), before = 20) %>% +#' ungroup() +#' +#' @importFrom dplyr group_by +#' @export +#' +#' @aliases grouped_epi_archive +group_by.epi_archive2 <- function(epi_archive, ..., .add = FALSE, .drop = dplyr::group_by_drop_default(epi_archive)) { + # `add` makes no difference; this is an ungrouped `epi_archive`. + detailed_mutate <- epix_detailed_restricted_mutate2(epi_archive, ...) + assert_logical(.drop) + if (!.drop) { + grouping_cols <- as.list(detailed_mutate[["archive"]][["DT"]])[detailed_mutate[["request_names"]]] + grouping_col_is_factor <- purrr::map_lgl(grouping_cols, is.factor) + # ^ Use `as.list` to try to avoid any possibility of a deep copy. + if (!any(grouping_col_is_factor)) { + cli_warn( + "`.drop=FALSE` but there are no factor grouping columns; + did you mean to convert one of the columns to a factor beforehand?", + class = "epiprocess__group_by_epi_archive__drop_FALSE_no_factors" + ) + } else if (any(diff(grouping_col_is_factor) == -1L)) { + cli_warn( + "`.drop=FALSE` but there are one or more non-factor grouping columns listed + after a factor grouping column; this may produce groups with `NA`s for these + columns; see https://github.com/tidyverse/dplyr/issues/5369#issuecomment-683762553; + depending on how you want completion to work, you might instead want to convert all + grouping columns to factors beforehand, specify the non-factor grouping columns first, + or use `.drop=TRUE` and add a call to `tidyr::complete`.", + class = "epiprocess__group_by_epi_archive__drop_FALSE_nonfactor_after_factor" + ) + } + } + new_grouped_epi_archive(detailed_mutate[["archive"]], + detailed_mutate[["request_names"]], + drop = .drop + ) +} + + +#' @export +slide <- function(.data, ...) { + UseMethod("slide") +} + + +#' Slide over epi archive +#' @description Slides a given function over variables in an `epi_archive` +#' object. See the documentation for the wrapper function [`epix_slide()`] for +#' details. The parameter descriptions below are copied from there +#' @importFrom data.table key +#' @importFrom rlang !! !!! enquo quo_is_missing enquos is_quosure sym syms +#' @param f Function, formula, or missing; together with `...` specifies the +#' computation to slide. To "slide" means to apply a computation over a +#' sliding (a.k.a. "rolling") time window for each data group. The window is +#' determined by the `before` parameter described below. One time step is +#' typically one day or one week; see [`epi_slide`] details for more +#' explanation. If a function, `f` must take an `epi_df` with the same +#' column names as the archive's `DT`, minus the `version` column; followed +#' by a one-row tibble containing the values of the grouping variables for +#' the associated group; followed by a reference time value, usually as a +#' `Date` object; followed by any number of named arguments. If a formula, +#' `f` can operate directly on columns accessed via `.x$var` or `.$var`, as +#' in `~ mean (.x$var)` to compute a mean of a column `var` for each +#' group-`ref_time_value` combination. The group key can be accessed via +#' `.y` or `.group_key`, and the reference time value can be accessed via +#' `.z` or `.ref_time_value`. If `f` is missing, then `...` will specify the +#' computation. +#' @param ... Additional arguments to pass to the function or formula specified +#' via `f`. Alternatively, if `f` is missing, then `...` is interpreted as an +#' expression for tidy evaluation; in addition to referring to columns +#' directly by name, the expression has access to `.data` and `.env` pronouns +#' as in `dplyr` verbs, and can also refer to the `.group_key` and +#' `.ref_time_value`. See details of [`epi_slide`]. +#' @param before How far `before` each `ref_time_value` should the sliding +#' window extend? If provided, should be a single, non-NA, +#' [integer-compatible][vctrs::vec_cast] number of time steps. This window +#' endpoint is inclusive. For example, if `before = 7`, and one time step is +#' one day, then to produce a value for a `ref_time_value` of January 8, we +#' apply the given function or formula to data (for each group present) with +#' `time_value`s from January 1 onward, as they were reported on January 8. +#' For typical disease surveillance sources, this will not include any data +#' with a `time_value` of January 8, and, depending on the amount of reporting +#' latency, may not include January 7 or even earlier `time_value`s. (If +#' instead the archive were to hold nowcasts instead of regular surveillance +#' data, then we would indeed expect data for `time_value` January 8. If it +#' were to hold forecasts, then we would expect data for `time_value`s after +#' January 8, and the sliding window would extend as far after each +#' `ref_time_value` as needed to include all such `time_value`s.) +#' @param ref_time_values Reference time values / versions for sliding +#' computations; each element of this vector serves both as the anchor point +#' for the `time_value` window for the computation and the `max_version` +#' `as_of` which we fetch data in this window. If missing, then this will set +#' to a regularly-spaced sequence of values set to cover the range of +#' `version`s in the `DT` plus the `versions_end`; the spacing of values will +#' be guessed (using the GCD of the skips between values). +#' @param time_step Optional function used to define the meaning of one time +#' step, which if specified, overrides the default choice based on the +#' `time_value` column. This function must take a positive integer and return +#' an object of class `lubridate::period`. For example, we can use `time_step +#' = lubridate::hours` in order to set the time step to be one hour (this +#' would only be meaningful if `time_value` is of class `POSIXct`). +#' @param new_col_name String indicating the name of the new column that will +#' contain the derivative values. Default is "slide_value"; note that setting +#' `new_col_name` equal to an existing column name will overwrite this column. +#' @param as_list_col Should the slide results be held in a list column, or be +#' [unchopped][tidyr::unchop]/[unnested][tidyr::unnest]? Default is `FALSE`, +#' in which case a list object returned by `f` would be unnested (using +#' [`tidyr::unnest()`]), and, if the slide computations output data frames, +#' the names of the resulting columns are given by prepending `new_col_name` +#' to the names of the list elements. +#' @param names_sep String specifying the separator to use in `tidyr::unnest()` +#' when `as_list_col = FALSE`. Default is "_". Using `NULL` drops the prefix +#' from `new_col_name` entirely. +#' @param all_versions (Not the same as `all_rows` parameter of `epi_slide`.) If +#' `all_versions = TRUE`, then `f` will be passed the version history (all +#' `version <= ref_time_value`) for rows having `time_value` between +#' `ref_time_value - before` and `ref_time_value`. Otherwise, `f` will be +#' passed only the most recent `version` for every unique `time_value`. +#' Default is `FALSE`. +slide.epi_archive2 <- function(epi_archive, f, ..., before, ref_time_values, + time_step, new_col_name = "slide_value", + as_list_col = FALSE, names_sep = "_", + all_versions = FALSE) { + # For an "ungrouped" slide, treat all rows as belonging to one big + # group (group by 0 vars), like `dplyr::summarize`, and let the + # resulting `grouped_epi_archive` handle the slide: + slide( + group_by(epi_archive), + f, + ..., + before = before, ref_time_values = ref_time_values, + time_step = time_step, new_col_name = new_col_name, + as_list_col = as_list_col, names_sep = names_sep, + all_versions = all_versions + ) %>% + # We want a slide on ungrouped archives to output something + # ungrouped, rather than retaining the trivial (0-variable) + # grouping applied above. So we `ungroup()`. However, the current + # `dplyr` implementation automatically ignores/drops trivial + # groupings, so this is just a no-op for now. + ungroup() +} + + +#' Convert to `epi_archive` format +#' +#' Converts a data frame, data table, or tibble into an `epi_archive` +#' object. See the [archive +#' vignette](https://cmu-delphi.github.io/epiprocess/articles/archive.html) for +#' examples. The parameter descriptions below are copied from there +#' +#' @param x A data frame, data table, or tibble, with columns `geo_value`, +#' `time_value`, `version`, and then any additional number of columns. +#' @param geo_type Type for the geo values. If missing, then the function will +#' attempt to infer it from the geo values present; if this fails, then it +#' will be set to "custom". +#' @param time_type Type for the time values. If missing, then the function will +#' attempt to infer it from the time values present; if this fails, then it +#' will be set to "custom". +#' @param other_keys Character vector specifying the names of variables in `x` +#' that should be considered key variables (in the language of `data.table`) +#' apart from "geo_value", "time_value", and "version". +#' @param additional_metadata List of additional metadata to attach to the +#' `epi_archive` object. The metadata will have `geo_type` and `time_type` +#' fields; named entries from the passed list or will be included as well. +#' @param compactify Optional; Boolean or `NULL`: should we remove rows that are +#' considered redundant for the purposes of `epi_archive`'s built-in methods +#' such as `as_of`? As these methods use the last version of each observation +#' carried forward (LOCF) to interpolate between the version data provided, +#' rows that don't change these LOCF results can potentially be omitted to +#' save space. `TRUE` will remove these rows, `FALSE` will not, and missing or +#' `NULL` will remove these rows and issue a warning. Generally, this can be +#' set to `TRUE`, but if you directly inspect or edit the fields of the +#' `epi_archive` such as its `DT`, you will have to determine whether +#' `compactify=TRUE` will produce the desired results. If compactification +#' here is removing a large proportion of the rows, this may indicate a +#' potential for space, time, or bandwidth savings upstream the data pipeline, +#' e.g., when fetching, storing, or preparing the input data `x` +#' @param clobberable_versions_start Optional; `length`-1; either a value of the +#' same `class` and `typeof` as `x$version`, or an `NA` of any `class` and +#' `typeof`: specifically, either (a) the earliest version that could be +#' subject to "clobbering" (being overwritten with different update data, but +#' using the *same* version tag as the old update data), or (b) `NA`, to +#' indicate that no versions are clobberable. There are a variety of reasons +#' why versions could be clobberable under routine circumstances, such as (a) +#' today's version of one/all of the columns being published after initially +#' being filled with `NA` or LOCF, (b) a buggy version of today's data being +#' published but then fixed and republished later in the day, or (c) data +#' pipeline delays (e.g., publisher uploading, periodic scraping, database +#' syncing, periodic fetching, etc.) that make events (a) or (b) reflected +#' later in the day (or even on a different day) than expected; potential +#' causes vary between different data pipelines. The default value is `NA`, +#' which doesn't consider any versions to be clobberable. Another setting that +#' may be appropriate for some pipelines is `max_version_with_row_in(x)`. +#' @param versions_end Optional; length-1, same `class` and `typeof` as +#' `x$version`: what is the last version we have observed? The default is +#' `max_version_with_row_in(x)`, but values greater than this could also be +#' valid, and would indicate that we observed additional versions of the data +#' beyond `max(x$version)`, but they all contained empty updates. (The default +#' value of `clobberable_versions_start` does not fully trust these empty +#' updates, and assumes that any version `>= max(x$version)` could be +#' clobbered.) If `nrow(x) == 0`, then this argument is mandatory. +#' @return An `epi_archive` object. +#' +#' @details This simply a wrapper around the `new()` method of the `epi_archive` +#' class, so for example: +#' ``` +#' x <- as_epi_archive(df, geo_type = "state", time_type = "day") +#' ``` +#' would be equivalent to: +#' ``` +#' x <- epi_archive$new(df, geo_type = "state", time_type = "day") +#' ``` +#' +#' @export +#' @examples +#' # Simple ex. with necessary keys +#' tib <- tibble::tibble( +#' geo_value = rep(c("ca", "hi"), each = 5), +#' time_value = rep(seq(as.Date("2020-01-01"), +#' by = 1, length.out = 5 +#' ), times = 2), +#' version = rep(seq(as.Date("2020-01-02"), +#' by = 1, length.out = 5 +#' ), times = 2), +#' value = rnorm(10, mean = 2, sd = 1) +#' ) +#' +#' toy_epi_archive <- tib %>% as_epi_archive( +#' geo_type = "state", +#' time_type = "day" +#' ) +#' toy_epi_archive +#' +#' # Ex. with an additional key for county +#' df <- data.frame( +#' geo_value = c(replicate(2, "ca"), replicate(2, "fl")), +#' county = c(1, 3, 2, 5), +#' time_value = c( +#' "2020-06-01", +#' "2020-06-02", +#' "2020-06-01", +#' "2020-06-02" +#' ), +#' version = c( +#' "2020-06-02", +#' "2020-06-03", +#' "2020-06-02", +#' "2020-06-03" +#' ), +#' cases = c(1, 2, 3, 4), +#' cases_rate = c(0.01, 0.02, 0.01, 0.05) +#' ) +#' +#' x <- df %>% as_epi_archive( +#' geo_type = "state", +#' time_type = "day", +#' other_keys = "county" +#' ) +as_epi_archive2 <- function(x, geo_type, time_type, other_keys, + additional_metadata = list(), + compactify = NULL, + clobberable_versions_start = NA, + versions_end = max_version_with_row_in(x)) { + new_epi_archive2( + x, geo_type, time_type, other_keys, additional_metadata, + compactify, clobberable_versions_start, versions_end + ) +} + +#' Test for `epi_archive` format +#' +#' @param x An object. +#' @param grouped_okay Optional; Boolean; should a `grouped_epi_archive` also +#' count? Default is `FALSE`. +#' @return `TRUE` if the object inherits from `epi_archive`. +#' +#' @export +#' @examples +#' is_epi_archive(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) +#' is_epi_archive(archive_cases_dv_subset) # TRUE +#' +#' # By default, grouped_epi_archives don't count as epi_archives, as they may +#' # support a different set of operations from regular `epi_archives`. This +#' # behavior can be controlled by `grouped_okay`. +#' grouped_archive <- archive_cases_dv_subset$group_by(geo_value) +#' is_epi_archive(grouped_archive) # FALSE +#' is_epi_archive(grouped_archive, grouped_okay = TRUE) # TRUE +#' +#' @seealso [`is_grouped_epi_archive`] +is_epi_archive2 <- function(x, grouped_okay = FALSE) { + inherits(x, "epi_archive2") || grouped_okay && inherits(x, "grouped_epi_archive2") +} + + +#' @export +clone <- function(x, ...) { + UseMethod("clone") +} + + +#' @export +clone.epi_archive2 <- function(epi_archive, deep = FALSE) { + # TODO: Finish. + if (deep) { + epi_archive$DT <- copy(epi_archive$DT) + } else { + epi_archive$DT <- copy(epi_archive$DT) + } + return(epi_archive) +} diff --git a/R/grouped_archive_new.R b/R/grouped_archive_new.R new file mode 100644 index 000000000..c0e6c35e7 --- /dev/null +++ b/R/grouped_archive_new.R @@ -0,0 +1,456 @@ +#' +#' Convenience function for performing a `tidy_select` on dots according to its +#' docs, and taking the names (rather than the integer indices). +#' +#' @param ... tidyselect-syntax selection description +#' @param .data named vector / data frame; context for the description / the +#' object to which the selections apply +#' @return character vector containing names of entries/columns of +#' `names(.data)` denoting the selection +#' +#' @noRd +eval_pure_select_names_from_dots <- function(..., .data) { + # `?tidyselect::eval_select` tells us to use this form when we take in dots. + # It seems a bit peculiar, since the expr doesn't pack with it a way to get at + # the environment for the dots, but it looks like `eval_select` will assume + # the caller env (our `environment()`) when given an expr, and thus have + # access to the dots. + # + # If we were allowing renaming, we'd need to be careful about which names (new + # vs. old vs. both) to return here. + names(tidyselect::eval_select(rlang::expr(c(...)), .data, allow_rename = FALSE)) +} + +#' Get names of dots without forcing the dots +#' +#' For use in functions that use nonstandard evaluation (NSE) on the dots; we +#' can't use the pattern `names(list(...))` in this case because it will attempt +#' to force/(standard-)evaluate the dots, and we want to avoid attempted forcing of the +#' dots if we're using NSE. +#' +#' @noRd +nse_dots_names <- function(...) { + names(rlang::call_match()) +} +nse_dots_names2 <- function(...) { + rlang::names2(rlang::call_match()) +} + +#' @importFrom dplyr group_by_drop_default +#' @noRd +new_grouped_epi_archive <- function(ungrouped, vars, drop) { + if (inherits(ungrouped, "grouped_epi_archive")) { + cli_abort( + "`ungrouped` must not already be grouped (neither automatic regrouping + nor nested grouping is supported). Either use `group_by` with `.add=TRUE`, + or `ungroup` first.", + class = "epiprocess__grouped_epi_archive__ungrouped_arg_is_already_grouped", + epiprocess__ungrouped_class = class(ungrouped), + epiprocess__ungrouped_groups = groups(ungrouped) + ) + } + assert_class(ungrouped, "epi_archive2") + assert_character(vars) + if (!test_subset(vars, names(ungrouped$DT))) { + cli_abort( + "All grouping variables `vars` must be present in the data.", + ) + } + if ("version" %in% vars) { + cli_abort("`version` has a special interpretation and cannot be used by itself as a grouping variable") + } + assert_logical(drop, len = 1) + + # ----- + private <- list() + private$ungrouped <- ungrouped + private$vars <- vars + private$drop <- drop + + return(structure( + list( + private = private + ), + class = c("grouped_epi_archive2", "epi_archive2") + )) +} + +#' @export +print.grouped_epi_archive2 <- function(grouped_epi_archive, class = TRUE) { + if (class) cat("A `grouped_epi_archive` object:\n") + writeLines(wrap_varnames(grouped_epi_archive$private$vars, initial = "* Groups: ")) + # If none of the grouping vars is a factor, then $drop doesn't seem + # relevant, so try to be less verbose and don't message about it. + # + # Below map-then-extract may look weird, but the more natural + # extract-then-map appears to trigger copies of the extracted columns + # since we are working with a `data.table` (unless we go through + # `as.list`, but its current column-aliasing behavior is probably not + # something to rely too much on), while map functions currently appear + # to avoid column copies. + if (any(purrr::map_lgl(grouped_epi_archive$private$ungrouped$DT, is.factor)[grouped_epi_archive$private$vars])) { + cat(strwrap(init = "* ", prefix = " ", sprintf( + "%s groups formed by factor levels that don't appear in the data", + if (grouped_epi_archive$private$drop) "Drops" else "Does not drop" + ))) + cat("\n") + } + cat("It wraps an ungrouped `epi_archive`, with metadata:\n") + print(grouped_epi_archive$private$ungrouped, class = FALSE) + # Return self invisibly for convenience in `$`-"pipe": + invisible(grouped_epi_archive) +} + +#' @include methods-epi_archive.R +#' @rdname group_by.epi_archive +#' +#' @importFrom dplyr group_by +#' @export +group_by.grouped_epi_archive2 <- function( + grouped_epi_archive, + ..., + .add = FALSE, + .drop = dplyr::group_by_drop_default(grouped_epi_archive)) { + assert_logical(.add, len = 1) + if (!.add) { + cli_abort('`group_by` on a `grouped_epi_archive` with `.add=FALSE` is forbidden + (neither automatic regrouping nor nested grouping is supported). + If you want to "regroup", replacing the existing grouping vars, `ungroup` first and then `group_by`. + If you want to add to the existing grouping vars, call `group_by` specifying `.add=TRUE`. + ', + class = "epiprocess__grouped_epi_archive_group_by_with_add_FALSE" + ) + } else { + # `group_by` `...` computations are performed on ungrouped data (see + # `?dplyr::group_by`) + detailed_mutate <- epix_detailed_restricted_mutate2(grouped_epi_archive$private$ungrouped, ...) + out_ungrouped <- detailed_mutate[["archive"]] + vars_from_dots <- detailed_mutate[["request_names"]] + vars <- union(grouped_epi_archive$private$vars, vars_from_dots) + new_grouped_epi_archive(grouped_epi_archive$private$ungrouped, vars, .drop) + } +} + +#' @include methods-epi_archive.R +#' @rdname group_by.epi_archive +#' +#' @export +group_by_drop_default.grouped_epi_archive2 <- function(grouped_epi_archive) { + grouped_epi_archive$private$drop +} + +#' @include methods-epi_archive.R +#' @rdname group_by.epi_archive +#' +#' @importFrom dplyr groups +#' @export +groups.grouped_epi_archive2 <- function(grouped_epi_archive) { + rlang::syms(grouped_epi_archive$private$vars) +} + +#' @include methods-epi_archive.R +#' @rdname group_by.epi_archive +#' +#' @importFrom dplyr ungroup +#' @export +ungroup.grouped_epi_archive2 <- function(grouped_epi_archive, ...) { + if (rlang::dots_n(...) == 0L) { + # No dots = special behavior: remove all grouping vars and convert to + # an ungrouped class, as with `grouped_df`s. + grouped_epi_archive$private$ungrouped + } else { + exclude_vars <- eval_pure_select_names_from_dots(..., .data = grouped_epi_archive$private$ungrouped$DT) + # (requiring a pure selection here is a little stricter than dplyr + # implementations, but passing a renaming selection into `ungroup` + # seems pretty weird.) + result_vars <- grouped_epi_archive$private$vars[!grouped_epi_archive$private$vars %in% exclude_vars] + # `vars` might be length 0 if the user's tidyselection removed all + # grouping vars. Unlike with tibble, opt here to keep the result as a + # grouped_epi_archive, for output class consistency when `...` is + # provided. + new_grouped_epi_archive(grouped_epi_archive$private$ungrouped, result_vars, grouped_epi_archive$private$drop) + } +} + +#' Truncate versions after a given version, grouped +#' @description Filter to keep only older versions by mutating the underlying +#' `epi_archive` using `$truncate_versions_after`. Returns the mutated +#' `grouped_epi_archive` [invisibly][base::invisible]. +#' @param x as in [`epix_truncate_versions_after`] +#' @param max_version as in [`epix_truncate_versions_after`] +#' @export +truncate_versions_after.grouped_epi_archive2 <- function(grouped_epi_archive, max_version) { + # The grouping is irrelevant for this method; if we were to split into + # groups and recombine appropriately, we should get the same result as + # just leveraging the ungrouped method, so just do the latter: + truncate_versions_after(grouped_epi_archive$private$ungrouped, max_version) + return(invisible(grouped_epi_archive)) +} + +#' Truncate versions after a given version, grouped +#' @export +epix_truncate_versions_after.grouped_epi_archive2 <- function(grouped_epi_archive, max_version) { + cloned_group_epi_archive <- clone(grouped_epi_archive, deep = TRUE) + return((truncate_versions_after(cloned_group_epi_archive, max_version))) + # ^ second set of parens drops invisibility +} + + +#' Slide over grouped epi archive +#' @description Slides a given function over variables in a `grouped_epi_archive` +#' object. See the documentation for the wrapper function [`epix_slide()`] for +#' details. +#' @importFrom data.table key address rbindlist setDF +#' @importFrom tibble as_tibble new_tibble validate_tibble +#' @importFrom dplyr group_by groups +#' @importFrom rlang !! !!! enquo quo_is_missing enquos is_quosure sym syms +#' env missing_arg +#' @export +slide.grouped_epi_archive2 <- function(grouped_epi_archive, f, ..., before, ref_time_values, + time_step, new_col_name = "slide_value", + as_list_col = FALSE, names_sep = "_", + all_versions = FALSE) { + # Perform some deprecated argument checks without using ` = + # deprecated()` in the function signature, because they are from + # early development versions and much more likely to be clutter than + # informative in the signature. + if ("group_by" %in% nse_dots_names(...)) { + cli_abort(" + The `group_by` argument to `slide` has been removed; please use + the `group_by` S3 generic function or `$group_by` R6 method + before the slide instead. (If you were instead trying to pass a + `group_by` argument to `f` or create a column named `group_by`, + this check is a false positive, but you will still need to use a + different column name here and rename the resulting column after + the slide.) + ", class = "epiprocess__epix_slide_group_by_parameter_deprecated") + } + if ("all_rows" %in% nse_dots_names(...)) { + cli_abort(" + The `all_rows` argument has been removed from `epix_slide` (but + is still supported in `epi_slide`). Add rows for excluded + results with a manual join instead. + ", class = "epiprocess__epix_slide_all_rows_parameter_deprecated") + } + + if (missing(ref_time_values)) { + ref_time_values <- epix_slide_ref_time_values_default(grouped_epi_archive$private$ungrouped) + } else { + assert_numeric(ref_time_values, min.len = 1L, null.ok = FALSE, any.missing = FALSE) + if (any(ref_time_values > grouped_epi_archive$private$ungrouped$versions_end)) { + cli_abort("Some `ref_time_values` are greater than the latest version in the archive.") + } + if (anyDuplicated(ref_time_values) != 0L) { + cli_abort("Some `ref_time_values` are duplicated.") + } + # Sort, for consistency with `epi_slide`, although the current + # implementation doesn't take advantage of it. + ref_time_values <- sort(ref_time_values) + } + + # Validate and pre-process `before`: + if (missing(before)) { + cli_abort("`before` is required (and must be passed by name); + if you did not want to apply a sliding window but rather + to map `as_of` and `f` across various `ref_time_values`, + pass a large `before` value (e.g., if time steps are days, + `before=365000`).") + } + before <- vctrs::vec_cast(before, integer()) + assert_int(before, lower = 0L, null.ok = FALSE, na.ok = FALSE) + + # If a custom time step is specified, then redefine units + + if (!missing(time_step)) before <- time_step(before) + + # Symbolize column name + new_col <- sym(new_col_name) + + # Validate rest of parameters: + assert_logical(as_list_col, len = 1L) + assert_logical(all_versions, len = 1L) + assert_character(names_sep, len = 1L, null.ok = TRUE) + + # Computation for one group, one time value + comp_one_grp <- function(.data_group, .group_key, + f, ..., + ref_time_value, + new_col) { + # Carry out the specified computation + comp_value <- f(.data_group, .group_key, ref_time_value, ...) + + if (all_versions) { + # Extract data from archive so we can do length checks below. When + # `all_versions = TRUE`, `.data_group` will always be an ungrouped + # archive because of the preceding `as_of` step. + .data_group <- .data_group$DT + } + + assert( + check_atomic(comp_value, any.missing = TRUE), + check_data_frame(comp_value), + combine = "or", + .var.name = vname(comp_value) + ) + + # Label every result row with the `ref_time_value` + res <- list(time_value = ref_time_value) + + # Wrap the computation output in a list and unchop/unnest later if + # `as_list_col = FALSE`. This approach means that we will get a + # list-class col rather than a data.frame-class col when + # `as_list_col = TRUE` and the computations outputs are data + # frames. + res[[new_col]] <- list(comp_value) + + # Convert the list to a tibble all at once for speed. + return(validate_tibble(new_tibble(res))) + } + + # If `f` is missing, interpret ... as an expression for tidy evaluation + if (missing(f)) { + quos <- enquos(...) + if (length(quos) == 0) { + cli_abort("If `f` is missing then a computation must be specified via `...`.") + } + if (length(quos) > 1) { + cli_abort("If `f` is missing then only a single computation can be specified via `...`.") + } + + f <- quos[[1]] + new_col <- sym(names(rlang::quos_auto_name(quos))) + ... <- missing_arg() # magic value that passes zero args as dots in calls below + } + + f <- as_slide_computation(f, ...) + x <- lapply(ref_time_values, function(ref_time_value) { + # Ungrouped as-of data; `epi_df` if `all_versions` is `FALSE`, + # `epi_archive` if `all_versions` is `TRUE`: + as_of_raw <- as_of(grouped_epi_archive$private$ungrouped, + ref_time_value, + min_time_value = ref_time_value - before, + all_versions = all_versions + ) + + # Set: + # * `as_of_df`, the data.frame/tibble/epi_df/etc. that we will + # `group_modify` as the `.data` argument. Might or might not + # include version column. + # * `group_modify_fn`, the corresponding `.f` argument + if (!all_versions) { + as_of_df <- as_of_raw + group_modify_fn <- comp_one_grp + } else { + as_of_archive <- as_of_raw + # We essentially want to `group_modify` the archive, but + # haven't implemented this method yet. Next best would be + # `group_modify` on its `$DT`, but that has different + # behavior based on whether or not `dtplyr` is loaded. + # Instead, go through an ordinary data frame, trying to avoid + # copies. + if (address(as_of_archive$DT) == address(grouped_epi_archive$private$ungrouped$DT)) { + # `as_of` aliased its the full `$DT`; copy before mutating: + # + # Note: this step is probably unneeded; we're fine with + # aliasing of the DT or its columns: vanilla operations aren't + # going to mutate them in-place if they are aliases, and we're + # not performing mutation (unlike the situation with + # `fill_through_version` where we do mutate a `DT` and don't + # want aliasing). + as_of_archive$DT <- copy(as_of_archive$DT) + } + dt_key <- data.table::key(as_of_archive$DT) + as_of_df <- as_of_archive$DT + data.table::setDF(as_of_df) + + # Convert each subgroup chunk to an archive before running the calculation. + group_modify_fn <- function(.data_group, .group_key, + f, ..., + ref_time_value, + new_col) { + # .data_group is coming from as_of_df as a tibble, but we + # want to feed `comp_one_grp` an `epi_archive` backed by a + # DT; convert and wrap: + data.table::setattr(.data_group, "sorted", dt_key) + data.table::setDT(.data_group, key = dt_key) + .data_group_archive <- clone(as_of_archive) + .data_group_archive$DT <- .data_group + comp_one_grp(.data_group_archive, .group_key, + f = f, ..., + ref_time_value = ref_time_value, + new_col = new_col + ) + } + } + + return( + dplyr::group_modify( + dplyr::group_by(as_of_df, !!!syms(grouped_epi_archive$private$vars), .drop = grouped_epi_archive$private$drop), + group_modify_fn, + f = f, ..., + ref_time_value = ref_time_value, + new_col = new_col, + .keep = TRUE + ) + ) + }) + # Combine output into a single tibble + x <- as_tibble(setDF(rbindlist(x))) + # Reconstruct groups + x <- group_by(x, !!!syms(grouped_epi_archive$private$vars), .drop = grouped_epi_archive$private$drop) + + # Unchop/unnest if we need to + if (!as_list_col) { + x <- tidyr::unnest(x, !!new_col, names_sep = names_sep) + } + + # if (is_epi_df(x)) { + # # The analogue of `epi_df`'s `as_of` metadata for an archive is + # # `$versions_end`, at least in the current absence of + # # separate fields/columns denoting the "archive version" with a + # # different resolution, or from the perspective of a different + # # stage of a data pipeline. The `as_of` that is automatically + # # derived won't always match; override: + # attr(x, "metadata")[["as_of"]] <- private$ungrouped$versions_end + # } + + # XXX We need to work out when we want to return an `epi_df` and how + # to get appropriate keys (see #290, #223, #163). We'll probably + # need the commented-out code above if we ever output an `epi_df`. + # However, as a stopgap measure to have some more consistency across + # different ways of calling `epix_slide`, and to prevent `epi_df` + # output with invalid metadata, always output a (grouped or + # ungrouped) tibble. + x <- decay_epi_df(x) + + return(x) +} + + +# At time of writing, roxygen parses content in collation order, impacting the +# presentation of .Rd files that document multiple functions (see +# https://github.com/r-lib/roxygen2/pull/324). Use @include tags (determining +# `Collate:`) and ordering of functions within each file in order to get the +# desired ordering. + + + +#' @include methods-epi_archive.R +#' @rdname group_by.epi_archive +#' +#' @export +is_grouped_epi_archive2 <- function(x) { + inherits(x, "grouped_epi_archive2") +} + + +#' @export +clone.grouped_epi_archive2 <- function(x, deep = FALSE) { + # TODO: Finish. + if (deep) { + ungrouped <- clone(x$private$ungrouped, deep = TRUE) + } else { + ungrouped <- x$private$ungrouped + } + new_grouped_epi_archive(ungrouped, x$private$vars, x$private$drop) +} diff --git a/R/methods-epi_archive_new.R b/R/methods-epi_archive_new.R new file mode 100644 index 000000000..3af3056f1 --- /dev/null +++ b/R/methods-epi_archive_new.R @@ -0,0 +1,830 @@ +#' Generate a snapshot from an `epi_archive` object +#' +#' Generates a snapshot in `epi_df` format from an `epi_archive` object, as of a +#' given version. See the [archive +#' vignette](https://cmu-delphi.github.io/epiprocess/articles/archive.html) for +#' examples. +#' +#' @param x An `epi_archive` object +#' @param max_version Time value specifying the max version to permit in the +#' snapshot. That is, the snapshot will comprise the unique rows of the +#' current archive data that represent the most up-to-date signal values, as +#' of the specified `max_version` (and whose time values are at least +#' `min_time_value`.) +#' @param min_time_value Time value specifying the min time value to permit in +#' the snapshot. Default is `-Inf`, which effectively means that there is no +#' minimum considered. +#' @param all_versions If `all_versions = TRUE`, then the output will be in +#' `epi_archive` format, and contain rows in the specified `time_value` range +#' having `version <= max_version`. The resulting object will cover a +#' potentially narrower `version` and `time_value` range than `x`, depending +#' on user-provided arguments. Otherwise, there will be one row in the output +#' for the `max_version` of each `time_value`. Default is `FALSE`. +#' @return An `epi_df` object. +#' +#' @details This is simply a wrapper around the `as_of()` method of the +#' `epi_archive` class, so if `x` is an `epi_archive` object, then: +#' ``` +#' epix_as_of(x, max_version = v) +#' ``` +#' is equivalent to: +#' ``` +#' x$as_of(max_version = v) +#' ``` +#' +#' Mutation and aliasing: `epix_as_of` and `$as_of` will not mutate the input +#' archives, but may in some edge cases alias parts of the inputs, so copy the +#' outputs if needed before using mutating operations like `data.table`'s `:=` +#' operator. Currently, the only situation where there is potentially aliasing +#' is of the `DT` in edge cases with `all_versions = TRUE`, but this may change +#' in the future. +#' +#' @examples +#' # warning message of data latency shown +#' epix_as_of2( +#' x = archive_cases_dv_subset, +#' max_version = max(archive_cases_dv_subset$DT$version) +#' ) +#' +#' @examples +#' +#' range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 +#' +#' epix_as_of2( +#' x = archive_cases_dv_subset, +#' max_version = as.Date("2020-06-12") +#' ) +#' +#' # When fetching a snapshot as of the latest version with update data in the +#' # archive, a warning is issued by default, as this update data might not yet +#' # be finalized (for example, if data versions are labeled with dates, these +#' # versions might be overwritten throughout the corresponding days with +#' # additional data or "hotfixes" of erroroneous data; when we build an archive +#' # based on database queries, the latest available update might still be +#' # subject to change, but previous versions should be finalized). We can +#' # muffle such warnings with the following pattern: +#' withCallingHandlers( +#' { +#' epix_as_of2( +#' x = archive_cases_dv_subset, +#' max_version = max(archive_cases_dv_subset$DT$version) +#' ) +#' }, +#' epiprocess__snapshot_as_of_clobberable_version = function(wrn) invokeRestart("muffleWarning") +#' ) +#' # Since R 4.0, there is a `globalCallingHandlers` function that can be used +#' # to globally toggle these warnings. +#' +#' @export +epix_as_of2 <- function(epi_archive, max_version, min_time_value = -Inf, all_versions = FALSE) { + assert_class(epi_archive, "epi_archive2") + return(as_of(epi_archive, max_version, min_time_value, all_versions = all_versions)) +} + +#' `epi_archive` with unobserved history filled in (won't mutate, might alias) +#' +#' Sometimes, due to upstream data pipeline issues, we have to work with a +#' version history that isn't completely up to date, but with functions that +#' expect archives that are completely up to date, or equally as up-to-date as +#' another archive. This function provides one way to approach such mismatches: +#' pretend that we've "observed" additional versions, filling in these versions +#' with NAs or extrapolated values. +#' +#' '`epix_fill_through_version` will not mutate its `x` argument, but its result +#' might alias fields of `x` (e.g., mutating the result's `DT` might mutate +#' `x$DT`). The R6 method variant, `x$fill_through_version`, will mutate `x` to +#' give the result, but might reseat its fields (e.g., references to the old +#' `x$DT` might not be updated by this function or subsequent operations on +#' `x`), and returns the updated `x` [invisibly][base::invisible]. +#' +#' @param x An `epi_archive` +#' @param fill_versions_end Length-1, same class&type as `x$version`: the +#' version through which to fill in missing version history; this will be the +#' result's `$versions_end` unless it already had a later +#' `$versions_end`. +#' @param how Optional; `"na"` or `"locf"`: `"na"` will fill in any missing +#' required version history with `NA`s, by inserting (if necessary) an update +#' immediately after the current `$versions_end` that revises all +#' existing measurements to be `NA` (this is only supported for `version` +#' classes with a `next_after` implementation); `"locf"` will fill in missing +#' version history with the last version of each observation carried forward +#' (LOCF), by leaving the update `$DT` alone (other `epi_archive` methods are +#' based on LOCF). Default is `"na"`. +#' @return An `epi_archive` +epix_fill_through_version2 <- function(epi_archive, fill_versions_end, + how = c("na", "locf")) { + assert_class(epi_archive, "epi_archive2") + cloned_epi_archive <- clone(epi_archive) + # Enclosing parentheses drop the invisibility flag. See description above of + # potential mutation and aliasing behavior. + (fill_through_version(cloned_epi_archive, fill_versions_end, how = how)) +} + +#' Merge two `epi_archive` objects +#' +#' Merges two `epi_archive`s that share a common `geo_value`, `time_value`, and +#' set of key columns. When they also share a common `versions_end`, +#' using `$as_of` on the result should be the same as using `$as_of` on `x` and +#' `y` individually, then performing a full join of the `DT`s on the non-version +#' key columns (potentially consolidating multiple warnings about clobberable +#' versions). If the `versions_end` values differ, the +#' `sync` parameter controls what is done. +#' +#' This function, [`epix_merge`], does not mutate its inputs and will not alias +#' either archive's `DT`, but may alias other fields; `x$merge` will overwrite +#' `x` with the result of the merge, reseating its `DT` and several other fields +#' (making them point to different objects), but avoiding mutation of the +#' contents of the old `DT` (only relevant if you have another reference to the +#' old `DT` in another object). +#' +#' @param x,y Two `epi_archive` objects to join together. +#' @param sync Optional; `"forbid"`, `"na"`, `"locf"`, or `"truncate"`; in the +#' case that `x$versions_end` doesn't match `y$versions_end`, what do we do?: +#' `"forbid"`: emit an error; "na": use `max(x$versions_end, y$versions_end)` +#' as the result's `versions_end`, but ensure that, if we request a snapshot +#' as of a version after `min(x$versions_end, y$versions_end)`, the +#' observation columns from the less up-to-date archive will be all NAs (i.e., +#' imagine there was an update immediately after its `versions_end` which +#' revised all observations to be `NA`); `"locf"`: use `max(x$versions_end, +#' y$versions_end)` as the result's `versions_end`, allowing the last version +#' of each observation to be carried forward to extrapolate unavailable +#' versions for the less up-to-date input archive (i.e., imagining that in the +#' less up-to-date archive's data set remained unchanged between its actual +#' `versions_end` and the other archive's `versions_end`); or `"truncate"`: +#' use `min(x$versions_end, y$versions_end)` as the result's `versions_end`, +#' and discard any rows containing update rows for later versions. +#' @param compactify Optional; `TRUE`, `FALSE`, or `NULL`; should the result be +#' compactified? See [`as_epi_archive`] for an explanation of what this means. +#' Default here is `TRUE`. +#' @return the resulting `epi_archive` +#' +#' @details In all cases, `additional_metadata` will be an empty list, and +#' `clobberable_versions_start` will be set to the earliest version that could +#' be clobbered in either input archive. +#' +#' @examples +#' # create two example epi_archive datasets +#' x <- archive_cases_dv_subset$DT %>% +#' dplyr::select(geo_value, time_value, version, case_rate_7d_av) %>% +#' as_epi_archive(compactify = TRUE) +#' y <- archive_cases_dv_subset$DT %>% +#' dplyr::select(geo_value, time_value, version, percent_cli) %>% +#' as_epi_archive(compactify = TRUE) +#' # merge results stored in a third object: +#' xy <- epix_merge(x, y) +#' # vs. mutating x to hold the merge result: +#' x$merge(y) +#' +#' @importFrom data.table key set setkeyv +#' @export +epix_merge2 <- function(x, y, + sync = c("forbid", "na", "locf", "truncate"), + compactify = TRUE) { + assert_class(x, "epi_archive2") + assert_class(y, "epi_archive2") + sync <- rlang::arg_match(sync) + + if (!identical(x$geo_type, y$geo_type)) { + cli_abort("`x` and `y` must have the same `$geo_type`") + } + + if (!identical(x$time_type, y$time_type)) { + cli_abort("`x` and `y` must have the same `$time_type`") + } + + if (length(x$additional_metadata) != 0L) { + cli_warn("x$additional_metadata won't appear in merge result", + class = "epiprocess__epix_merge_ignores_additional_metadata" + ) + } + if (length(y$additional_metadata) != 0L) { + cli_warn("y$additional_metadata won't appear in merge result", + class = "epiprocess__epix_merge_ignores_additional_metadata" + ) + } + result_additional_metadata <- list() + + result_clobberable_versions_start <- + if (all(is.na(c(x$clobberable_versions_start, y$clobberable_versions_start)))) { + NA # (any type of NA is fine here) + } else { + Min(c(x$clobberable_versions_start, y$clobberable_versions_start)) + } + + # The actual merge below may not succeed 100% of the time, so do this + # preprocessing using non-mutating (but potentially aliasing) functions. This + # approach potentially uses more memory, but won't leave behind a + # partially-mutated `x` on failure. + if (sync == "forbid") { + if (!identical(x$versions_end, y$versions_end)) { + cli_abort(paste( + "`x` and `y` were not equally up to date version-wise:", + "`x$versions_end` was not identical to `y$versions_end`;", + "either ensure that `x` and `y` are equally up to date before merging,", + "or specify how to deal with this using `sync`" + ), class = "epiprocess__epix_merge_unresolved_sync") + } else { + new_versions_end <- x$versions_end + x_DT <- x$DT + y_DT <- y$DT + } + } else if (sync %in% c("na", "locf")) { + new_versions_end <- max(x$versions_end, y$versions_end) + x_DT <- epix_fill_through_version2(x, new_versions_end, sync)$DT + y_DT <- epix_fill_through_version2(y, new_versions_end, sync)$DT + } else if (sync == "truncate") { + new_versions_end <- min(x$versions_end, y$versions_end) + x_DT <- x$DT[x[["DT"]][["version"]] <= new_versions_end, names(x$DT), with = FALSE] + y_DT <- y$DT[y[["DT"]][["version"]] <= new_versions_end, names(y$DT), with = FALSE] + } else { + cli_abort("unimplemented") + } + + # key(x_DT) should be the same as key(x$DT) and key(y_DT) should be the same + # as key(y$DT). Below, we only use {x,y}_DT in the code (making it easier to + # split the code into separate functions if we wish), but still refer to + # {x,y}$DT in the error messages (further relying on this assumption). + # + # Check&ensure that the above assumption; if it didn't already hold, we likely + # have a bug in the preprocessing, a weird/invalid archive as input, and/or a + # data.table version with different semantics (which may break other parts of + # our code). + x_DT_key_as_expected <- identical(key(x$DT), key(x_DT)) + y_DT_key_as_expected <- identical(key(y$DT), key(y_DT)) + if (!x_DT_key_as_expected || !y_DT_key_as_expected) { + cli_warn(" + `epiprocess` internal warning (please report): pre-processing for + epix_merge unexpectedly resulted in an intermediate data table (or + tables) with a different key than the corresponding input archive. + Manually setting intermediate data table keys to the expected values. + ", internal = TRUE) + setkeyv(x_DT, key(x$DT)) + setkeyv(y_DT, key(y$DT)) + } + # Without some sort of annotations of what various columns represent, we can't + # do something that makes sense when merging archives with mismatched keys. + # E.g., even if we assume extra keys represent demographic breakdowns, a + # sensible default treatment of count-type and rate-type value columns would + # differ. + if (!identical(sort(key(x_DT)), sort(key(y_DT)))) { + cli_abort(" + The archives must have the same set of key column names; if the + key columns represent the same things, just with different + names, please retry after manually renaming to match; if they + represent different things (e.g., x has an age breakdown + but y does not), please retry after processing them to share + the same key (e.g., by summarizing x to remove the age breakdown, + or by applying a static age breakdown to y). + ", class = "epiprocess__epix_merge_x_y_must_have_same_key_set") + } + # `by` cols = result (and each input's) `key` cols, and determine + # the row set, determined using a full join via `merge` + # + # non-`by` cols = "value"-ish cols, and are looked up with last + # version carried forward via rolling joins + by <- key(x_DT) # = some perm of key(y_DT) + if (!all(c("geo_value", "time_value", "version") %in% key(x_DT))) { + cli_abort('Invalid `by`; `by` is currently set to the common `key` of + the two archives, and is expected to contain + "geo_value", "time_value", and "version".', + class = "epiprocess__epi_archive_must_have_required_key_cols" + ) + } + if (length(by) < 1L || utils::tail(by, 1L) != "version") { + cli_abort('Invalid `by`; `by` is currently set to the common `key` of + the two archives, and is expected to have a "version" as + the last key col.', + class = "epiprocess__epi_archive_must_have_version_at_end_of_key" + ) + } + x_nonby_colnames <- setdiff(names(x_DT), by) + y_nonby_colnames <- setdiff(names(y_DT), by) + if (length(intersect(x_nonby_colnames, y_nonby_colnames)) != 0L) { + cli_abort(" + `x` and `y` DTs have overlapping non-by column names; + this is currently not supported; please manually fix up first: + any overlapping columns that can are key-like should be + incorporated into the key, and other columns should be renamed. + ", class = "epiprocess__epix_merge_x_y_must_not_have_overlapping_nonby_colnames") + } + x_by_vals <- x_DT[, by, with = FALSE] + if (anyDuplicated(x_by_vals) != 0L) { + cli_abort(" + The `by` columns must uniquely determine rows of `x$DT`; + the `by` is currently set to the common `key` of the two + archives, so this can be resolved by adding key-like columns + to `x`'s key (to get a unique key). + ", class = "epiprocess__epix_merge_by_cols_must_act_as_unique_key") + } + y_by_vals <- y_DT[, by, with = FALSE] + if (anyDuplicated(y_by_vals) != 0L) { + cli_abort(" + The `by` columns must uniquely determine rows of `y$DT`; + the `by` is currently set to the common `key` of the two + archives, so this can be resolved by adding key-like columns + to `y`'s key (to get a unique key). + ", class = "epiprocess__epix_merge_by_cols_must_act_as_unique_key") + } + result_DT <- merge(x_by_vals, y_by_vals, + by = by, + # We must have `all=TRUE` or we may skip updates + # from x and/or y and corrupt the history + all = TRUE, + # We don't want Cartesian products, but the + # by-is-unique-key check above already ensures + # this. (Note that `allow.cartesian=FALSE` doesn't + # actually catch all Cartesian products anyway.) + # Disable superfluous check: + allow.cartesian = TRUE + ) + set( + result_DT, , x_nonby_colnames, + x_DT[result_DT[, by, with = FALSE], x_nonby_colnames, + with = FALSE, + # It's good practice to specify `on`, and we must + # explicitly specify `on` if there's a potential key vs. + # by order mismatch (not possible currently for x + # with by = key(x$DT), but possible for y): + on = by, + # last version carried forward: + roll = TRUE, + # requesting non-version key that doesn't exist in the other archive, + # or before its first version, should result in NA + nomatch = NA, + # see note on `allow.cartesian` above; currently have a + # similar story here. + allow.cartesian = TRUE + ] + ) + set( + result_DT, , y_nonby_colnames, + y_DT[result_DT[, by, with = FALSE], y_nonby_colnames, + with = FALSE, + on = by, + roll = TRUE, + nomatch = NA, + allow.cartesian = TRUE + ] + ) + # The key could be unset in case of a key vs. by order mismatch as + # noted above. Ensure that we keep it: + setkeyv(result_DT, by) + + return(as_epi_archive2( + result_DT[], # clear data.table internal invisibility flag if set + geo_type = x$geo_type, + time_type = x$time_type, + other_keys = setdiff(key(result_DT), c("geo_value", "time_value", "version")), + additional_metadata = result_additional_metadata, + # It'd probably be better to pre-compactify before the merge, and might be + # guaranteed not to be necessary to compactify the merge result if the + # inputs are already compactified, but at time of writing we don't have + # compactify in its own method or field, and it seems like it should be + # pretty fast anyway. + compactify = compactify, + clobberable_versions_start = result_clobberable_versions_start, + versions_end = new_versions_end + )) +} + +# Helpers for `group_by`: + +#' Make non-testing mock to get [`dplyr::dplyr_col_modify`] input +#' +#' A workaround for `dplyr:::mutate_cols` not being exported and directly +#' applying test mock libraries likely being impossible (due to mocking another +#' package's S3 generic or method). +#' +#' Use solely with a single call to the [`dplyr::mutate`] function and then +#' `destructure_col_modify_recorder_df`; other applicable operations from +#' [dplyr::dplyr_extending] have not been implemented. +#' +#' @param parent_df the "parent class" data frame to wrap +#' @return a `col_modify_recorder_df` +#' +#' @noRd +new_col_modify_recorder_df <- function(parent_df) { + assert_class(parent_df, "data.frame") + `class<-`(parent_df, c("col_modify_recorder_df", class(parent_df))) +} + +#' Extract unchanged parent-class data frame from a `new_col_modify_recorder_df` +#' +#' @param col_modify_recorder_df an instance of a `col_modify_recorder_df` +#' @return named list with elements `unchanged_parent_df`, `cols`; `cols` is the +#' input to [`dplyr::dplyr_col_modify`] that this class was designed to record +#' +#' @noRd +destructure_col_modify_recorder_df <- function(col_modify_recorder_df) { + assert_class(col_modify_recorder_df, "col_modify_recorder_df") + list( + unchanged_parent_df = col_modify_recorder_df %>% + `attr<-`("epiprocess::col_modify_recorder_df::cols", NULL) %>% + `class<-`(setdiff(class(.), "col_modify_recorder_df")), + cols = attr(col_modify_recorder_df, + "epiprocess::col_modify_recorder_df::cols", + exact = TRUE + ) + ) +} + +#' `dplyr_col_modify` method that simply records the `cols` argument +#' +#' Must export S3 methods in R >= 4.0, even if they're only designed to be +#' package internals, and must import any corresponding upstream S3 generic +#' functions: +#' @importFrom dplyr dplyr_col_modify +#' @export +#' @noRd +dplyr_col_modify.col_modify_recorder_df <- function(data, cols) { + if (!is.null(attr(data, "epiprocess::col_modify_recorder_df::cols", exact = TRUE))) { + cli_abort("`col_modify_recorder_df` can only record `cols` once", + internal = TRUE + ) + } + attr(data, "epiprocess::col_modify_recorder_df::cols") <- cols + data +} + +#' A more detailed but restricted `mutate` for use in `group_by.epi_archive` +#' +#' More detailed: provides the names of the "requested" columns in addition to +#' the output expected from a regular `mutate` method. +#' +#' Restricted: doesn't allow replacing or removing key cols, where a sort is +#' potentially required at best and what the output key should be is unclear at +#' worst. (The originally expected restriction was that the `mutate` parameters +#' not present in `group_by` would not be recognized, but the current +#' implementation just lets `mutate` handle these even anyway, even if they're +#' not part of the regular `group_by` parameters; these arguments would have to +#' be passed by names with dot prefixes, so just hope that the user means to use +#' them here if provided.) +#' +#' This can introduce column-level aliasing in `data.table`s, which isn't really +#' intended in the `data.table` user model but we can make it part of our user +#' model (see +#' https://stackoverflow.com/questions/45925482/make-a-shallow-copy-in-data-table +#' and links). +#' +#' Don't export this without cleaning up language of "mutate" as in side effects +#' vs. "mutate" as in `dplyr::mutate`. +#' @noRd +epix_detailed_restricted_mutate2 <- function(.data, ...) { + # We don't want to directly use `dplyr::mutate` on the `$DT`, as: + # - `mutate` behavior, including the output class, changes depending on + # whether `dtplyr` < 1.3.0 is loaded and would require post-processing + # - behavior with `dtplyr` isn't fully compatible + # - it doesn't give the desired details, and `rlang::exprs_auto_name` does not + # appropriately handle the `= NULL` and `= ` tidyeval cases + # Instead: + # - Use `as.list` to get a shallow copy (undocumented, but apparently + # intended, behavior), then `as_tibble` (also shallow, given a list) to get + # back to something that will use `dplyr`'s included `mutate` method(s), + # then convert this using shallow operations into a `data.table`. + # - Use `col_modify_recorder_df` to get the desired details. + in_tbl <- tibble::as_tibble(as.list(.data$DT), .name_repair = "minimal") + col_modify_cols <- + destructure_col_modify_recorder_df( + mutate(new_col_modify_recorder_df(in_tbl), ...) + )[["cols"]] + invalidated_key_col_is <- + which(purrr::map_lgl(key(.data$DT), function(key_colname) { + key_colname %in% names(col_modify_cols) && + !rlang::is_reference(in_tbl[[key_colname]], col_modify_cols[[key_colname]]) + })) + if (length(invalidated_key_col_is) != 0L) { + rlang::abort(paste_lines(c( + "Key columns must not be replaced or removed.", + wrap_varnames(key(.data$DT)[invalidated_key_col_is], + initial = "Flagged key cols: " + ) + ))) + } else { + # Have `dplyr` do the `dplyr_col_modify`, keeping the column-level-aliasing + # and must-copy-on-write-if-refcount-more-than-1 model, obtaining a tibble, + # then convert it into a `data.table`. The key should still be valid + # (assuming that the user did not explicitly alter `key(.data$DT)` or the + # columns by reference somehow within `...` tidyeval-style computations, or + # trigger refcount-1 alterations due to still having >1 refcounts on the + # columns), set the "sorted" attribute accordingly to prevent attempted + # sorting (including potential extra copies) or sortedness checking, then + # `setDT` (rather than `as.data.table`, in order to prevent column copying + # to establish ownership according to `data.table`'s memory model). + out_DT <- dplyr::dplyr_col_modify(in_tbl, col_modify_cols) %>% + data.table::setattr("sorted", data.table::key(.data$DT)) %>% + data.table::setDT(key = key(.data$DT)) + out_archive <- clone(.data) + out_archive$DT <- out_DT + request_names <- names(col_modify_cols) + return(list( + archive = out_archive, + request_names = request_names + )) + # (We might also consider special-casing when `mutate` hands back something + # equivalent (in some sense) to the input (probably only encountered when + # we're dealing with `group_by`), and using just `$DT`, not a shallow copy, + # in the result, primarily in order to hedge against `as.list` or `setDT` + # changing their behavior and generating deep copies somehow. This could + # also prevent storage, and perhaps also generation, of shallow copies, but + # this seems unlikely to be a major gain unless it helps enable some + # in-place modifications of refcount-1 columns (although detecting this case + # seems to be common across `group_by` implementations; maybe there is + # something there).) + } +} + + +#' Slide a function over variables in an `epi_archive` or `grouped_epi_archive` +#' +#' Slides a given function over variables in an `epi_archive` object. This +#' behaves similarly to `epi_slide()`, with the key exception that it is +#' version-aware: the sliding computation at any given reference time t is +#' performed on **data that would have been available as of t**. See the +#' [archive +#' vignette](https://cmu-delphi.github.io/epiprocess/articles/archive.html) for +#' examples. +#' +#' @param x An [`epi_archive`] or [`grouped_epi_archive`] object. If ungrouped, +#' all data in `x` will be treated as part of a single data group. +#' @param f Function, formula, or missing; together with `...` specifies the +#' computation to slide. To "slide" means to apply a computation over a +#' sliding (a.k.a. "rolling") time window for each data group. The window is +#' determined by the `before` parameter described below. One time step is +#' typically one day or one week; see [`epi_slide`] details for more +#' explanation. If a function, `f` must take an `epi_df` with the same +#' column names as the archive's `DT`, minus the `version` column; followed +#' by a one-row tibble containing the values of the grouping variables for +#' the associated group; followed by a reference time value, usually as a +#' `Date` object; followed by any number of named arguments. If a formula, +#' `f` can operate directly on columns accessed via `.x$var` or `.$var`, as +#' in `~ mean (.x$var)` to compute a mean of a column `var` for each +#' group-`ref_time_value` combination. The group key can be accessed via +#' `.y` or `.group_key`, and the reference time value can be accessed via +#' `.z` or `.ref_time_value`. If `f` is missing, then `...` will specify the +#' computation. +#' @param ... Additional arguments to pass to the function or formula specified +#' via `f`. Alternatively, if `f` is missing, then `...` is interpreted as an +#' expression for tidy evaluation; in addition to referring to columns +#' directly by name, the expression has access to `.data` and `.env` pronouns +#' as in `dplyr` verbs, and can also refer to the `.group_key` and +#' `.ref_time_value`. See details of [`epi_slide`]. +#' @param before How far `before` each `ref_time_value` should the sliding +#' window extend? If provided, should be a single, non-NA, +#' [integer-compatible][vctrs::vec_cast] number of time steps. This window +#' endpoint is inclusive. For example, if `before = 7`, and one time step is +#' one day, then to produce a value for a `ref_time_value` of January 8, we +#' apply the given function or formula to data (for each group present) with +#' `time_value`s from January 1 onward, as they were reported on January 8. +#' For typical disease surveillance sources, this will not include any data +#' with a `time_value` of January 8, and, depending on the amount of reporting +#' latency, may not include January 7 or even earlier `time_value`s. (If +#' instead the archive were to hold nowcasts instead of regular surveillance +#' data, then we would indeed expect data for `time_value` January 8. If it +#' were to hold forecasts, then we would expect data for `time_value`s after +#' January 8, and the sliding window would extend as far after each +#' `ref_time_value` as needed to include all such `time_value`s.) +#' @param ref_time_values Reference time values / versions for sliding +#' computations; each element of this vector serves both as the anchor point +#' for the `time_value` window for the computation and the `max_version` +#' `as_of` which we fetch data in this window. If missing, then this will set +#' to a regularly-spaced sequence of values set to cover the range of +#' `version`s in the `DT` plus the `versions_end`; the spacing of values will +#' be guessed (using the GCD of the skips between values). +#' @param time_step Optional function used to define the meaning of one time +#' step, which if specified, overrides the default choice based on the +#' `time_value` column. This function must take a positive integer and return +#' an object of class `lubridate::period`. For example, we can use `time_step +#' = lubridate::hours` in order to set the time step to be one hour (this +#' would only be meaningful if `time_value` is of class `POSIXct`). +#' @param new_col_name String indicating the name of the new column that will +#' contain the derivative values. Default is "slide_value"; note that setting +#' `new_col_name` equal to an existing column name will overwrite this column. +#' @param as_list_col Should the slide results be held in a list column, or be +#' [unchopped][tidyr::unchop]/[unnested][tidyr::unnest]? Default is `FALSE`, +#' in which case a list object returned by `f` would be unnested (using +#' [`tidyr::unnest()`]), and, if the slide computations output data frames, +#' the names of the resulting columns are given by prepending `new_col_name` +#' to the names of the list elements. +#' @param names_sep String specifying the separator to use in `tidyr::unnest()` +#' when `as_list_col = FALSE`. Default is "_". Using `NULL` drops the prefix +#' from `new_col_name` entirely. +#' @param all_versions (Not the same as `all_rows` parameter of `epi_slide`.) If +#' `all_versions = TRUE`, then `f` will be passed the version history (all +#' `version <= ref_time_value`) for rows having `time_value` between +#' `ref_time_value - before` and `ref_time_value`. Otherwise, `f` will be +#' passed only the most recent `version` for every unique `time_value`. +#' Default is `FALSE`. +#' @return A tibble whose columns are: the grouping variables, `time_value`, +#' containing the reference time values for the slide computation, and a +#' column named according to the `new_col_name` argument, containing the slide +#' values. +#' +#' @details A few key distinctions between the current function and `epi_slide()`: +#' 1. In `f` functions for `epix_slide`, one should not assume that the input +#' data to contain any rows with `time_value` matching the computation's +#' `ref_time_value` (accessible via `attributes()$metadata$as_of`); for +#' typical epidemiological surveillance data, observations pertaining to a +#' particular time period (`time_value`) are first reported `as_of` some +#' instant after that time period has ended. +#' 2. `epix_slide()` doesn't accept an `after` argument; its windows extend +#' from `before` time steps before a given `ref_time_value` through the last +#' `time_value` available as of version `ref_time_value` (typically, this +#' won't include `ref_time_value` itself, as observations about a particular +#' time interval (e.g., day) are only published after that time interval +#' ends); `epi_slide` windows extend from `before` time steps before a +#' `ref_time_value` through `after` time steps after `ref_time_value`. +#' 3. The input class and columns are similar but different: `epix_slide` +#' (with the default `all_versions=FALSE`) keeps all columns and the +#' `epi_df`-ness of the first argument to each computation; `epi_slide` only +#' provides the grouping variables in the second input, and will convert the +#' first input into a regular tibble if the grouping variables include the +#' essential `geo_value` column. (With `all_versions=TRUE`, `epix_slide` will +#' will provide an `epi_archive` rather than an `epi-df` to each +#' computation.) +#' 4. The output class and columns are similar but different: `epix_slide()` +#' returns a tibble containing only the grouping variables, `time_value`, and +#' the new column(s) from the slide computations, whereas `epi_slide()` +#' returns an `epi_df` with all original variables plus the new columns from +#' the slide computations. (Both will mirror the grouping or ungroupedness of +#' their input, with one exception: `epi_archive`s can have trivial +#' (zero-variable) groupings, but these will be dropped in `epix_slide` +#' results as they are not supported by tibbles.) +#' 5. There are no size stability checks or element/row recycling to maintain +#' size stability in `epix_slide`, unlike in `epi_slide`. (`epix_slide` is +#' roughly analogous to [`dplyr::group_modify`], while `epi_slide` is roughly +#' analogous to `dplyr::mutate` followed by `dplyr::arrange`) This is detailed +#' in the "advanced" vignette. +#' 6. `all_rows` is not supported in `epix_slide`; since the slide +#' computations are allowed more flexibility in their outputs than in +#' `epi_slide`, we can't guess a good representation for missing computations +#' for excluded group-`ref_time_value` pairs. +#' 7. The `ref_time_values` default for `epix_slide` is based on making an +#' evenly-spaced sequence out of the `version`s in the `DT` plus the +#' `versions_end`, rather than the `time_value`s. +#' +#' Apart from the above distinctions, the interfaces between `epix_slide()` and +#' `epi_slide()` are the same. +#' +#' Furthermore, the current function can be considerably slower than +#' `epi_slide()`, for two reasons: (1) it must repeatedly fetch +#' properly-versioned snapshots from the data archive (via its `as_of()` +#' method), and (2) it performs a "manual" sliding of sorts, and does not +#' benefit from the highly efficient `slider` package. For this reason, it +#' should never be used in place of `epi_slide()`, and only used when +#' version-aware sliding is necessary (as it its purpose). +#' +#' Finally, this is simply a wrapper around the `slide()` method of the +#' `epi_archive` and `grouped_epi_archive` classes, so if `x` is an +#' object of either of these classes, then: +#' ``` +#' epix_slide(x, new_var = comp(old_var), before = 119) +#' ``` +#' is equivalent to: +#' ``` +#' x$slide(new_var = comp(old_var), before = 119) +#' ``` +#' +#' Mutation and aliasing: `epix_slide` and `$slide` will not perform in-place +#' mutation of the input archives on their own. In some edge cases the inputs it +#' feeds to the slide computations may alias parts of the input archive, so copy +#' the slide computation inputs if needed before using mutating operations like +#' `data.table`'s `:=` operator. Similarly, in some edge cases, the output of +#' the slide operation may alias parts of the input archive, so similarly, make +#' sure to clone and/or copy appropriately before using in-place mutation. +#' +#' @examples +#' library(dplyr) +#' +#' # Reference time points for which we want to compute slide values: +#' ref_time_values <- seq(as.Date("2020-06-01"), +#' as.Date("2020-06-15"), +#' by = "1 day" +#' ) +#' +#' # A simple (but not very useful) example (see the archive vignette for a more +#' # realistic one): +#' archive_cases_dv_subset %>% +#' group_by(geo_value) %>% +#' epix_slide( +#' f = ~ mean(.x$case_rate_7d_av), +#' before = 2, +#' ref_time_values = ref_time_values, +#' new_col_name = "case_rate_7d_av_recent_av" +#' ) %>% +#' ungroup() +#' # We requested time windows that started 2 days before the corresponding time +#' # values. The actual number of `time_value`s in each computation depends on +#' # the reporting latency of the signal and `time_value` range covered by the +#' # archive (2020-06-01 -- 2021-11-30 in this example). In this case, we have +#' # * 0 `time_value`s, for ref time 2020-06-01 --> the result is automatically +#' # discarded +#' # * 1 `time_value`, for ref time 2020-06-02 +#' # * 2 `time_value`s, for the rest of the results +#' # * never the 3 `time_value`s we would get from `epi_slide`, since, because +#' # of data latency, we'll never have an observation +#' # `time_value == ref_time_value` as of `ref_time_value`. +#' # The example below shows this type of behavior in more detail. +#' +#' # Examining characteristics of the data passed to each computation with +#' # `all_versions=FALSE`. +#' archive_cases_dv_subset %>% +#' group_by(geo_value) %>% +#' epix_slide( +#' function(x, gk, rtv) { +#' tibble( +#' time_range = if (nrow(x) == 0L) { +#' "0 `time_value`s" +#' } else { +#' sprintf("%s -- %s", min(x$time_value), max(x$time_value)) +#' }, +#' n = nrow(x), +#' class1 = class(x)[[1L]] +#' ) +#' }, +#' before = 5, all_versions = FALSE, +#' ref_time_values = ref_time_values, names_sep = NULL +#' ) %>% +#' ungroup() %>% +#' arrange(geo_value, time_value) +#' +#' # --- Advanced: --- +#' +#' # `epix_slide` with `all_versions=FALSE` (the default) applies a +#' # version-unaware computation to several versions of the data. We can also +#' # use `all_versions=TRUE` to apply a version-*aware* computation to several +#' # versions of the data, again looking at characteristics of the data passed +#' # to each computation. In this case, each computation should expect an +#' # `epi_archive` containing the relevant version data: +#' +#' archive_cases_dv_subset %>% +#' group_by(geo_value) %>% +#' epix_slide( +#' function(x, gk, rtv) { +#' tibble( +#' versions_start = if (nrow(x$DT) == 0L) { +#' "NA (0 rows)" +#' } else { +#' toString(min(x$DT$version)) +#' }, +#' versions_end = x$versions_end, +#' time_range = if (nrow(x$DT) == 0L) { +#' "0 `time_value`s" +#' } else { +#' sprintf("%s -- %s", min(x$DT$time_value), max(x$DT$time_value)) +#' }, +#' n = nrow(x$DT), +#' class1 = class(x)[[1L]] +#' ) +#' }, +#' before = 5, all_versions = TRUE, +#' ref_time_values = ref_time_values, names_sep = NULL +#' ) %>% +#' ungroup() %>% +#' # Focus on one geo_value so we can better see the columns above: +#' filter(geo_value == "ca") %>% +#' select(-geo_value) +#' +#' @importFrom rlang enquo !!! +#' @export +epix_slide2 <- function(x, f, ..., before, ref_time_values, + time_step, new_col_name = "slide_value", + as_list_col = FALSE, names_sep = "_", + all_versions = FALSE) { + if (!is_epi_archive2(x, grouped_okay = TRUE)) { + cli_abort("`x` must be of class `epi_archive` or `grouped_epi_archive`.") + } + return(slide(x, f, ..., + before = before, + ref_time_values = ref_time_values, + time_step = time_step, + new_col_name = new_col_name, + as_list_col = as_list_col, + names_sep = names_sep, + all_versions = all_versions + )) +} + + +#' Filter an `epi_archive` object to keep only older versions +#' +#' Generates a filtered `epi_archive` from an `epi_archive` object, keeping +#' only rows with `version` falling on or before a specified date. +#' +#' @param x An `epi_archive` object +#' @param max_version Time value specifying the max version to permit in the +#' filtered archive. That is, the output archive will comprise rows of the +#' current archive data having `version` less than or equal to the +#' specified `max_version` +#' @return An `epi_archive` object +#' +#' @export +epix_truncate_versions_after <- function(x, max_version) { + UseMethod("epix_truncate_versions_after") +} + +#' @export +epix_truncate_versions_after.epi_archive2 <- function(x, max_version) { + cloned_epi_archive <- clone(x) + return((truncate_versions_after(x, max_version))) + # ^ second set of parens drops invisibility +} diff --git a/man/as_epi_archive2.Rd b/man/as_epi_archive2.Rd new file mode 100644 index 000000000..090b455ab --- /dev/null +++ b/man/as_epi_archive2.Rd @@ -0,0 +1,142 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{as_epi_archive2} +\alias{as_epi_archive2} +\title{Convert to \code{epi_archive} format} +\usage{ +as_epi_archive2( + x, + geo_type, + time_type, + other_keys, + additional_metadata = list(), + compactify = NULL, + clobberable_versions_start = NA, + versions_end = max_version_with_row_in(x) +) +} +\arguments{ +\item{x}{A data frame, data table, or tibble, with columns \code{geo_value}, +\code{time_value}, \code{version}, and then any additional number of columns.} + +\item{geo_type}{Type for the geo values. If missing, then the function will +attempt to infer it from the geo values present; if this fails, then it +will be set to "custom".} + +\item{time_type}{Type for the time values. If missing, then the function will +attempt to infer it from the time values present; if this fails, then it +will be set to "custom".} + +\item{other_keys}{Character vector specifying the names of variables in \code{x} +that should be considered key variables (in the language of \code{data.table}) +apart from "geo_value", "time_value", and "version".} + +\item{additional_metadata}{List of additional metadata to attach to the +\code{epi_archive} object. The metadata will have \code{geo_type} and \code{time_type} +fields; named entries from the passed list or will be included as well.} + +\item{compactify}{Optional; Boolean or \code{NULL}: should we remove rows that are +considered redundant for the purposes of \code{epi_archive}'s built-in methods +such as \code{as_of}? As these methods use the last version of each observation +carried forward (LOCF) to interpolate between the version data provided, +rows that don't change these LOCF results can potentially be omitted to +save space. \code{TRUE} will remove these rows, \code{FALSE} will not, and missing or +\code{NULL} will remove these rows and issue a warning. Generally, this can be +set to \code{TRUE}, but if you directly inspect or edit the fields of the +\code{epi_archive} such as its \code{DT}, you will have to determine whether +\code{compactify=TRUE} will produce the desired results. If compactification +here is removing a large proportion of the rows, this may indicate a +potential for space, time, or bandwidth savings upstream the data pipeline, +e.g., when fetching, storing, or preparing the input data \code{x}} + +\item{clobberable_versions_start}{Optional; \code{length}-1; either a value of the +same \code{class} and \code{typeof} as \code{x$version}, or an \code{NA} of any \code{class} and +\code{typeof}: specifically, either (a) the earliest version that could be +subject to "clobbering" (being overwritten with different update data, but +using the \emph{same} version tag as the old update data), or (b) \code{NA}, to +indicate that no versions are clobberable. There are a variety of reasons +why versions could be clobberable under routine circumstances, such as (a) +today's version of one/all of the columns being published after initially +being filled with \code{NA} or LOCF, (b) a buggy version of today's data being +published but then fixed and republished later in the day, or (c) data +pipeline delays (e.g., publisher uploading, periodic scraping, database +syncing, periodic fetching, etc.) that make events (a) or (b) reflected +later in the day (or even on a different day) than expected; potential +causes vary between different data pipelines. The default value is \code{NA}, +which doesn't consider any versions to be clobberable. Another setting that +may be appropriate for some pipelines is \code{max_version_with_row_in(x)}.} + +\item{versions_end}{Optional; length-1, same \code{class} and \code{typeof} as +\code{x$version}: what is the last version we have observed? The default is +\code{max_version_with_row_in(x)}, but values greater than this could also be +valid, and would indicate that we observed additional versions of the data +beyond \code{max(x$version)}, but they all contained empty updates. (The default +value of \code{clobberable_versions_start} does not fully trust these empty +updates, and assumes that any version \verb{>= max(x$version)} could be +clobbered.) If \code{nrow(x) == 0}, then this argument is mandatory.} +} +\value{ +An \code{epi_archive} object. +} +\description{ +Converts a data frame, data table, or tibble into an \code{epi_archive} +object. See the \href{https://cmu-delphi.github.io/epiprocess/articles/archive.html}{archive vignette} for +examples. The parameter descriptions below are copied from there +} +\details{ +This simply a wrapper around the \code{new()} method of the \code{epi_archive} +class, so for example: + +\if{html}{\out{
}}\preformatted{x <- as_epi_archive(df, geo_type = "state", time_type = "day") +}\if{html}{\out{
}} + +would be equivalent to: + +\if{html}{\out{
}}\preformatted{x <- epi_archive$new(df, geo_type = "state", time_type = "day") +}\if{html}{\out{
}} +} +\examples{ +# Simple ex. with necessary keys +tib <- tibble::tibble( + geo_value = rep(c("ca", "hi"), each = 5), + time_value = rep(seq(as.Date("2020-01-01"), + by = 1, length.out = 5 + ), times = 2), + version = rep(seq(as.Date("2020-01-02"), + by = 1, length.out = 5 + ), times = 2), + value = rnorm(10, mean = 2, sd = 1) +) + +toy_epi_archive <- tib \%>\% as_epi_archive( + geo_type = "state", + time_type = "day" +) +toy_epi_archive + +# Ex. with an additional key for county +df <- data.frame( + geo_value = c(replicate(2, "ca"), replicate(2, "fl")), + county = c(1, 3, 2, 5), + time_value = c( + "2020-06-01", + "2020-06-02", + "2020-06-01", + "2020-06-02" + ), + version = c( + "2020-06-02", + "2020-06-03", + "2020-06-02", + "2020-06-03" + ), + cases = c(1, 2, 3, 4), + cases_rate = c(0.01, 0.02, 0.01, 0.05) +) + +x <- df \%>\% as_epi_archive( + geo_type = "state", + time_type = "day", + other_keys = "county" +) +} diff --git a/man/as_of.epi_archive2.Rd b/man/as_of.epi_archive2.Rd new file mode 100644 index 000000000..21a4cfc11 --- /dev/null +++ b/man/as_of.epi_archive2.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{as_of.epi_archive2} +\alias{as_of.epi_archive2} +\title{As of epi_archive} +\usage{ +\method{as_of}{epi_archive2}(epi_archive, max_version, min_time_value = -Inf, all_versions = FALSE) +} +\arguments{ +\item{epi_archive}{An \code{epi_archive} object} + +\item{max_version}{Version specifying the max version to permit in the +snapshot. That is, the snapshot will comprise the unique rows of the +current archive data that represent the most up-to-date signal values, as +of the specified \code{max_version} (and whose \code{time_value}s are at least +\code{min_time_value}).} + +\item{min_time_value}{Time value specifying the min \code{time_value} to permit in +the snapshot. Default is \code{-Inf}, which effectively means that there is no +minimum considered.} + +\item{all_versions}{Boolean; If \code{all_versions = TRUE}, then the output will be in +\code{epi_archive} format, and contain rows in the specified \code{time_value} range +having \code{version <= max_version}. The resulting object will cover a +potentially narrower \code{version} and \code{time_value} range than \code{x}, depending +on user-provided arguments. Otherwise, there will be one row in the output +for the \code{max_version} of each \code{time_value}. Default is \code{FALSE}.} +} +\description{ +Generates a snapshot in \code{epi_df} format as of a given version. +See the documentation for the wrapper function \code{\link[=epix_as_of]{epix_as_of()}} for +details. The parameter descriptions below are copied from there +} diff --git a/man/epi_archive.Rd b/man/epi_archive.Rd index 6a25b2af0..efe5d5bab 100644 --- a/man/epi_archive.Rd +++ b/man/epi_archive.Rd @@ -1,9 +1,14 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/archive.R +% Please edit documentation in R/archive.R, R/archive_new.R \name{epi_archive} \alias{epi_archive} \title{\code{epi_archive} object} \description{ +An \code{epi_archive} is an R6 class which contains a data table +along with several relevant pieces of metadata. The data table can be seen +as the full archive (version history) for some signal variables of +interest. + An \code{epi_archive} is an R6 class which contains a data table along with several relevant pieces of metadata. The data table can be seen as the full archive (version history) for some signal variables of @@ -49,6 +54,56 @@ represent potential update data that we do not yet have access to; or in version in which it was first released, or if no version of that observation appears in the archive data at all. +\strong{A word of caution:} R6 objects, unlike most other objects in R, have +reference semantics. A primary consequence of this is that objects are not +copied when modified. You can read more about this in Hadley Wickham's +\href{https://adv-r.hadley.nz/r6.html#r6-semantics}{Advanced R} book. In order +to construct a modified archive while keeping the original intact, first +make a clone using the \verb{$clone} method, then overwrite the clone's \code{DT} +field with \code{data.table::copy(clone$DT)}, and finally perform the +modifications on the clone. + +epi archive + +An \code{epi_archive} is an R6 class which contains a data table \code{DT}, of +class \code{data.table} from the \code{data.table} package, with (at least) the +following columns: +\itemize{ +\item \code{geo_value}: the geographic value associated with each row of measurements. +\item \code{time_value}: the time value associated with each row of measurements. +\item \code{version}: the time value specifying the version for each row of +measurements. For example, if in a given row the \code{version} is January 15, +2022 and \code{time_value} is January 14, 2022, then this row contains the +measurements of the data for January 14, 2022 that were available one day +later. +} + +The data table \code{DT} has key variables \code{geo_value}, \code{time_value}, \code{version}, +as well as any others (these can be specified when instantiating the +\code{epi_archive} object via the \code{other_keys} argument, and/or set by operating +on \code{DT} directly). Refer to the documentation for \code{\link[=as_epi_archive]{as_epi_archive()}} for +information and examples of relevant parameter names for an \code{epi_archive} object. +Note that there can only be a single row per unique combination of +key variables, and thus the key variables are critical for figuring out how +to generate a snapshot of data from the archive, as of a given version. + +In general, the last version of each observation is carried forward (LOCF) to +fill in data between recorded versions, and between the last recorded +update and the \code{versions_end}. One consequence is that the \code{DT} +doesn't have to contain a full snapshot of every version (although this +generally works), but can instead contain only the rows that are new or +changed from the previous version (see \code{compactify}, which does this +automatically). Currently, deletions must be represented as revising a row +to a special state (e.g., making the entries \code{NA} or including a special +column that flags the data as removed and performing some kind of +post-processing), and the archive is unaware of what this state is. Note +that \code{NA}s \emph{can} be introduced by \code{epi_archive} methods for other reasons, +e.g., in \code{\link{epix_fill_through_version}} and \code{\link{epix_merge}}, if requested, to +represent potential update data that we do not yet have access to; or in +\code{\link{epix_merge}} to represent the "value" of an observation before the +version in which it was first released, or if no version of that +observation appears in the archive data at all. + \strong{A word of caution:} R6 objects, unlike most other objects in R, have reference semantics. A primary consequence of this is that objects are not copied when modified. You can read more about this in Hadley Wickham's @@ -60,6 +115,22 @@ modifications on the clone. } \section{Metadata}{ +The following pieces of metadata are included as fields in an \code{epi_archive} +object: +\itemize{ +\item \code{geo_type}: the type for the geo values. +\item \code{time_type}: the type for the time values. +\item \code{additional_metadata}: list of additional metadata for the data archive. +} + +Unlike an \code{epi_df} object, metadata for an \code{epi_archive} object \code{x} can be +accessed (and altered) directly, as in \code{x$geo_type} or \code{x$time_type}, +etc. Like an \code{epi_df} object, the \code{geo_type} and \code{time_type} fields in the +metadata of an \code{epi_archive} object are not currently used by any +downstream functions in the \code{epiprocess} package, and serve only as useful +bits of information to convey about the data set at hand. + + The following pieces of metadata are included as fields in an \code{epi_archive} object: \itemize{ @@ -78,6 +149,13 @@ bits of information to convey about the data set at hand. \section{Generating Snapshots}{ +An \code{epi_archive} object can be used to generate a snapshot of the data in +\code{epi_df} format, which represents the most up-to-date values of the signal +variables, as of the specified version. This is accomplished by calling the +\code{as_of()} method for an \code{epi_archive} object \code{x}. More details on this +method are documented in the wrapper function \code{\link[=epix_as_of]{epix_as_of()}}. + + An \code{epi_archive} object can be used to generate a snapshot of the data in \code{epi_df} format, which represents the most up-to-date values of the signal variables, as of the specified version. This is accomplished by calling the @@ -87,6 +165,16 @@ method are documented in the wrapper function \code{\link[=epix_as_of]{epix_as_o \section{Sliding Computations}{ +We can run a sliding computation over an \code{epi_archive} object, much like +\code{epi_slide()} does for an \code{epi_df} object. This is accomplished by calling +the \code{slide()} method for an \code{epi_archive} object, which works similarly to +the way \code{epi_slide()} works for an \code{epi_df} object, but with one key +difference: it is version-aware. That is, for an \code{epi_archive} object, the +sliding computation at any given reference time point t is performed on +\strong{data that would have been available as of t}. More details on \code{slide()} +are documented in the wrapper function \code{\link[=epix_slide]{epix_slide()}}. + + We can run a sliding computation over an \code{epi_archive} object, much like \code{epi_slide()} does for an \code{epi_df} object. This is accomplished by calling the \code{slide()} method for an \code{epi_archive} object, which works similarly to @@ -109,6 +197,22 @@ tib <- tibble::tibble( value = rnorm(10, mean = 2, sd = 1) ) +toy_epi_archive <- tib \%>\% epi_archive$new( + geo_type = "state", + time_type = "day" +) +toy_epi_archive +tib <- tibble::tibble( + geo_value = rep(c("ca", "hi"), each = 5), + time_value = rep(seq(as.Date("2020-01-01"), + by = 1, length.out = 5 + ), times = 2), + version = rep(seq(as.Date("2020-01-02"), + by = 1, length.out = 5 + ), times = 2), + value = rnorm(10, mean = 2, sd = 1) +) + toy_epi_archive <- tib \%>\% epi_archive$new( geo_type = "state", time_type = "day" diff --git a/man/epix_as_of2.Rd b/man/epix_as_of2.Rd new file mode 100644 index 000000000..6c3db7170 --- /dev/null +++ b/man/epix_as_of2.Rd @@ -0,0 +1,96 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-epi_archive_new.R +\name{epix_as_of2} +\alias{epix_as_of2} +\title{Generate a snapshot from an \code{epi_archive} object} +\usage{ +epix_as_of2( + epi_archive, + max_version, + min_time_value = -Inf, + all_versions = FALSE +) +} +\arguments{ +\item{max_version}{Time value specifying the max version to permit in the +snapshot. That is, the snapshot will comprise the unique rows of the +current archive data that represent the most up-to-date signal values, as +of the specified \code{max_version} (and whose time values are at least +\code{min_time_value}.)} + +\item{min_time_value}{Time value specifying the min time value to permit in +the snapshot. Default is \code{-Inf}, which effectively means that there is no +minimum considered.} + +\item{all_versions}{If \code{all_versions = TRUE}, then the output will be in +\code{epi_archive} format, and contain rows in the specified \code{time_value} range +having \code{version <= max_version}. The resulting object will cover a +potentially narrower \code{version} and \code{time_value} range than \code{x}, depending +on user-provided arguments. Otherwise, there will be one row in the output +for the \code{max_version} of each \code{time_value}. Default is \code{FALSE}.} + +\item{x}{An \code{epi_archive} object} +} +\value{ +An \code{epi_df} object. +} +\description{ +Generates a snapshot in \code{epi_df} format from an \code{epi_archive} object, as of a +given version. See the \href{https://cmu-delphi.github.io/epiprocess/articles/archive.html}{archive vignette} for +examples. +} +\details{ +This is simply a wrapper around the \code{as_of()} method of the +\code{epi_archive} class, so if \code{x} is an \code{epi_archive} object, then: + +\if{html}{\out{
}}\preformatted{epix_as_of(x, max_version = v) +}\if{html}{\out{
}} + +is equivalent to: + +\if{html}{\out{
}}\preformatted{x$as_of(max_version = v) +}\if{html}{\out{
}} + +Mutation and aliasing: \code{epix_as_of} and \verb{$as_of} will not mutate the input +archives, but may in some edge cases alias parts of the inputs, so copy the +outputs if needed before using mutating operations like \code{data.table}'s \verb{:=} +operator. Currently, the only situation where there is potentially aliasing +is of the \code{DT} in edge cases with \code{all_versions = TRUE}, but this may change +in the future. +} +\examples{ +# warning message of data latency shown +epix_as_of2( + x = archive_cases_dv_subset, + max_version = max(archive_cases_dv_subset$DT$version) +) + + +range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 + +epix_as_of2( + x = archive_cases_dv_subset, + max_version = as.Date("2020-06-12") +) + +# When fetching a snapshot as of the latest version with update data in the +# archive, a warning is issued by default, as this update data might not yet +# be finalized (for example, if data versions are labeled with dates, these +# versions might be overwritten throughout the corresponding days with +# additional data or "hotfixes" of erroroneous data; when we build an archive +# based on database queries, the latest available update might still be +# subject to change, but previous versions should be finalized). We can +# muffle such warnings with the following pattern: +withCallingHandlers( + { + epix_as_of2( + x = archive_cases_dv_subset, + max_version = max(archive_cases_dv_subset$DT$version) + ) + }, + epiprocess__snapshot_as_of_clobberable_version = function(wrn) invokeRestart("muffleWarning") +) +# Since R 4.0, there is a `globalCallingHandlers` function that can be used +# to globally toggle these warnings. + +} diff --git a/man/epix_fill_through_version2.Rd b/man/epix_fill_through_version2.Rd new file mode 100644 index 000000000..7389388ab --- /dev/null +++ b/man/epix_fill_through_version2.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-epi_archive_new.R +\name{epix_fill_through_version2} +\alias{epix_fill_through_version2} +\title{\code{epi_archive} with unobserved history filled in (won't mutate, might alias)} +\usage{ +epix_fill_through_version2( + epi_archive, + fill_versions_end, + how = c("na", "locf") +) +} +\arguments{ +\item{fill_versions_end}{Length-1, same class&type as \code{x$version}: the +version through which to fill in missing version history; this will be the +result's \verb{$versions_end} unless it already had a later +\verb{$versions_end}.} + +\item{how}{Optional; \code{"na"} or \code{"locf"}: \code{"na"} will fill in any missing +required version history with \code{NA}s, by inserting (if necessary) an update +immediately after the current \verb{$versions_end} that revises all +existing measurements to be \code{NA} (this is only supported for \code{version} +classes with a \code{next_after} implementation); \code{"locf"} will fill in missing +version history with the last version of each observation carried forward +(LOCF), by leaving the update \verb{$DT} alone (other \code{epi_archive} methods are +based on LOCF). Default is \code{"na"}.} + +\item{x}{An \code{epi_archive}} +} +\value{ +An \code{epi_archive} +} +\description{ +Sometimes, due to upstream data pipeline issues, we have to work with a +version history that isn't completely up to date, but with functions that +expect archives that are completely up to date, or equally as up-to-date as +another archive. This function provides one way to approach such mismatches: +pretend that we've "observed" additional versions, filling in these versions +with NAs or extrapolated values. +} +\details{ +'\code{epix_fill_through_version} will not mutate its \code{x} argument, but its result +might alias fields of \code{x} (e.g., mutating the result's \code{DT} might mutate +\code{x$DT}). The R6 method variant, \code{x$fill_through_version}, will mutate \code{x} to +give the result, but might reseat its fields (e.g., references to the old +\code{x$DT} might not be updated by this function or subsequent operations on +\code{x}), and returns the updated \code{x} \link[base:invisible]{invisibly}. +} diff --git a/man/epix_merge2.Rd b/man/epix_merge2.Rd new file mode 100644 index 000000000..a42e53e42 --- /dev/null +++ b/man/epix_merge2.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-epi_archive_new.R +\name{epix_merge2} +\alias{epix_merge2} +\title{Merge two \code{epi_archive} objects} +\usage{ +epix_merge2( + x, + y, + sync = c("forbid", "na", "locf", "truncate"), + compactify = TRUE +) +} +\arguments{ +\item{x, y}{Two \code{epi_archive} objects to join together.} + +\item{sync}{Optional; \code{"forbid"}, \code{"na"}, \code{"locf"}, or \code{"truncate"}; in the +case that \code{x$versions_end} doesn't match \code{y$versions_end}, what do we do?: +\code{"forbid"}: emit an error; "na": use \code{max(x$versions_end, y$versions_end)} +as the result's \code{versions_end}, but ensure that, if we request a snapshot +as of a version after \code{min(x$versions_end, y$versions_end)}, the +observation columns from the less up-to-date archive will be all NAs (i.e., +imagine there was an update immediately after its \code{versions_end} which +revised all observations to be \code{NA}); \code{"locf"}: use \code{max(x$versions_end, y$versions_end)} as the result's \code{versions_end}, allowing the last version +of each observation to be carried forward to extrapolate unavailable +versions for the less up-to-date input archive (i.e., imagining that in the +less up-to-date archive's data set remained unchanged between its actual +\code{versions_end} and the other archive's \code{versions_end}); or \code{"truncate"}: +use \code{min(x$versions_end, y$versions_end)} as the result's \code{versions_end}, +and discard any rows containing update rows for later versions.} + +\item{compactify}{Optional; \code{TRUE}, \code{FALSE}, or \code{NULL}; should the result be +compactified? See \code{\link{as_epi_archive}} for an explanation of what this means. +Default here is \code{TRUE}.} +} +\value{ +the resulting \code{epi_archive} +} +\description{ +Merges two \code{epi_archive}s that share a common \code{geo_value}, \code{time_value}, and +set of key columns. When they also share a common \code{versions_end}, +using \verb{$as_of} on the result should be the same as using \verb{$as_of} on \code{x} and +\code{y} individually, then performing a full join of the \code{DT}s on the non-version +key columns (potentially consolidating multiple warnings about clobberable +versions). If the \code{versions_end} values differ, the +\code{sync} parameter controls what is done. +} +\details{ +This function, \code{\link{epix_merge}}, does not mutate its inputs and will not alias +either archive's \code{DT}, but may alias other fields; \code{x$merge} will overwrite +\code{x} with the result of the merge, reseating its \code{DT} and several other fields +(making them point to different objects), but avoiding mutation of the +contents of the old \code{DT} (only relevant if you have another reference to the +old \code{DT} in another object). + +In all cases, \code{additional_metadata} will be an empty list, and +\code{clobberable_versions_start} will be set to the earliest version that could +be clobbered in either input archive. +} +\examples{ +# create two example epi_archive datasets +x <- archive_cases_dv_subset$DT \%>\% + dplyr::select(geo_value, time_value, version, case_rate_7d_av) \%>\% + as_epi_archive(compactify = TRUE) +y <- archive_cases_dv_subset$DT \%>\% + dplyr::select(geo_value, time_value, version, percent_cli) \%>\% + as_epi_archive(compactify = TRUE) +# merge results stored in a third object: +xy <- epix_merge(x, y) +# vs. mutating x to hold the merge result: +x$merge(y) + +} diff --git a/man/epix_slide2.Rd b/man/epix_slide2.Rd new file mode 100644 index 000000000..71d3a11ce --- /dev/null +++ b/man/epix_slide2.Rd @@ -0,0 +1,283 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-epi_archive_new.R +\name{epix_slide2} +\alias{epix_slide2} +\title{Slide a function over variables in an \code{epi_archive} or \code{grouped_epi_archive}} +\usage{ +epix_slide2( + x, + f, + ..., + before, + ref_time_values, + time_step, + new_col_name = "slide_value", + as_list_col = FALSE, + names_sep = "_", + all_versions = FALSE +) +} +\arguments{ +\item{x}{An \code{\link{epi_archive}} or \code{\link{grouped_epi_archive}} object. If ungrouped, +all data in \code{x} will be treated as part of a single data group.} + +\item{f}{Function, formula, or missing; together with \code{...} specifies the +computation to slide. To "slide" means to apply a computation over a +sliding (a.k.a. "rolling") time window for each data group. The window is +determined by the \code{before} parameter described below. One time step is +typically one day or one week; see \code{\link{epi_slide}} details for more +explanation. If a function, \code{f} must take an \code{epi_df} with the same +column names as the archive's \code{DT}, minus the \code{version} column; followed +by a one-row tibble containing the values of the grouping variables for +the associated group; followed by a reference time value, usually as a +\code{Date} object; followed by any number of named arguments. If a formula, +\code{f} can operate directly on columns accessed via \code{.x$var} or \code{.$var}, as +in \code{~ mean (.x$var)} to compute a mean of a column \code{var} for each +group-\code{ref_time_value} combination. The group key can be accessed via +\code{.y} or \code{.group_key}, and the reference time value can be accessed via +\code{.z} or \code{.ref_time_value}. If \code{f} is missing, then \code{...} will specify the +computation.} + +\item{...}{Additional arguments to pass to the function or formula specified +via \code{f}. Alternatively, if \code{f} is missing, then \code{...} is interpreted as an +expression for tidy evaluation; in addition to referring to columns +directly by name, the expression has access to \code{.data} and \code{.env} pronouns +as in \code{dplyr} verbs, and can also refer to the \code{.group_key} and +\code{.ref_time_value}. See details of \code{\link{epi_slide}}.} + +\item{before}{How far \code{before} each \code{ref_time_value} should the sliding +window extend? If provided, should be a single, non-NA, +\link[vctrs:vec_cast]{integer-compatible} number of time steps. This window +endpoint is inclusive. For example, if \code{before = 7}, and one time step is +one day, then to produce a value for a \code{ref_time_value} of January 8, we +apply the given function or formula to data (for each group present) with +\code{time_value}s from January 1 onward, as they were reported on January 8. +For typical disease surveillance sources, this will not include any data +with a \code{time_value} of January 8, and, depending on the amount of reporting +latency, may not include January 7 or even earlier \code{time_value}s. (If +instead the archive were to hold nowcasts instead of regular surveillance +data, then we would indeed expect data for \code{time_value} January 8. If it +were to hold forecasts, then we would expect data for \code{time_value}s after +January 8, and the sliding window would extend as far after each +\code{ref_time_value} as needed to include all such \code{time_value}s.)} + +\item{ref_time_values}{Reference time values / versions for sliding +computations; each element of this vector serves both as the anchor point +for the \code{time_value} window for the computation and the \code{max_version} +\code{as_of} which we fetch data in this window. If missing, then this will set +to a regularly-spaced sequence of values set to cover the range of +\code{version}s in the \code{DT} plus the \code{versions_end}; the spacing of values will +be guessed (using the GCD of the skips between values).} + +\item{time_step}{Optional function used to define the meaning of one time +step, which if specified, overrides the default choice based on the +\code{time_value} column. This function must take a positive integer and return +an object of class \code{lubridate::period}. For example, we can use \code{time_step = lubridate::hours} in order to set the time step to be one hour (this +would only be meaningful if \code{time_value} is of class \code{POSIXct}).} + +\item{new_col_name}{String indicating the name of the new column that will +contain the derivative values. Default is "slide_value"; note that setting +\code{new_col_name} equal to an existing column name will overwrite this column.} + +\item{as_list_col}{Should the slide results be held in a list column, or be +\link[tidyr:chop]{unchopped}/\link[tidyr:unnest]{unnested}? Default is \code{FALSE}, +in which case a list object returned by \code{f} would be unnested (using +\code{\link[tidyr:unnest]{tidyr::unnest()}}), and, if the slide computations output data frames, +the names of the resulting columns are given by prepending \code{new_col_name} +to the names of the list elements.} + +\item{names_sep}{String specifying the separator to use in \code{tidyr::unnest()} +when \code{as_list_col = FALSE}. Default is "_". Using \code{NULL} drops the prefix +from \code{new_col_name} entirely.} + +\item{all_versions}{(Not the same as \code{all_rows} parameter of \code{epi_slide}.) If +\code{all_versions = TRUE}, then \code{f} will be passed the version history (all +\code{version <= ref_time_value}) for rows having \code{time_value} between +\code{ref_time_value - before} and \code{ref_time_value}. Otherwise, \code{f} will be +passed only the most recent \code{version} for every unique \code{time_value}. +Default is \code{FALSE}.} +} +\value{ +A tibble whose columns are: the grouping variables, \code{time_value}, +containing the reference time values for the slide computation, and a +column named according to the \code{new_col_name} argument, containing the slide +values. +} +\description{ +Slides a given function over variables in an \code{epi_archive} object. This +behaves similarly to \code{epi_slide()}, with the key exception that it is +version-aware: the sliding computation at any given reference time t is +performed on \strong{data that would have been available as of t}. See the +\href{https://cmu-delphi.github.io/epiprocess/articles/archive.html}{archive vignette} for +examples. +} +\details{ +A few key distinctions between the current function and \code{epi_slide()}: +\enumerate{ +\item In \code{f} functions for \code{epix_slide}, one should not assume that the input +data to contain any rows with \code{time_value} matching the computation's +\code{ref_time_value} (accessible via \verb{attributes()$metadata$as_of}); for +typical epidemiological surveillance data, observations pertaining to a +particular time period (\code{time_value}) are first reported \code{as_of} some +instant after that time period has ended. +\item \code{epix_slide()} doesn't accept an \code{after} argument; its windows extend +from \code{before} time steps before a given \code{ref_time_value} through the last +\code{time_value} available as of version \code{ref_time_value} (typically, this +won't include \code{ref_time_value} itself, as observations about a particular +time interval (e.g., day) are only published after that time interval +ends); \code{epi_slide} windows extend from \code{before} time steps before a +\code{ref_time_value} through \code{after} time steps after \code{ref_time_value}. +\item The input class and columns are similar but different: \code{epix_slide} +(with the default \code{all_versions=FALSE}) keeps all columns and the +\code{epi_df}-ness of the first argument to each computation; \code{epi_slide} only +provides the grouping variables in the second input, and will convert the +first input into a regular tibble if the grouping variables include the +essential \code{geo_value} column. (With \code{all_versions=TRUE}, \code{epix_slide} will +will provide an \code{epi_archive} rather than an \code{epi-df} to each +computation.) +\item The output class and columns are similar but different: \code{epix_slide()} +returns a tibble containing only the grouping variables, \code{time_value}, and +the new column(s) from the slide computations, whereas \code{epi_slide()} +returns an \code{epi_df} with all original variables plus the new columns from +the slide computations. (Both will mirror the grouping or ungroupedness of +their input, with one exception: \code{epi_archive}s can have trivial +(zero-variable) groupings, but these will be dropped in \code{epix_slide} +results as they are not supported by tibbles.) +\item There are no size stability checks or element/row recycling to maintain +size stability in \code{epix_slide}, unlike in \code{epi_slide}. (\code{epix_slide} is +roughly analogous to \code{\link[dplyr:group_map]{dplyr::group_modify}}, while \code{epi_slide} is roughly +analogous to \code{dplyr::mutate} followed by \code{dplyr::arrange}) This is detailed +in the "advanced" vignette. +\item \code{all_rows} is not supported in \code{epix_slide}; since the slide +computations are allowed more flexibility in their outputs than in +\code{epi_slide}, we can't guess a good representation for missing computations +for excluded group-\code{ref_time_value} pairs. +\item The \code{ref_time_values} default for \code{epix_slide} is based on making an +evenly-spaced sequence out of the \code{version}s in the \code{DT} plus the +\code{versions_end}, rather than the \code{time_value}s. +} + +Apart from the above distinctions, the interfaces between \code{epix_slide()} and +\code{epi_slide()} are the same. + +Furthermore, the current function can be considerably slower than +\code{epi_slide()}, for two reasons: (1) it must repeatedly fetch +properly-versioned snapshots from the data archive (via its \code{as_of()} +method), and (2) it performs a "manual" sliding of sorts, and does not +benefit from the highly efficient \code{slider} package. For this reason, it +should never be used in place of \code{epi_slide()}, and only used when +version-aware sliding is necessary (as it its purpose). + +Finally, this is simply a wrapper around the \code{slide()} method of the +\code{epi_archive} and \code{grouped_epi_archive} classes, so if \code{x} is an +object of either of these classes, then: + +\if{html}{\out{
}}\preformatted{epix_slide(x, new_var = comp(old_var), before = 119) +}\if{html}{\out{
}} + +is equivalent to: + +\if{html}{\out{
}}\preformatted{x$slide(new_var = comp(old_var), before = 119) +}\if{html}{\out{
}} + +Mutation and aliasing: \code{epix_slide} and \verb{$slide} will not perform in-place +mutation of the input archives on their own. In some edge cases the inputs it +feeds to the slide computations may alias parts of the input archive, so copy +the slide computation inputs if needed before using mutating operations like +\code{data.table}'s \verb{:=} operator. Similarly, in some edge cases, the output of +the slide operation may alias parts of the input archive, so similarly, make +sure to clone and/or copy appropriately before using in-place mutation. +} +\examples{ +library(dplyr) + +# Reference time points for which we want to compute slide values: +ref_time_values <- seq(as.Date("2020-06-01"), + as.Date("2020-06-15"), + by = "1 day" +) + +# A simple (but not very useful) example (see the archive vignette for a more +# realistic one): +archive_cases_dv_subset \%>\% + group_by(geo_value) \%>\% + epix_slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = ref_time_values, + new_col_name = "case_rate_7d_av_recent_av" + ) \%>\% + ungroup() +# We requested time windows that started 2 days before the corresponding time +# values. The actual number of `time_value`s in each computation depends on +# the reporting latency of the signal and `time_value` range covered by the +# archive (2020-06-01 -- 2021-11-30 in this example). In this case, we have +# * 0 `time_value`s, for ref time 2020-06-01 --> the result is automatically +# discarded +# * 1 `time_value`, for ref time 2020-06-02 +# * 2 `time_value`s, for the rest of the results +# * never the 3 `time_value`s we would get from `epi_slide`, since, because +# of data latency, we'll never have an observation +# `time_value == ref_time_value` as of `ref_time_value`. +# The example below shows this type of behavior in more detail. + +# Examining characteristics of the data passed to each computation with +# `all_versions=FALSE`. +archive_cases_dv_subset \%>\% + group_by(geo_value) \%>\% + epix_slide( + function(x, gk, rtv) { + tibble( + time_range = if (nrow(x) == 0L) { + "0 `time_value`s" + } else { + sprintf("\%s -- \%s", min(x$time_value), max(x$time_value)) + }, + n = nrow(x), + class1 = class(x)[[1L]] + ) + }, + before = 5, all_versions = FALSE, + ref_time_values = ref_time_values, names_sep = NULL + ) \%>\% + ungroup() \%>\% + arrange(geo_value, time_value) + +# --- Advanced: --- + +# `epix_slide` with `all_versions=FALSE` (the default) applies a +# version-unaware computation to several versions of the data. We can also +# use `all_versions=TRUE` to apply a version-*aware* computation to several +# versions of the data, again looking at characteristics of the data passed +# to each computation. In this case, each computation should expect an +# `epi_archive` containing the relevant version data: + +archive_cases_dv_subset \%>\% + group_by(geo_value) \%>\% + epix_slide( + function(x, gk, rtv) { + tibble( + versions_start = if (nrow(x$DT) == 0L) { + "NA (0 rows)" + } else { + toString(min(x$DT$version)) + }, + versions_end = x$versions_end, + time_range = if (nrow(x$DT) == 0L) { + "0 `time_value`s" + } else { + sprintf("\%s -- \%s", min(x$DT$time_value), max(x$DT$time_value)) + }, + n = nrow(x$DT), + class1 = class(x)[[1L]] + ) + }, + before = 5, all_versions = TRUE, + ref_time_values = ref_time_values, names_sep = NULL + ) \%>\% + ungroup() \%>\% + # Focus on one geo_value so we can better see the columns above: + filter(geo_value == "ca") \%>\% + select(-geo_value) + +} diff --git a/man/epix_truncate_versions_after.Rd b/man/epix_truncate_versions_after.Rd index 8f7414184..f30be07fe 100644 --- a/man/epix_truncate_versions_after.Rd +++ b/man/epix_truncate_versions_after.Rd @@ -1,9 +1,12 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/methods-epi_archive.R +% Please edit documentation in R/methods-epi_archive.R, +% R/methods-epi_archive_new.R \name{epix_truncate_versions_after} \alias{epix_truncate_versions_after} \title{Filter an \code{epi_archive} object to keep only older versions} \usage{ +epix_truncate_versions_after(x, max_version) + epix_truncate_versions_after(x, max_version) } \arguments{ @@ -15,9 +18,14 @@ current archive data having \code{version} less than or equal to the specified \code{max_version}} } \value{ +An \code{epi_archive} object + An \code{epi_archive} object } \description{ +Generates a filtered \code{epi_archive} from an \code{epi_archive} object, keeping +only rows with \code{version} falling on or before a specified date. + Generates a filtered \code{epi_archive} from an \code{epi_archive} object, keeping only rows with \code{version} falling on or before a specified date. } diff --git a/man/epix_truncate_versions_after.grouped_epi_archive2.Rd b/man/epix_truncate_versions_after.grouped_epi_archive2.Rd new file mode 100644 index 000000000..5fba48fb6 --- /dev/null +++ b/man/epix_truncate_versions_after.grouped_epi_archive2.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/grouped_archive_new.R +\name{epix_truncate_versions_after.grouped_epi_archive2} +\alias{epix_truncate_versions_after.grouped_epi_archive2} +\title{Truncate versions after a given version, grouped} +\usage{ +\method{epix_truncate_versions_after}{grouped_epi_archive2}(grouped_epi_archive, max_version) +} +\description{ +Truncate versions after a given version, grouped +} diff --git a/man/fill_through_version.epi_archive2.Rd b/man/fill_through_version.epi_archive2.Rd new file mode 100644 index 000000000..48afb864d --- /dev/null +++ b/man/fill_through_version.epi_archive2.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{fill_through_version.epi_archive2} +\alias{fill_through_version.epi_archive2} +\title{Fill through version} +\usage{ +\method{fill_through_version}{epi_archive2}(epi_archive, fill_versions_end, how = c("na", "locf")) +} +\arguments{ +\item{epi_archive}{an \code{epi_archive} object} + +\item{fill_versions_end}{as in \code{\link{epix_fill_through_version}}} + +\item{how}{as in \code{\link{epix_fill_through_version}}} +} +\description{ +Fill in unobserved history using requested scheme by mutating +the given object and potentially reseating its fields. See +\code{\link{epix_fill_through_version}}, which doesn't mutate the input archive but +might alias its fields. +} diff --git a/man/group_by.epi_archive.Rd b/man/group_by.epi_archive.Rd index 5e867bf30..f157e834a 100644 --- a/man/group_by.epi_archive.Rd +++ b/man/group_by.epi_archive.Rd @@ -1,8 +1,14 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/methods-epi_archive.R, R/grouped_epi_archive.R +% Please edit documentation in R/methods-epi_archive.R, R/grouped_archive_new.R, +% R/grouped_epi_archive.R \name{group_by.epi_archive} \alias{group_by.epi_archive} \alias{grouped_epi_archive} +\alias{group_by.grouped_epi_archive2} +\alias{group_by_drop_default.grouped_epi_archive2} +\alias{groups.grouped_epi_archive2} +\alias{ungroup.grouped_epi_archive2} +\alias{is_grouped_epi_archive2} \alias{group_by.grouped_epi_archive} \alias{groups.grouped_epi_archive} \alias{ungroup.grouped_epi_archive} @@ -12,6 +18,21 @@ \usage{ \method{group_by}{epi_archive}(.data, ..., .add = FALSE, .drop = dplyr::group_by_drop_default(.data)) +\method{group_by}{grouped_epi_archive2}( + grouped_epi_archive, + ..., + .add = FALSE, + .drop = dplyr::group_by_drop_default(grouped_epi_archive) +) + +\method{group_by_drop_default}{grouped_epi_archive2}(grouped_epi_archive) + +\method{groups}{grouped_epi_archive2}(grouped_epi_archive) + +\method{ungroup}{grouped_epi_archive2}(grouped_epi_archive, ...) + +is_grouped_epi_archive2(x) + \method{group_by}{grouped_epi_archive}(.data, ..., .add = FALSE, .drop = dplyr::group_by_drop_default(.data)) \method{groups}{grouped_epi_archive}(x) diff --git a/man/group_by.epi_archive2.Rd b/man/group_by.epi_archive2.Rd new file mode 100644 index 000000000..3191b134d --- /dev/null +++ b/man/group_by.epi_archive2.Rd @@ -0,0 +1,147 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{group_by.epi_archive2} +\alias{group_by.epi_archive2} +\alias{grouped_epi_archive} +\title{\code{group_by} and related methods for \code{epi_archive}, \code{grouped_epi_archive}} +\usage{ +\method{group_by}{epi_archive2}( + epi_archive, + ..., + .add = FALSE, + .drop = dplyr::group_by_drop_default(epi_archive) +) +} +\arguments{ +\item{...}{Similar to \code{\link[dplyr:group_by]{dplyr::group_by}} (see "Details:" for edge cases); +\itemize{ +\item For \code{group_by}: unquoted variable name(s) or other +\link[dplyr:dplyr_data_masking]{"data masking"} expression(s). It's possible to +use \code{\link[dplyr:mutate]{dplyr::mutate}}-like syntax here to calculate new columns on which to +perform grouping, but note that, if you are regrouping an already-grouped +\code{.data} object, the calculations will be carried out ignoring such grouping +(same as \link[dplyr:group_by]{in dplyr}). +\item For \code{ungroup}: either +\itemize{ +\item empty, in order to remove the grouping and output an \code{epi_archive}; or +\item variable name(s) or other \link[dplyr:dplyr_tidy_select]{"tidy-select"} +expression(s), in order to remove the matching variables from the list of +grouping variables, and output another \code{grouped_epi_archive}. +} +}} + +\item{.add}{Boolean. If \code{FALSE}, the default, the output will be grouped by +the variable selection from \code{...} only; if \code{TRUE}, the output will be +grouped by the current grouping variables plus the variable selection from +\code{...}.} + +\item{.drop}{As described in \code{\link[dplyr:group_by]{dplyr::group_by}}; determines treatment of +factor columns.} + +\item{.data}{An \code{epi_archive} or \code{grouped_epi_archive}} + +\item{x}{For \code{groups} or \code{ungroup}: a \code{grouped_epi_archive}; for +\code{is_grouped_epi_archive}: any object} + +\item{.tbl}{(For \code{group_by_drop_default}:) an \code{epi_archive} or +\code{grouped_epi_archive} (\code{epi_archive} dispatches to the S3 default method; +\code{grouped_epi_archive} dispatches its own S3 method)} +} +\description{ +\code{group_by} and related methods for \code{epi_archive}, \code{grouped_epi_archive} +} +\details{ +To match \code{dplyr}, \code{group_by} allows "data masking" (also referred to as +"tidy evaluation") expressions \code{...}, not just column names, in a way similar +to \code{mutate}. Note that replacing or removing key columns with these +expressions is disabled. + +\code{archive \%>\% group_by()} and other expressions that group or regroup by zero +columns (indicating that all rows should be treated as part of one large +group) will output a \code{grouped_epi_archive}, in order to enable the use of +\code{grouped_epi_archive} methods on the result. This is in slight contrast to +the same operations on tibbles and grouped tibbles, which will \emph{not} output a +\code{grouped_df} in these circumstances. + +Using \code{group_by} with \code{.add=FALSE} to override the existing grouping is +disabled; instead, \code{ungroup} first then \code{group_by}. + +Mutation and aliasing: \code{group_by} tries to use a shallow copy of the \code{DT}, +introducing column-level aliasing between its input and its result. This +doesn't follow the general model for most \code{data.table} operations, which +seems to be that, given an nonaliased (i.e., unique) pointer to a +\code{data.table} object, its pointers to its columns should also be nonaliased. +If you mutate any of the columns of either the input or result, first ensure +that it is fine if columns of the other are also mutated, but do not rely on +such behavior to occur. Additionally, never perform mutation on the key +columns at all (except for strictly increasing transformations), as this will +invalidate sortedness assumptions about the rows. + +\code{group_by_drop_default} on (ungrouped) \code{epi_archive}s is expected to dispatch +to \code{group_by_drop_default.default} (but there is a dedicated method for +\code{grouped_epi_archive}s). +} +\examples{ + +grouped_archive <- archive_cases_dv_subset \%>\% group_by(geo_value) + +# `print` for metadata and method listing: +grouped_archive \%>\% print() + +# The primary use for grouping is to perform a grouped `epix_slide`: + +archive_cases_dv_subset \%>\% + group_by(geo_value) \%>\% + epix_slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = as.Date("2020-06-11") + 0:2, + new_col_name = "case_rate_3d_av" + ) \%>\% + ungroup() + +# ----------------------------------------------------------------- + +# Advanced: some other features of dplyr grouping are implemented: + +library(dplyr) +toy_archive <- + tribble( + ~geo_value, ~age_group, ~time_value, ~version, ~value, + "us", "adult", "2000-01-01", "2000-01-02", 121, + "us", "pediatric", "2000-01-02", "2000-01-03", 5, # (addition) + "us", "adult", "2000-01-01", "2000-01-03", 125, # (revision) + "us", "adult", "2000-01-02", "2000-01-03", 130 # (addition) + ) \%>\% + mutate( + age_group = ordered(age_group, c("pediatric", "adult")), + time_value = as.Date(time_value), + version = as.Date(version) + ) \%>\% + as_epi_archive(other_keys = "age_group") + +# The following are equivalent: +toy_archive \%>\% group_by(geo_value, age_group) +toy_archive \%>\% + group_by(geo_value) \%>\% + group_by(age_group, .add = TRUE) +grouping_cols <- c("geo_value", "age_group") +toy_archive \%>\% group_by(across(all_of(grouping_cols))) + +# And these are equivalent: +toy_archive \%>\% group_by(geo_value) +toy_archive \%>\% + group_by(geo_value, age_group) \%>\% + ungroup(age_group) + +# To get the grouping variable names as a `list` of `name`s (a.k.a. symbols): +toy_archive \%>\% + group_by(geo_value) \%>\% + groups() + +toy_archive \%>\% + group_by(geo_value, age_group, .drop = FALSE) \%>\% + epix_slide(f = ~ sum(.x$value), before = 20) \%>\% + ungroup() + +} diff --git a/man/is_epi_archive2.Rd b/man/is_epi_archive2.Rd new file mode 100644 index 000000000..fd2f0a1f5 --- /dev/null +++ b/man/is_epi_archive2.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{is_epi_archive2} +\alias{is_epi_archive2} +\title{Test for \code{epi_archive} format} +\usage{ +is_epi_archive2(x, grouped_okay = FALSE) +} +\arguments{ +\item{x}{An object.} + +\item{grouped_okay}{Optional; Boolean; should a \code{grouped_epi_archive} also +count? Default is \code{FALSE}.} +} +\value{ +\code{TRUE} if the object inherits from \code{epi_archive}. +} +\description{ +Test for \code{epi_archive} format +} +\examples{ +is_epi_archive(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) +is_epi_archive(archive_cases_dv_subset) # TRUE + +# By default, grouped_epi_archives don't count as epi_archives, as they may +# support a different set of operations from regular `epi_archives`. This +# behavior can be controlled by `grouped_okay`. +grouped_archive <- archive_cases_dv_subset$group_by(geo_value) +is_epi_archive(grouped_archive) # FALSE +is_epi_archive(grouped_archive, grouped_okay = TRUE) # TRUE + +} +\seealso{ +\code{\link{is_grouped_epi_archive}} +} diff --git a/man/max_version_with_row_in.Rd b/man/max_version_with_row_in.Rd index cca554fae..6f0d35b3f 100644 --- a/man/max_version_with_row_in.Rd +++ b/man/max_version_with_row_in.Rd @@ -1,18 +1,25 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/archive.R +% Please edit documentation in R/archive.R, R/archive_new.R \name{max_version_with_row_in} \alias{max_version_with_row_in} \title{\code{max(x$version)}, with error if \code{x} has 0 rows} \usage{ +max_version_with_row_in(x) + max_version_with_row_in(x) } \arguments{ \item{x}{\code{x} argument of \code{\link{as_epi_archive}}} } \value{ +\code{max(x$version)} if it has any rows; raises error if it has 0 rows or +an \code{NA} version value + \code{max(x$version)} if it has any rows; raises error if it has 0 rows or an \code{NA} version value } \description{ +Exported to make defaults more easily copyable. + Exported to make defaults more easily copyable. } diff --git a/man/merge_epi_archive2.Rd b/man/merge_epi_archive2.Rd new file mode 100644 index 000000000..dd1e671ec --- /dev/null +++ b/man/merge_epi_archive2.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{merge_epi_archive2} +\alias{merge_epi_archive2} +\title{Merge epi archive} +\usage{ +merge_epi_archive2( + x, + y, + sync = c("forbid", "na", "locf", "truncate"), + compactify = TRUE +) +} +\arguments{ +\item{x}{as in \code{\link{epix_merge}}} + +\item{y}{as in \code{\link{epix_merge}}} + +\item{sync}{as in \code{\link{epix_merge}}} + +\item{compactify}{as in \code{\link{epix_merge}}} +} +\description{ +Merges another \code{epi_archive} with the current one, mutating the +current one by reseating its \code{DT} and several other fields, but avoiding +mutation of the old \code{DT}; returns the current archive +\link[base:invisible]{invisibly}. See \code{\link{epix_merge}} for a full description +of the non-R6-method version, which does not mutate either archive, and +does not alias either archive's \code{DT}.a +} diff --git a/man/new_epi_archive2.Rd b/man/new_epi_archive2.Rd new file mode 100644 index 000000000..521411903 --- /dev/null +++ b/man/new_epi_archive2.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{new_epi_archive2} +\alias{new_epi_archive2} +\title{New epi archive} +\usage{ +new_epi_archive2( + x, + geo_type = NULL, + time_type = NULL, + other_keys = NULL, + additional_metadata = NULL, + compactify = NULL, + clobberable_versions_start = NA, + versions_end = NULL +) +} +\arguments{ +\item{x}{A data.frame, data.table, or tibble, with columns \code{geo_value}, +\code{time_value}, \code{version}, and then any additional number of columns.} + +\item{geo_type}{Type for the geo values. If missing, then the function will +attempt to infer it from the geo values present; if this fails, then it +will be set to "custom".} + +\item{time_type}{Type for the time values. If missing, then the function will +attempt to infer it from the time values present; if this fails, then it +will be set to "custom".} + +\item{other_keys}{Character vector specifying the names of variables in \code{x} +that should be considered key variables (in the language of \code{data.table}) +apart from "geo_value", "time_value", and "version".} + +\item{additional_metadata}{List of additional metadata to attach to the +\code{epi_archive} object. The metadata will have \code{geo_type} and \code{time_type} +fields; named entries from the passed list or will be included as well.} + +\item{compactify}{Optional; Boolean or \code{NULL}: should we remove rows that are +considered redundant for the purposes of \code{epi_archive}'s built-in methods +such as \code{as_of}? As these methods use the last version of each observation +carried forward (LOCF) to interpolate between the version data provided, +rows that don't change these LOCF results can potentially be omitted to +save space while maintaining the same behavior (with the help of the +\code{clobberable_versions_start} and \code{versions_end} fields in some edge cases). +\code{TRUE} will remove these rows, \code{FALSE} will not, and missing or \code{NULL} will +remove these rows and issue a warning. Generally, this can be set to +\code{TRUE}, but if you directly inspect or edit the fields of the \code{epi_archive} +such as its \code{DT}, or rely on redundant updates to achieve a certain +behavior of the \code{ref_time_values} default in \code{epix_slide}, you will have to +determine whether \code{compactify=TRUE} will produce the desired results. If +compactification here is removing a large proportion of the rows, this may +indicate a potential for space, time, or bandwidth savings upstream the +data pipeline, e.g., by avoiding fetching, storing, or processing these +rows of \code{x}.} + +\item{clobberable_versions_start}{Optional; as in \code{\link{as_epi_archive}}} + +\item{versions_end}{Optional; as in \code{\link{as_epi_archive}}} +} +\value{ +An \code{epi_archive} object. +} +\description{ +Creates a new \code{epi_archive} object. +} +\details{ +Refer to the documentation for \code{\link[=as_epi_archive]{as_epi_archive()}} for more information +and examples of parameter names. +} diff --git a/man/next_after.Rd b/man/next_after.Rd index 5170e8d9d..82fd3ebbe 100644 --- a/man/next_after.Rd +++ b/man/next_after.Rd @@ -1,17 +1,23 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/archive.R +% Please edit documentation in R/archive.R, R/archive_new.R \name{next_after} \alias{next_after} \title{Get the next possible value greater than \code{x} of the same type} \usage{ +next_after(x) + next_after(x) } \arguments{ \item{x}{the starting "value"(s)} } \value{ +same class, typeof, and length as \code{x} + same class, typeof, and length as \code{x} } \description{ +Get the next possible value greater than \code{x} of the same type + Get the next possible value greater than \code{x} of the same type } diff --git a/man/print.epi_archive2.Rd b/man/print.epi_archive2.Rd new file mode 100644 index 000000000..0105c47e7 --- /dev/null +++ b/man/print.epi_archive2.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{print.epi_archive2} +\alias{print.epi_archive2} +\title{Print information about an \code{epi_archive} object} +\usage{ +\method{print}{epi_archive2}(epi_archive, class = TRUE, methods = TRUE) +} +\arguments{ +\item{class}{Boolean; whether to print the class label header} + +\item{methods}{Boolean; whether to print all available methods of +the archive} +} +\description{ +Print information about an \code{epi_archive} object +} diff --git a/man/slide.epi_archive2.Rd b/man/slide.epi_archive2.Rd new file mode 100644 index 000000000..54db56368 --- /dev/null +++ b/man/slide.epi_archive2.Rd @@ -0,0 +1,101 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{slide.epi_archive2} +\alias{slide.epi_archive2} +\title{Slide over epi archive} +\usage{ +\method{slide}{epi_archive2}( + epi_archive, + f, + ..., + before, + ref_time_values, + time_step, + new_col_name = "slide_value", + as_list_col = FALSE, + names_sep = "_", + all_versions = FALSE +) +} +\arguments{ +\item{f}{Function, formula, or missing; together with \code{...} specifies the +computation to slide. To "slide" means to apply a computation over a +sliding (a.k.a. "rolling") time window for each data group. The window is +determined by the \code{before} parameter described below. One time step is +typically one day or one week; see \code{\link{epi_slide}} details for more +explanation. If a function, \code{f} must take an \code{epi_df} with the same +column names as the archive's \code{DT}, minus the \code{version} column; followed +by a one-row tibble containing the values of the grouping variables for +the associated group; followed by a reference time value, usually as a +\code{Date} object; followed by any number of named arguments. If a formula, +\code{f} can operate directly on columns accessed via \code{.x$var} or \code{.$var}, as +in \code{~ mean (.x$var)} to compute a mean of a column \code{var} for each +group-\code{ref_time_value} combination. The group key can be accessed via +\code{.y} or \code{.group_key}, and the reference time value can be accessed via +\code{.z} or \code{.ref_time_value}. If \code{f} is missing, then \code{...} will specify the +computation.} + +\item{...}{Additional arguments to pass to the function or formula specified +via \code{f}. Alternatively, if \code{f} is missing, then \code{...} is interpreted as an +expression for tidy evaluation; in addition to referring to columns +directly by name, the expression has access to \code{.data} and \code{.env} pronouns +as in \code{dplyr} verbs, and can also refer to the \code{.group_key} and +\code{.ref_time_value}. See details of \code{\link{epi_slide}}.} + +\item{before}{How far \code{before} each \code{ref_time_value} should the sliding +window extend? If provided, should be a single, non-NA, +\link[vctrs:vec_cast]{integer-compatible} number of time steps. This window +endpoint is inclusive. For example, if \code{before = 7}, and one time step is +one day, then to produce a value for a \code{ref_time_value} of January 8, we +apply the given function or formula to data (for each group present) with +\code{time_value}s from January 1 onward, as they were reported on January 8. +For typical disease surveillance sources, this will not include any data +with a \code{time_value} of January 8, and, depending on the amount of reporting +latency, may not include January 7 or even earlier \code{time_value}s. (If +instead the archive were to hold nowcasts instead of regular surveillance +data, then we would indeed expect data for \code{time_value} January 8. If it +were to hold forecasts, then we would expect data for \code{time_value}s after +January 8, and the sliding window would extend as far after each +\code{ref_time_value} as needed to include all such \code{time_value}s.)} + +\item{ref_time_values}{Reference time values / versions for sliding +computations; each element of this vector serves both as the anchor point +for the \code{time_value} window for the computation and the \code{max_version} +\code{as_of} which we fetch data in this window. If missing, then this will set +to a regularly-spaced sequence of values set to cover the range of +\code{version}s in the \code{DT} plus the \code{versions_end}; the spacing of values will +be guessed (using the GCD of the skips between values).} + +\item{time_step}{Optional function used to define the meaning of one time +step, which if specified, overrides the default choice based on the +\code{time_value} column. This function must take a positive integer and return +an object of class \code{lubridate::period}. For example, we can use \code{time_step = lubridate::hours} in order to set the time step to be one hour (this +would only be meaningful if \code{time_value} is of class \code{POSIXct}).} + +\item{new_col_name}{String indicating the name of the new column that will +contain the derivative values. Default is "slide_value"; note that setting +\code{new_col_name} equal to an existing column name will overwrite this column.} + +\item{as_list_col}{Should the slide results be held in a list column, or be +\link[tidyr:chop]{unchopped}/\link[tidyr:unnest]{unnested}? Default is \code{FALSE}, +in which case a list object returned by \code{f} would be unnested (using +\code{\link[tidyr:unnest]{tidyr::unnest()}}), and, if the slide computations output data frames, +the names of the resulting columns are given by prepending \code{new_col_name} +to the names of the list elements.} + +\item{names_sep}{String specifying the separator to use in \code{tidyr::unnest()} +when \code{as_list_col = FALSE}. Default is "_". Using \code{NULL} drops the prefix +from \code{new_col_name} entirely.} + +\item{all_versions}{(Not the same as \code{all_rows} parameter of \code{epi_slide}.) If +\code{all_versions = TRUE}, then \code{f} will be passed the version history (all +\code{version <= ref_time_value}) for rows having \code{time_value} between +\code{ref_time_value - before} and \code{ref_time_value}. Otherwise, \code{f} will be +passed only the most recent \code{version} for every unique \code{time_value}. +Default is \code{FALSE}.} +} +\description{ +Slides a given function over variables in an \code{epi_archive} +object. See the documentation for the wrapper function \code{\link[=epix_slide]{epix_slide()}} for +details. The parameter descriptions below are copied from there +} diff --git a/man/slide.grouped_epi_archive2.Rd b/man/slide.grouped_epi_archive2.Rd new file mode 100644 index 000000000..b5aac24c8 --- /dev/null +++ b/man/slide.grouped_epi_archive2.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/grouped_archive_new.R +\name{slide.grouped_epi_archive2} +\alias{slide.grouped_epi_archive2} +\title{Slide over grouped epi archive} +\usage{ +\method{slide}{grouped_epi_archive2}( + grouped_epi_archive, + f, + ..., + before, + ref_time_values, + time_step, + new_col_name = "slide_value", + as_list_col = FALSE, + names_sep = "_", + all_versions = FALSE +) +} +\description{ +Slides a given function over variables in a \code{grouped_epi_archive} +object. See the documentation for the wrapper function \code{\link[=epix_slide]{epix_slide()}} for +details. +} diff --git a/man/truncate_versions_after.epi_archive2.Rd b/man/truncate_versions_after.epi_archive2.Rd new file mode 100644 index 000000000..08ae40d4f --- /dev/null +++ b/man/truncate_versions_after.epi_archive2.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/archive_new.R +\name{truncate_versions_after.epi_archive2} +\alias{truncate_versions_after.epi_archive2} +\title{Truncate versions after} +\usage{ +\method{truncate_versions_after}{epi_archive2}(epi_archive, max_version) +} +\arguments{ +\item{epi_archive}{as in \code{\link{epix_truncate_versions_after}}} + +\item{max_version}{as in \code{\link{epix_truncate_versions_after}}} +} +\description{ +Filter to keep only older versions, mutating the archive by +potentially reseating but not mutating some fields. \code{DT} is likely, but not +guaranteed, to be copied. Returns the mutated archive +\link[base:invisible]{invisibly}. +} diff --git a/man/truncate_versions_after.grouped_epi_archive2.Rd b/man/truncate_versions_after.grouped_epi_archive2.Rd new file mode 100644 index 000000000..7c25950f5 --- /dev/null +++ b/man/truncate_versions_after.grouped_epi_archive2.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/grouped_archive_new.R +\name{truncate_versions_after.grouped_epi_archive2} +\alias{truncate_versions_after.grouped_epi_archive2} +\title{Truncate versions after a given version, grouped} +\usage{ +\method{truncate_versions_after}{grouped_epi_archive2}(grouped_epi_archive, max_version) +} +\arguments{ +\item{max_version}{as in \code{\link{epix_truncate_versions_after}}} + +\item{x}{as in \code{\link{epix_truncate_versions_after}}} +} +\description{ +Filter to keep only older versions by mutating the underlying +\code{epi_archive} using \verb{$truncate_versions_after}. Returns the mutated +\code{grouped_epi_archive} \link[base:invisible]{invisibly}. +} diff --git a/tests/testthat/test-archive_new.R b/tests/testthat/test-archive_new.R new file mode 100644 index 000000000..f2d0bde58 --- /dev/null +++ b/tests/testthat/test-archive_new.R @@ -0,0 +1,173 @@ +library(dplyr) + +test_that("first input must be a data.frame", { + expect_error(as_epi_archive2(c(1, 2, 3), compactify = FALSE), + regexp = "Must be of type 'data.frame'." + ) +}) + +dt <- archive_cases_dv_subset$DT + +test_that("data.frame must contain geo_value, time_value and version columns", { + expect_error(as_epi_archive2(select(dt, -geo_value), compactify = FALSE), + regexp = "Columns `geo_value`, `time_value`, and `version` must be present in `x`." + ) + expect_error(as_epi_archive2(select(dt, -time_value), compactify = FALSE), + regexp = "Columns `geo_value`, `time_value`, and `version` must be present in `x`." + ) + expect_error(as_epi_archive2(select(dt, -version), compactify = FALSE), + regexp = "Columns `geo_value`, `time_value`, and `version` must be present in `x`." + ) +}) + +test_that("other_keys can only contain names of the data.frame columns", { + expect_error(as_epi_archive2(dt, other_keys = "xyz", compactify = FALSE), + regexp = "`other_keys` must be contained in the column names of `x`." + ) + expect_error(as_epi_archive2(dt, other_keys = "percent_cli", compactify = FALSE), NA) +}) + +test_that("other_keys cannot contain names geo_value, time_value or version", { + expect_error(as_epi_archive2(dt, other_keys = "geo_value", compactify = FALSE), + regexp = "`other_keys` cannot contain \"geo_value\", \"time_value\", or \"version\"." + ) + expect_error(as_epi_archive2(dt, other_keys = "time_value", compactify = FALSE), + regexp = "`other_keys` cannot contain \"geo_value\", \"time_value\", or \"version\"." + ) + expect_error(as_epi_archive2(dt, other_keys = "version", compactify = FALSE), + regexp = "`other_keys` cannot contain \"geo_value\", \"time_value\", or \"version\"." + ) +}) + +test_that("Warning thrown when other_metadata contains overlapping names with geo_type or time_type fields", { + expect_warning(as_epi_archive2(dt, additional_metadata = list(geo_type = 1), compactify = FALSE), + regexp = "`additional_metadata` names overlap with existing metadata fields \"geo_type\", \"time_type\"." + ) + expect_warning(as_epi_archive2(dt, additional_metadata = list(time_type = 1), compactify = FALSE), + regexp = "`additional_metadata` names overlap with existing metadata fields \"geo_type\", \"time_type\"." + ) +}) + +test_that("epi_archives are correctly instantiated with a variety of data types", { + # Data frame + df <- data.frame( + geo_value = "ca", + time_value = as.Date("2020-01-01"), + version = as.Date("2020-01-01") + 0:19, + value = 1:20 + ) + + ea1 <- as_epi_archive2(df, compactify = FALSE) + expect_equal(key(ea1$DT), c("geo_value", "time_value", "version")) + expect_equal(ea1$additional_metadata, list()) + + ea2 <- as_epi_archive2(df, other_keys = "value", additional_metadata = list(value = df$value), compactify = FALSE) + expect_equal(key(ea2$DT), c("geo_value", "time_value", "value", "version")) + expect_equal(ea2$additional_metadata, list(value = df$value)) + + # Tibble + tib <- tibble::tibble(df, code = "x") + + ea3 <- as_epi_archive2(tib, compactify = FALSE) + expect_equal(key(ea3$DT), c("geo_value", "time_value", "version")) + expect_equal(ea3$additional_metadata, list()) + + ea4 <- as_epi_archive2(tib, other_keys = "code", additional_metadata = list(value = df$value), compactify = FALSE) + expect_equal(key(ea4$DT), c("geo_value", "time_value", "code", "version")) + expect_equal(ea4$additional_metadata, list(value = df$value)) + + # Keyed data.table + kdt <- data.table::data.table( + geo_value = "ca", + time_value = as.Date("2020-01-01"), + version = as.Date("2020-01-01") + 0:19, + value = 1:20, + code = "CA", + key = "code" + ) + + ea5 <- as_epi_archive2(kdt, compactify = FALSE) + # Key from data.table isn't absorbed when as_epi_archive2 is used + expect_equal(key(ea5$DT), c("geo_value", "time_value", "version")) + expect_equal(ea5$additional_metadata, list()) + + ea6 <- as_epi_archive2(kdt, other_keys = "value", additional_metadata = list(value = df$value), compactify = FALSE) + # Mismatched keys, but the one from as_epi_archive2 overrides + expect_equal(key(ea6$DT), c("geo_value", "time_value", "value", "version")) + expect_equal(ea6$additional_metadata, list(value = df$value)) + + # Unkeyed data.table + udt <- data.table::data.table( + geo_value = "ca", + time_value = as.Date("2020-01-01"), + version = as.Date("2020-01-01") + 0:19, + value = 1:20, + code = "CA" + ) + + ea7 <- as_epi_archive2(udt, compactify = FALSE) + expect_equal(key(ea7$DT), c("geo_value", "time_value", "version")) + expect_equal(ea7$additional_metadata, list()) + + ea8 <- as_epi_archive2(udt, other_keys = "code", additional_metadata = list(value = df$value), compactify = FALSE) + expect_equal(key(ea8$DT), c("geo_value", "time_value", "code", "version")) + expect_equal(ea8$additional_metadata, list(value = df$value)) + + # epi_df + edf1 <- jhu_csse_daily_subset %>% + select(geo_value, time_value, cases) %>% + mutate(version = max(time_value), code = "USA") + + ea9 <- as_epi_archive2(edf1, compactify = FALSE) + expect_equal(key(ea9$DT), c("geo_value", "time_value", "version")) + expect_equal(ea9$additional_metadata, list()) + + ea10 <- as_epi_archive2(edf1, other_keys = "code", additional_metadata = list(value = df$value), compactify = FALSE) + expect_equal(key(ea10$DT), c("geo_value", "time_value", "code", "version")) + expect_equal(ea10$additional_metadata, list(value = df$value)) + + # Keyed epi_df + edf2 <- data.frame( + geo_value = "al", + time_value = rep(as.Date("2020-01-01") + 0:9, 2), + version = c( + rep(as.Date("2020-01-25"), 10), + rep(as.Date("2020-01-26"), 10) + ), + cases = 1:20, + misc = "USA" + ) %>% + as_epi_df(additional_metadata = list(other_keys = "misc")) + + ea11 <- as_epi_archive2(edf2, compactify = FALSE) + expect_equal(key(ea11$DT), c("geo_value", "time_value", "version")) + expect_equal(ea11$additional_metadata, list()) + + ea12 <- as_epi_archive2(edf2, other_keys = "misc", additional_metadata = list(value = df$misc), compactify = FALSE) + expect_equal(key(ea12$DT), c("geo_value", "time_value", "misc", "version")) + expect_equal(ea12$additional_metadata, list(value = df$misc)) +}) + +test_that("`epi_archive` rejects nonunique keys", { + toy_update_tbl <- + tibble::tribble( + ~geo_value, ~age_group, ~time_value, ~version, ~value, + "us", "adult", "2000-01-01", "2000-01-02", 121, + "us", "adult", "2000-01-01", "2000-01-03", 125, # (revision) + "us", "adult", "2000-01-02", "2000-01-03", 130, + "us", "pediatric", "2000-01-01", "2000-01-02", 5 + ) %>% + mutate( + age_group = ordered(age_group, c("pediatric", "adult")), + time_value = as.Date(time_value), + version = as.Date(version) + ) + expect_error( + as_epi_archive2(toy_update_tbl), + class = "epiprocess__epi_archive_requires_unique_key" + ) + expect_error( + regexp = NA, + as_epi_archive2(toy_update_tbl, other_keys = "age_group"), + ) +}) diff --git a/tests/testthat/test-compactify_new.R b/tests/testthat/test-compactify_new.R new file mode 100644 index 000000000..f2887eaf7 --- /dev/null +++ b/tests/testthat/test-compactify_new.R @@ -0,0 +1,110 @@ +library(epiprocess) +library(data.table) +library(dplyr) + +dt <- archive_cases_dv_subset$DT +dt <- filter(dt, geo_value == "ca") %>% + filter(version <= "2020-06-15") %>% + select(-case_rate_7d_av) + +test_that("Input for compactify must be NULL or a boolean", { + expect_error(as_epi_archive2(dt, compactify = "no")) +}) + +dt$percent_cli <- c(1:80) +dt$case_rate <- c(1:80) + +row_replace <- function(dt, row, x, y) { + # (This way of "replacing" elements appears to use copy-on-write even though + # we are working with a data.table.) + dt[row, 4] <- x + dt[row, 5] <- y + dt +} + +# Note that compactify is working on version-wise LOCF (last version of each +# observation carried forward) + +# Rows 1 should not be eliminated even if NA +dt <- row_replace(dt, 1, NA, NA) # Not LOCF + +# NOTE! We are assuming that there are no NA's in geo_value, time_value, +# and version. Even though compactify may erroneously remove the first row +# if it has all NA's, we are not testing this behaviour for now as this dataset +# has problems beyond the scope of this test + +# Rows 11 and 12 correspond to different time_values +dt <- row_replace(dt, 12, 11, 11) # Not LOCF + +# Rows 20 and 21 only differ in version +dt <- row_replace(dt, 21, 20, 20) # LOCF + +# Rows 21 and 22 only differ in version +dt <- row_replace(dt, 22, 20, 20) # LOCF + +# Row 39 comprises the first NA's +dt <- row_replace(dt, 39, NA, NA) # Not LOCF + +# Row 40 has two NA's, just like its lag, row 39 +dt <- row_replace(dt, 40, NA, NA) # LOCF + +# Row 62's values already exist in row 15, but row 15 is not a preceding row +dt <- row_replace(dt, 62, 15, 15) # Not LOCF + +# Row 73 only has one value carried over +dt <- row_replace(dt, 74, 73, 74) # Not LOCF + +dt_true <- as_tibble(as_epi_archive2(dt, compactify = TRUE)$DT) +dt_false <- as_tibble(as_epi_archive2(dt, compactify = FALSE)$DT) +dt_null <- suppressWarnings(as_tibble(as_epi_archive2(dt, compactify = NULL)$DT)) + +test_that("Warning for LOCF with compactify as NULL", { + expect_warning(as_epi_archive2(dt, compactify = NULL)) +}) + +test_that("No warning when there is no LOCF", { + expect_warning(as_epi_archive2(dt[1:5], compactify = NULL), NA) +}) + +test_that("LOCF values are ignored with compactify=FALSE", { + expect_identical(nrow(dt), nrow(dt_false)) +}) + +test_that("LOCF values are taken out with compactify=TRUE", { + dt_test <- as_tibble(as_epi_archive2(dt[-c(21, 22, 40), ], compactify = FALSE)$DT) + + expect_identical(dt_true, dt_null) + expect_identical(dt_null, dt_test) +}) + +test_that("as_of produces the same results with compactify=TRUE as with compactify=FALSE", { + ea_true <- as_epi_archive2(dt, compactify = TRUE) + ea_false <- as_epi_archive2(dt, compactify = FALSE) + + # Row 22, an LOCF row corresponding to the latest version, is omitted in + # ea_true + latest_version <- max(ea_false$DT$version) + as_of_true <- as_of(ea_true, latest_version) + as_of_false <- as_of(ea_false, latest_version) + + expect_identical(as_of_true, as_of_false) +}) + +test_that("compactify does not alter the default clobberable and observed version bounds", { + x <- tibble::tibble( + geo_value = "geo1", + time_value = as.Date("2000-01-01"), + version = as.Date("2000-01-01") + 1:5, + value = 42L + ) + ea_true <- as_epi_archive2(x, compactify = TRUE) + ea_false <- as_epi_archive2(x, compactify = FALSE) + # We say that we base the bounds on the user's `x` arg. We might mess up or + # change our minds and base things on the `DT` field (or a temporary `DT` + # variable, post-compactify) instead. Check that this test would trigger + # in that case: + expect_true(max(ea_true$DT$version) != max(ea_false$DT$version)) + # The actual test: + expect_identical(ea_true$clobberable_versions_start, ea_false$clobberable_versions_start) + expect_identical(ea_true$versions_end, ea_false$versions_end) +}) diff --git a/tests/testthat/test-epix_fill_through_version_new.R b/tests/testthat/test-epix_fill_through_version_new.R new file mode 100644 index 000000000..2b76a851f --- /dev/null +++ b/tests/testthat/test-epix_fill_through_version_new.R @@ -0,0 +1,109 @@ +test_that("epix_fill_through_version2 mirrors input when it is sufficiently up to date", { + ea_orig <- as_epi_archive2(data.table::data.table( + geo_value = "g1", time_value = as.Date("2020-01-01"), + version = 1:5, value = 1:5 + )) + some_earlier_observed_version <- 2L + ea_trivial_fill_na1 <- epix_fill_through_version2(ea_orig, some_earlier_observed_version, "na") + ea_trivial_fill_na2 <- epix_fill_through_version2(ea_orig, ea_orig$versions_end, "na") + ea_trivial_fill_locf <- epix_fill_through_version2(ea_orig, some_earlier_observed_version, "locf") + # Below, we want R6 objects to be compared based on contents rather than + # addresses. We appear to get this with `expect_identical` in `testthat` + # edition 3, which is based on `waldo::compare` rather than `base::identical`; + # `waldo::compare` in waldo >=0.3.1 appears (as of 0.4.0) to compare R6 + # objects by contents rather than address (in a way that is tested but maybe + # not guaranteed via user docs). Use `testthat::local_edition` to ensure we + # use testthat edition 3 here (use `testthat::` to prevent ambiguity with + # `readr`). + testthat::local_edition(3) + expect_identical(ea_orig, ea_trivial_fill_na1) + expect_identical(ea_orig, ea_trivial_fill_na2) + expect_identical(ea_orig, ea_trivial_fill_locf) +}) + +test_that("epix_fill_through_version2 can extend observed versions, gives expected `as_of`s", { + ea_orig <- as_epi_archive2(data.table::data.table( + geo_value = "g1", + time_value = as.Date("2020-01-01") + c(rep(0L, 5L), 1L), + version = c(1:5, 2L), + value = 1:6 + )) + first_unobserved_version <- 6L + later_unobserved_version <- 10L + ea_fill_na <- epix_fill_through_version2(ea_orig, later_unobserved_version, "na") + ea_fill_locf <- epix_fill_through_version2(ea_orig, later_unobserved_version, "locf") + + # We use testthat edition 3 features here, passing `ignore_attr` to + # `waldo::compare`. Ensure we are using edition 3: + testthat::local_edition(3) + withCallingHandlers( + { + expect_identical(ea_fill_na$versions_end, later_unobserved_version) + expect_identical(tibble::as_tibble(as_of(ea_fill_na, first_unobserved_version)), + tibble::tibble(geo_value = "g1", time_value = as.Date("2020-01-01") + 0:1, value = rep(NA_integer_, 2L)), + ignore_attr = TRUE + ) + expect_identical(ea_fill_locf$versions_end, later_unobserved_version) + expect_identical( + as_of(ea_fill_locf, first_unobserved_version), + as_of(ea_fill_locf, ea_orig$versions_end) %>% + { + attr(., "metadata")$as_of <- first_unobserved_version + . + } + ) + }, + epiprocess__snapshot_as_of_clobberable_version = function(wrn) invokeRestart("muffleWarning") + ) +}) + +test_that("epix_fill_through_version2 does not mutate x", { + for (ea_orig in list( + # vanilla case + as_epi_archive2(data.table::data.table( + geo_value = "g1", time_value = as.Date("2020-01-01"), + version = 1:5, value = 1:5 + )), + # data.table unique yielding original DT by reference special case (maybe + # having only 1 row is the trigger? having no revisions of initial values + # doesn't seem sufficient to trigger) + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, value = 10L)) + )) { + # We want to perform a strict comparison of the contents of `ea_orig` before + # and `ea_orig` after. `clone` + `expect_identical` based on waldo would + # sort of work, but we might want something stricter. `as.list` + + # `identical` plus a check of the DT seems to do the trick. + ea_orig_before_as_list <- as.list(ea_orig) + ea_orig_DT_before_copy <- data.table::copy(ea_orig$DT) + some_unobserved_version <- 8L + # + ea_fill_na <- epix_fill_through_version2(ea_orig, some_unobserved_version, "na") + ea_orig_after_as_list <- as.list(ea_orig) + # use identical, not expect_identical, for the R6-as-list test; latter isn't as strict + expect_true(identical(ea_orig_before_as_list, ea_orig_after_as_list)) + expect_identical(ea_orig_DT_before_copy, ea_orig$DT) + # + ea_fill_locf <- epix_fill_through_version2(ea_orig, some_unobserved_version, "locf") + ea_orig_after_as_list <- as.list(ea_orig) + expect_true(identical(ea_orig_before_as_list, ea_orig_after_as_list)) + expect_identical(ea_orig_DT_before_copy, ea_orig$DT) + } +}) + +test_that("epix_fill_through_version return with expected visibility", { + ea <- as_epi_archive(data.table::data.table( + geo_value = "g1", time_value = as.Date("2020-01-01"), + version = 1:5, value = 1:5 + )) + expect_true(withVisible(epix_fill_through_version(ea, 10L, "na"))[["visible"]]) +}) + +test_that("epix_fill_through_version2 returns same key & doesn't mutate old DT or its key", { + ea <- as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, value = 10L)) + old_DT <- ea$DT + old_DT_copy <- data.table::copy(old_DT) + old_key <- data.table::key(ea$DT) + expect_identical(data.table::key(epix_fill_through_version2(ea, 5L, "na")$DT), old_key) + expect_identical(data.table::key(epix_fill_through_version2(ea, 5L, "locf")$DT), old_key) + expect_identical(data.table::key(ea$DT), old_key) +}) diff --git a/tests/testthat/test-epix_merge_new.R b/tests/testthat/test-epix_merge_new.R new file mode 100644 index 000000000..594b7b5e0 --- /dev/null +++ b/tests/testthat/test-epix_merge_new.R @@ -0,0 +1,228 @@ +test_that("epix_merge requires forbids on invalid `y`", { + ea <- archive_cases_dv_subset$DT %>% + as_epi_archive2() %>% + clone() %>% + suppressWarnings() + expect_error(epix_merge2(ea, data.frame(x = 1))) +}) + +test_that("epix_merge merges and carries forward updates properly", { + x <- as_epi_archive2( + data.table::as.data.table( + tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, + # same version set for x and y + "g1", 1L, 1:3, paste0("XA", 1:3), + # versions of x surround those of y + this measurement has + # max update version beyond some others + "g1", 2L, 1:5, paste0("XB", 1:5), + # mirror case + "g1", 3L, 2L, paste0("XC", 2L), + # x has 1 version, y has 0 + "g1", 4L, 1L, paste0("XD", 1L), + # non-NA values that should be carried forward + # (version-wise LOCF) in other versions, plus NAs that + # should (similarly) be carried forward as NA (latter + # wouldn't work with an ordinary merge + post-processing + # with `data.table::nafill`) + "g1", 6L, c(1L, 3L, 5L), paste0("XE", c(1L, NA, 5L)) + ) %>% + tidyr::unchop(c(version, x_value)) %>% + dplyr::mutate(dplyr::across(c(x_value), ~ dplyr::if_else(grepl("NA", .x), NA_character_, .x))) + ) + ) + y <- as_epi_archive2( + data.table::as.data.table( + tibble::tribble( + ~geo_value, ~time_value, ~version, ~y_value, + "g1", 1L, 1:3, paste0("YA", 1:3), + "g1", 2L, 2L, paste0("YB", 2L), + "g1", 3L, 1:5, paste0("YC", 1:5), + "g1", 5L, 1L, paste0("YD", 1L), + "g1", 6L, 1:5, paste0("YE", 1:5), + ) %>% + tidyr::unchop(c(version, y_value)) %>% + dplyr::mutate(dplyr::across(c(y_value), ~ dplyr::if_else(grepl("NA", .x), NA_character_, .x))) + ) + ) + xy <- epix_merge2(x, y) + xy_expected <- as_epi_archive2( + data.table::as.data.table( + tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, ~y_value, + "g1", 1L, 1:3, paste0("XA", 1:3), paste0("YA", 1:3), + "g1", 2L, 1:5, paste0("XB", 1:5), paste0("YB", c(NA, 2L, 2L, 2L, 2L)), + "g1", 3L, 1:5, paste0("XC", c(NA, 2L, 2L, 2L, 2L)), paste0("YC", 1:5), + "g1", 4L, 1L, paste0("XD", 1L), paste0("YD", NA), + "g1", 5L, 1L, paste0("XD", NA), paste0("YD", 1L), + "g1", 6L, 1:5, paste0("XE", c(1L, 1L, NA, NA, 5L)), paste0("YE", 1:5), + ) %>% + tidyr::unchop(c(version, x_value, y_value)) %>% + dplyr::mutate(dplyr::across(c(x_value, y_value), ~ dplyr::if_else(grepl("NA", .x), NA_character_, .x))) + ) + ) + # We rely on testthat edition 3 expect_identical using waldo, not identical. See + # test-epix_fill_through_version.R comments for details. + testthat::local_edition(3) + expect_identical(xy, xy_expected) +}) + +test_that("epix_merge forbids and warns on metadata and naming issues", { + expect_error( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = "tx", time_value = 1L, version = 1L, x_value = 1L)), + as_epi_archive2(tibble::tibble(geo_value = "us", time_value = 1L, version = 5L, y_value = 2L)) + ), + regexp = "must have the same.*geo_type" + ) + expect_error( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = "pa", time_value = 1L, version = 1L, x_value = 1L)), + as_epi_archive2(tibble::tibble(geo_value = "pa", time_value = as.Date("2020-01-01"), version = 5L, y_value = 2L)) + ), + regexp = "must have the same.*time_type" + ) + expect_error( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, value = 1L)), + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, value = 2L)) + ), + regexp = "overlapping.*names" + ) + expect_warning( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, x_value = 1L), + additional_metadata = list("updates_fetched" = lubridate::ymd_hms("2022-05-01 16:00:00", tz = "UTC")) + ), + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, y_value = 2L)) + ), + regexp = "x\\$additional_metadata", + class = "epiprocess__epix_merge_ignores_additional_metadata" + ) + expect_warning( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, x_value = 1L)), + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, y_value = 2L), + additional_metadata = list("updates_fetched" = lubridate::ymd_hms("2022-05-01 16:00:00", tz = "UTC")) + ) + ), + regexp = "y\\$additional_metadata", + class = "epiprocess__epix_merge_ignores_additional_metadata" + ) +}) + +# use `local` to prevent accidentally using the x, y, xy bindings here +# elsewhere, while allowing reuse across a couple tests +local({ + x <- as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, x_value = 1L), + clobberable_versions_start = 1L, versions_end = 10L + ) + y <- as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, y_value = 2L), + clobberable_versions_start = 3L, versions_end = 10L + ) + xy <- epix_merge2(x, y) + test_that("epix_merge considers partially-clobberable row to be clobberable", { + expect_identical(xy$clobberable_versions_start, 1L) + }) + test_that("epix_merge result uses versions_end metadata not max version val", { + expect_identical(xy$versions_end, 10L) + }) +}) + +local({ + x <- as_epi_archive2( + tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, x_value = 10L), + clobberable_versions_start = 1L, + versions_end = 3L + ) + y <- as_epi_archive2( + tibble::tibble(geo_value = 1L, time_value = 1L, version = 5L, y_value = 20L), + clobberable_versions_start = 1L + ) + test_that('epix_merge forbids on sync default or "forbid"', { + expect_error(epix_merge2(x, y), + class = "epiprocess__epix_merge_unresolved_sync" + ) + expect_error(epix_merge2(x, y, sync = "forbid"), + class = "epiprocess__epix_merge_unresolved_sync" + ) + }) + test_that('epix_merge sync="na" works', { + expect_equal( + epix_merge2(x, y, sync = "na"), + as_epi_archive2(tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, ~y_value, + 1L, 1L, 1L, 10L, NA_integer_, # x updated, y not observed yet + 1L, 1L, 4L, NA_integer_, NA_integer_, # NA-ing out x, y not observed yet + 1L, 1L, 5L, NA_integer_, 20L, # x still NA, y updated + # (we should not have a y vals -> NA update here; version 5 should be + # the `versions_end` of the result) + ), clobberable_versions_start = 1L) + ) + }) + test_that('epix_merge sync="locf" works', { + expect_equal( + epix_merge2(x, y, sync = "locf"), + as_epi_archive2(tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, ~y_value, + 1L, 1L, 1L, 10L, NA_integer_, # x updated, y not observed yet + 1L, 1L, 5L, 10L, 20L, # x LOCF'd, y updated + ), clobberable_versions_start = 1L) + ) + }) + test_that('epix_merge sync="truncate" works', { + expect_equal( + epix_merge2(x, y, sync = "truncate"), + as_epi_archive2(tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, ~y_value, + 1L, 1L, 1L, 10L, NA_integer_, # x updated, y not observed yet + # y's update beyond x's last update has been truncated + ), clobberable_versions_start = 1L, versions_end = 3L) + ) + }) + x_no_conflict <- as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, x_value = 10L)) + y_no_conflict <- as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = 1L, y_value = 20L)) + xy_no_conflict_expected <- as_epi_archive2(tibble::tribble( + ~geo_value, ~time_value, ~version, ~x_value, ~y_value, + 1L, 1L, 1L, 10L, 20L, # x updated, y not observed yet + )) + test_that('epix_merge sync="forbid" on no-conflict works', { + expect_equal( + epix_merge2(x_no_conflict, y_no_conflict, sync = "forbid"), + xy_no_conflict_expected + ) + }) + test_that('epix_merge sync="na" on no-conflict works', { + # This test is the main reason for these no-conflict tests. We want to make + # sure that we don't add an unnecessary NA-ing-out version beyond a common + # versions_end. + expect_equal( + epix_merge2(x_no_conflict, y_no_conflict, sync = "na"), + xy_no_conflict_expected + ) + }) + test_that('epix_merge sync="locf" on no-conflict works', { + expect_equal( + epix_merge2(x_no_conflict, y_no_conflict, sync = "locf"), + xy_no_conflict_expected + ) + }) + test_that('epix_merge sync="truncate" on no-conflict works', { + expect_equal( + epix_merge2(x_no_conflict, y_no_conflict, sync = "truncate"), + xy_no_conflict_expected + ) + }) +}) + + +test_that('epix_merge sync="na" balks if do not know next_after', { + expect_error( + epix_merge2( + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = as.POSIXct(as.Date("2020-01-01")), x_value = 10L)), + as_epi_archive2(tibble::tibble(geo_value = 1L, time_value = 1L, version = as.POSIXct(as.Date("2020-01-02")), y_value = 20L)), + sync = "na" + ), + regexp = "no applicable method.*next_after" + ) +}) diff --git a/tests/testthat/test-epix_slide_new.R b/tests/testthat/test-epix_slide_new.R new file mode 100644 index 000000000..f748231a6 --- /dev/null +++ b/tests/testthat/test-epix_slide_new.R @@ -0,0 +1,810 @@ +library(dplyr) + +test_that("epix_slide2 only works on an epi_archive", { + expect_error(epix_slide2(data.frame(x = 1))) +}) + +x <- tibble::tribble( + ~version, ~time_value, ~binary, + 4, c(1:3), 2^(1:3), + 5, c(1:2, 4), 2^(4:6), + 6, c(1:2, 4:5), 2^(7:10), + 7, 2:6, 2^(11:15) +) %>% + tidyr::unnest(c(time_value, binary)) + +xx <- bind_cols(geo_value = rep("x", 15), x) %>% + as_epi_archive2() + +test_that("epix_slide2 works as intended", { + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ sum(.x$binary), + before = 2, + new_col_name = "sum_binary" + ) + + xx2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + sum_binary = c( + 2^3 + 2^2, + 2^6 + 2^3, + 2^10 + 2^9, + 2^15 + 2^14 + ) + ) %>% + group_by(geo_value) + + expect_identical(xx1, xx2) # * + + xx3 <- xx %>% + group_by( + dplyr::across(dplyr::all_of("geo_value")) + ) %>% + slide( + f = ~ sum(.x$binary), + before = 2, + new_col_name = "sum_binary" + ) + + expect_identical(xx1, xx3) # This and * imply xx2 and xx3 are identical + + # function interface + xx4 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2(f = function(x, gk, rtv) { + tibble::tibble(sum_binary = sum(x$binary)) + }, before = 2, names_sep = NULL) + + expect_identical(xx1, xx4) + + # tidyeval interface + xx5 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + sum_binary = sum(binary), + before = 2 + ) + + expect_identical(xx1, xx5) +}) + +test_that("epix_slide2 works as intended with `as_list_col=TRUE`", { + xx_dfrow1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ data.frame(bin_sum = sum(.x$binary)), + before = 2, + as_list_col = TRUE + ) + + xx_dfrow2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = + c( + 2^3 + 2^2, + 2^6 + 2^3, + 2^10 + 2^9, + 2^15 + 2^14 + ) %>% + purrr::map(~ data.frame(bin_sum = .x)) + ) %>% + group_by(geo_value) + + expect_identical(xx_dfrow1, xx_dfrow2) # * + + xx_dfrow3 <- xx %>% + group_by(dplyr::across(dplyr::all_of("geo_value"))) %>% + slide( + f = ~ data.frame(bin_sum = sum(.x$binary)), + before = 2, + as_list_col = TRUE + ) + + expect_identical(xx_dfrow1, xx_dfrow3) # This and * Imply xx_dfrow2 and xx_dfrow3 are identical + + xx_df1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ data.frame(bin = .x$binary), + before = 2, + as_list_col = TRUE + ) + + xx_df2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = + list( + c(2^3, 2^2), + c(2^6, 2^3), + c(2^10, 2^9), + c(2^15, 2^14) + ) %>% + purrr::map(~ data.frame(bin = rev(.x))) + ) %>% + group_by(geo_value) + + expect_identical(xx_df1, xx_df2) + + xx_scalar1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ sum(.x$binary), + before = 2, + as_list_col = TRUE + ) + + xx_scalar2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = + list( + 2^3 + 2^2, + 2^6 + 2^3, + 2^10 + 2^9, + 2^15 + 2^14 + ) + ) %>% + group_by(geo_value) + + expect_identical(xx_scalar1, xx_scalar2) + + xx_vec1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ .x$binary, + before = 2, + as_list_col = TRUE + ) + + xx_vec2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = + list( + c(2^3, 2^2), + c(2^6, 2^3), + c(2^10, 2^9), + c(2^15, 2^14) + ) %>% + purrr::map(rev) + ) %>% + group_by(geo_value) + + expect_identical(xx_vec1, xx_vec2) +}) + +test_that("epix_slide2 `before` validation works", { + expect_error( + slide(xx, f = ~ sum(.x$binary)), + "`before` is required" + ) + expect_error( + slide(xx, f = ~ sum(.x$binary), before = NA), + "Assertion on 'before' failed: May not be NA" + ) + expect_error( + slide(xx, f = ~ sum(.x$binary), before = -1), + "Assertion on 'before' failed: Element 1 is not >= 0" + ) + expect_error(slide(xx, f = ~ sum(.x$binary), before = 1.5), + regexp = "before", + class = "vctrs_error_incompatible_type" + ) + # We might want to allow this at some point (issue #219): + expect_error(slide(xx, f = ~ sum(.x$binary), before = Inf), + regexp = "before", + class = "vctrs_error_incompatible_type" + ) + # (wrapper shouldn't introduce a value:) + expect_error(epix_slide2(xx, f = ~ sum(.x$binary)), "`before` is required") + # These `before` values should be accepted: + expect_error( + slide(xx, f = ~ sum(.x$binary), before = 0), + NA + ) + expect_error( + slide(xx, f = ~ sum(.x$binary), before = 2L), + NA + ) + expect_error( + slide(xx, f = ~ sum(.x$binary), before = 365000), + NA + ) +}) + +test_that("quosure passing issue in epix_slide2 is resolved + other potential issues", { + # (First part adapted from @examples) + time_values <- seq(as.Date("2020-06-01"), + as.Date("2020-06-02"), + by = "1 day" + ) + # We only have one non-version, non-time key in the example archive. Add + # another so that we don't accidentally pass tests due to accidentally + # matching the default grouping. + ea <- as_epi_archive2( + archive_cases_dv_subset$DT %>% + dplyr::mutate(modulus = seq_len(nrow(.)) %% 5L), + other_keys = "modulus", + compactify = TRUE + ) + reference_by_modulus <- ea %>% + group_by(modulus) %>% + epix_slide2( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ) + reference_by_neither <- ea %>% + group_by() %>% + epix_slide2( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ) + # test the passing-something-that-must-be-enquosed behavior: + # + # (S3 group_by behavior for this case is the `reference_by_modulus`) + expect_identical( + ea %>% group_by(modulus) %>% slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + # test the .data pronoun behavior: + expect_identical( + epix_slide2( + x = ea %>% group_by(.data$modulus), + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + expect_identical( + ea %>% group_by(.data$modulus) %>% slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + # test the passing across-all-of-string-literal behavior: + expect_identical( + epix_slide2( + x = ea %>% group_by(dplyr::across(all_of("modulus"))), + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + expect_identical( + ea %>% group_by(across(all_of("modulus"))) %>% slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + # test the passing-across-all-of-string-var behavior: + my_group_by <- "modulus" + expect_identical( + epix_slide2( + x = ea %>% group_by(dplyr::across(tidyselect::all_of(my_group_by))), + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + expect_identical( + ea %>% group_by(dplyr::across(tidyselect::all_of(my_group_by))) %>% slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_modulus + ) + # test the default behavior (default in this case should just be grouping by neither): + expect_identical( + epix_slide2( + x = ea, + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_neither + ) + expect_identical( + ea %>% slide( + f = ~ mean(.x$case_rate_7d_av), + before = 2, + ref_time_values = time_values, + new_col_name = "case_rate_3d_av" + ), + reference_by_neither + ) +}) + +ea <- tibble::tribble( + ~version, ~time_value, ~binary, + 2, 1:1, 2^(1:1), + 3, 1:2, 2^(2:1), + 4, 1:3, 2^(3:1), + 5, 1:4, 2^(4:1), + 6, 1:5, 2^(5:1), + 7, 1:6, 2^(6:1) +) %>% + tidyr::unnest(c(time_value, binary)) %>% + mutate(geo_value = "x") %>% + as_epi_archive2() + +test_that("epix_slide2 with all_versions option has access to all older versions", { + library(data.table) + # Make sure we're using testthat edition 3, where `expect_identical` doesn't + # actually mean `base::identical` but something more content-based using + # `waldo` package: + testthat::local_edition(3) + + slide_fn <- function(x, gk, rtv) { + return(tibble( + n_versions = length(unique(x$DT$version)), + n_row = nrow(x$DT), + dt_class1 = class(x$DT)[[1L]], + dt_key = list(key(x$DT)) + )) + } + + ea_orig_mirror <- ea %>% clone(deep = TRUE) + ea_orig_mirror$DT <- copy(ea_orig_mirror$DT) + + result1 <- ea %>% + group_by() %>% + epix_slide2( + f = slide_fn, + before = 10^3, + names_sep = NULL, + all_versions = TRUE + ) + + expect_true(inherits(result1, "tbl_df")) + + result2 <- tibble::tribble( + ~time_value, ~n_versions, ~n_row, ~dt_class1, ~dt_key, + 2, 1L, sum(1:1), "data.table", key(ea$DT), + 3, 2L, sum(1:2), "data.table", key(ea$DT), + 4, 3L, sum(1:3), "data.table", key(ea$DT), + 5, 4L, sum(1:4), "data.table", key(ea$DT), + 6, 5L, sum(1:5), "data.table", key(ea$DT), + 7, 6L, sum(1:6), "data.table", key(ea$DT), + ) + + expect_identical(result1, result2) # * + + result3 <- ea %>% + group_by() %>% + slide( + f = slide_fn, + before = 10^3, + names_sep = NULL, + all_versions = TRUE + ) + + expect_identical(result1, result3) # This and * Imply result2 and result3 are identical + + # formula interface + result4 <- ea %>% + group_by() %>% + epix_slide2( + f = ~ slide_fn(.x, .y), + before = 10^3, + names_sep = NULL, + all_versions = TRUE + ) + + expect_identical(result1, result4) # This and * Imply result2 and result4 are identical + + # tidyeval interface + result5 <- ea %>% + group_by() %>% + epix_slide2( + data = slide_fn( + .x, + stop("slide_fn doesn't use group key, no need to prepare it") + ), + before = 10^3, + names_sep = NULL, + all_versions = TRUE + ) + + expect_identical(result1, result5) # This and * Imply result2 and result5 are identical + expect_identical(ea, ea_orig_mirror) # We shouldn't have mutated ea +}) + +test_that("as_of and epix_slide2 with long enough window are compatible", { + library(data.table) + testthat::local_edition(3) + + # For all_versions = FALSE: + + f1 <- function(x, gk, rtv) { + tibble( + diff_mean = mean(diff(x$binary)) + ) + } + ref_time_value1 <- 5 + + expect_identical( + ea %>% as_of(ref_time_value1) %>% f1() %>% mutate(time_value = ref_time_value1, .before = 1L), + ea %>% slide(f1, before = 1000L, ref_time_values = ref_time_value1, names_sep = NULL) + ) + + # For all_versions = TRUE: + + f2 <- function(x, gk, rtv) { + x %>% + # extract time&version-lag-1 data: + epix_slide2( + function(subx, subgk, rtv) { + tibble(data = list( + subx %>% + filter(time_value == attr(subx, "metadata")$as_of - 1) %>% + rename(real_time_value = time_value, lag1 = binary) + )) + }, + before = 1, names_sep = NULL + ) %>% + # assess as nowcast: + unnest(data) %>% + inner_join(x %>% as_of(x$versions_end), by = setdiff(key(x$DT), c("version"))) %>% + summarize(mean_abs_delta = mean(abs(binary - lag1))) + } + ref_time_value2 <- 5 + + expect_identical( + ea %>% as_of(ref_time_value2, all_versions = TRUE) %>% f2() %>% mutate(time_value = ref_time_value2, .before = 1L), + ea %>% slide(f2, before = 1000L, ref_time_values = ref_time_value2, all_versions = TRUE, names_sep = NULL) + ) + + # Test the same sort of thing when grouping by geo in an archive with multiple geos. + ea_multigeo <- ea %>% clone() + ea_multigeo$DT <- rbind( + ea_multigeo$DT, + copy(ea_multigeo$DT)[, geo_value := "y"][, binary := -binary][] + ) + setkeyv(ea_multigeo$DT, key(ea$DT)) + + expect_identical( + ea_multigeo %>% + group_by(geo_value) %>% + epix_slide2(f2, before = 1000L, ref_time_values = ref_time_value2, all_versions = TRUE, names_sep = NULL) %>% + filter(geo_value == "x"), + ea %>% # using `ea` here is like filtering `ea_multigeo` to `geo_value=="x"` + epix_as_of2(ref_time_value2, all_versions = TRUE) %>% + f2() %>% + transmute(geo_value = "x", time_value = ref_time_value2, mean_abs_delta) %>% + group_by(geo_value) + ) +}) + +test_that("epix_slide2 `f` is passed an ungrouped `epi_archive` when `all_versions=TRUE`", { + slide_fn <- function(x, gk, rtv) { + expect_true(is_epi_archive2(x)) + return(NA) + } + + ea %>% + group_by() %>% + epix_slide2( + f = slide_fn, + before = 1, + ref_time_values = 5, + new_col_name = "out", + all_versions = TRUE + ) +}) + +test_that("epix_slide2 with all_versions option works as intended", { + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~ sum(.x$DT$binary), + before = 2, + new_col_name = "sum_binary", + all_versions = TRUE + ) + + xx2 <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + sum_binary = c( + 2^3 + 2^2, + 2^6 + 2^3, + 2^10 + 2^9 + 2^6, + 2^15 + 2^14 + 2^10 + ) + ) %>% + group_by(geo_value) + + expect_identical(xx1, xx2) # * + + xx3 <- xx %>% + group_by(dplyr::across(dplyr::all_of("geo_value"))) %>% + slide( + f = ~ sum(.x$DT$binary), + before = 2, + new_col_name = "sum_binary", + all_versions = TRUE + ) + + expect_identical(xx1, xx3) # This and * Imply xx2 and xx3 are identical +}) + +# XXX currently, we're using a stopgap measure of having `epix_slide2` always +# output a (grouped/ungrouped) tibble while we think about the class, columns, +# and attributes of `epix_slide2` output more carefully. We might bring this test +# back depending on the decisions there: +# +# test_that("`epix_slide2` uses `versions_end` as a resulting `epi_df`'s `as_of`", { +# ea_updated_stale = ea$clone() +# ea_updated_stale$versions_end <- ea_updated_stale$versions_end + 3 # (dbl) +# # +# expect_identical( +# ea_updated_stale %>% +# group_by(geo_value) %>% +# epix_slide2(~ slice_head(.x, n = 1L), before = 10L) %>% +# ungroup() %>% +# attr("metadata") %>% +# .$as_of, +# 10 +# ) +# }) + +test_that("epix_slide2 works with 0-row computation outputs", { + epix_slide_empty <- function(ea, ...) { + ea %>% + epix_slide2(before = 5L, ..., function(x, gk, rtv) { + tibble::tibble() + }) + } + expect_identical( + ea %>% + epix_slide_empty(), + tibble::tibble( + time_value = ea$DT$version[integer(0)] + ) + ) + expect_identical( + ea %>% + group_by(geo_value) %>% + epix_slide_empty(), + tibble::tibble( + geo_value = ea$DT$geo_value[integer(0)], + time_value = ea$DT$version[integer(0)] + ) %>% + # new_epi_df(geo_type = ea$geo_type, time_type = ea$time_type, + # as_of = ea$versions_end) %>% + group_by(geo_value) + ) + # with `all_versions=TRUE`, we have something similar but never get an + # `epi_df`: + expect_identical( + ea %>% + epix_slide_empty(all_versions = TRUE), + tibble::tibble( + time_value = ea$DT$version[integer(0)] + ) + ) + expect_identical( + ea %>% + group_by(geo_value) %>% + epix_slide_empty(all_versions = TRUE), + tibble::tibble( + geo_value = ea$DT$geo_value[integer(0)], + time_value = ea$DT$version[integer(0)] + ) %>% + group_by(geo_value) + ) +}) + +# test_that("epix_slide grouped by geo can produce `epi_df` output", { +# # This is a characterization test. Not sure we actually want this behavior; +# # https://github.com/cmu-delphi/epiprocess/pull/290#issuecomment-1489099157 +# expect_identical( +# ea %>% +# group_by(geo_value) %>% +# epix_slide(before = 5L, function(x,g) { +# tibble::tibble(value = 42) +# }, names_sep = NULL), +# tibble::tibble( +# geo_value = "x", +# time_value = epix_slide_ref_time_values_default(ea), +# value = 42 +# ) %>% +# new_epi_df(as_of = ea$versions_end) +# ) +# }) + +test_that("epix_slide alerts if the provided f doesn't take enough args", { + f_xgt <- function(x, g, t) dplyr::tibble(value = mean(x$binary), count = length(x$binary)) + # If `regexp` is NA, asserts that there should be no errors/messages. + expect_error(epix_slide2(xx, f = f_xgt, before = 2L), regexp = NA) + expect_warning(epix_slide2(xx, f = f_xgt, before = 2L), regexp = NA) + + f_x_dots <- function(x, ...) dplyr::tibble(value = mean(x$binary), count = length(x$binary)) + expect_warning(epix_slide2(xx, f_x_dots, before = 2L), + class = "epiprocess__assert_sufficient_f_args__mandatory_f_args_passed_to_f_dots" + ) +}) + +test_that("epix_slide2 computation via formula can use ref_time_value", { + xx_ref <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = c(4, 5, 6, 7) + ) %>% + group_by(geo_value) + + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~.ref_time_value, + before = 2 + ) + + expect_identical(xx1, xx_ref) + + xx2 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~.z, + before = 2 + ) + + expect_identical(xx2, xx_ref) + + xx3 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = ~..3, + before = 2 + ) + + expect_identical(xx3, xx_ref) +}) + +test_that("epix_slide2 computation via function can use ref_time_value", { + xx_ref <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = c(4, 5, 6, 7) + ) %>% + group_by(geo_value) + + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + f = function(x, g, t) t, + before = 2 + ) + + expect_identical(xx1, xx_ref) +}) + +test_that("epix_slide2 computation via dots can use ref_time_value and group", { + # ref_time_value + xx_ref <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = c(4, 5, 6, 7) + ) %>% + group_by(geo_value) + + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + slide_value = .ref_time_value + ) + + expect_identical(xx1, xx_ref) + + # group_key + xx_ref <- tibble( + geo_value = rep("x", 4), + time_value = c(4, 5, 6, 7), + slide_value = "x" + ) %>% + group_by(geo_value) + + # Use group_key column + xx3 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + slide_value = .group_key$geo_value + ) + + expect_identical(xx3, xx_ref) + + # Use entire group_key object + expect_error( + xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + slide_value = nrow(.group_key) + ), + NA + ) +}) + +test_that("epix_slide2 computation via dots outputs the same result using col names and the data var", { + xx_ref <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + sum_binary = sum(time_value) + ) + + xx1 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + sum_binary = sum(.x$time_value) + ) + + expect_identical(xx1, xx_ref) + + xx2 <- xx %>% + group_by(.data$geo_value) %>% + epix_slide2( + before = 2, + sum_binary = sum(.data$time_value) + ) + + expect_identical(xx2, xx_ref) +}) + +test_that("`epix_slide2` doesn't decay date output", { + expect_true( + xx$DT %>% + as_tibble() %>% + mutate(across(c(time_value, version), ~ as.Date("2000-01-01") + .x - 1L)) %>% + as_epi_archive2() %>% + epix_slide2(before = 5L, ~ attr(.x, "metadata")$as_of) %>% + `[[`("slide_value") %>% + inherits("Date") + ) +}) + +test_that("`epix_slide2` can access objects inside of helper functions", { + helper <- function(archive_haystack, time_value_needle) { + archive_haystack %>% epix_slide2(has_needle = time_value_needle %in% time_value, before = 365000L) + } + expect_error( + helper(suppressWarnings(as_epi_archive2(archive_cases_dv_subset$DT)), as.Date("2021-01-01")), + NA + ) + expect_error( + helper(xx, 3L), + NA + ) +}) diff --git a/tests/testthat/test-grouped_epi_archive_new.R b/tests/testthat/test-grouped_epi_archive_new.R new file mode 100644 index 000000000..8f0133b99 --- /dev/null +++ b/tests/testthat/test-grouped_epi_archive_new.R @@ -0,0 +1,104 @@ +test_that("Grouping, regrouping, and ungrouping archives works as intended", { + # From an example: + library(dplyr) + toy_archive <- + tribble( + ~geo_value, ~age_group, ~time_value, ~version, ~value, + "us", "adult", "2000-01-01", "2000-01-02", 121, + "us", "pediatric", "2000-01-02", "2000-01-03", 5, # (addition) + "us", "adult", "2000-01-01", "2000-01-03", 125, # (revision) + "us", "adult", "2000-01-02", "2000-01-03", 130 # (addition) + ) %>% + mutate( + age_group = ordered(age_group, c("pediatric", "adult")), + time_value = as.Date(time_value), + version = as.Date(version) + ) %>% + as_epi_archive2(other_keys = "age_group") + + # Ensure that we're using testthat edition 3's idea of "identical", which is + # not as strict as `identical`: + testthat::local_edition(3) + + # Test equivalency claims in example: + by_both_keys <- toy_archive %>% group_by(geo_value, age_group) + expect_identical( + by_both_keys, + toy_archive %>% group_by(geo_value) %>% group_by(age_group, .add = TRUE) + ) + grouping_cols <- c("geo_value", "age_group") + expect_identical( + by_both_keys, + toy_archive %>% group_by(across(all_of(grouping_cols))) + ) + + expect_identical( + toy_archive %>% group_by(geo_value), + toy_archive %>% group_by(geo_value, age_group) %>% ungroup(age_group) + ) + + # Test `.drop` behavior: + expect_error(toy_archive %>% group_by(.drop = "bogus"), + regexp = "Must be of type 'logical', not 'character'" + ) + expect_warning(toy_archive %>% group_by(.drop = FALSE), + class = "epiprocess__group_by_epi_archive__drop_FALSE_no_factors" + ) + expect_warning(toy_archive %>% group_by(geo_value, .drop = FALSE), + class = "epiprocess__group_by_epi_archive__drop_FALSE_no_factors" + ) + expect_warning( + grouped_factor_then_nonfactor <- + toy_archive %>% group_by(age_group, geo_value, .drop = FALSE), + class = "epiprocess__group_by_epi_archive__drop_FALSE_nonfactor_after_factor" + ) + expect_identical( + grouped_factor_then_nonfactor %>% + epix_slide2(before = 10, s = sum(value)), + tibble::tribble( + ~age_group, ~geo_value, ~time_value, ~s, + "pediatric", NA_character_, "2000-01-02", 0, + "adult", "us", "2000-01-02", 121, + "pediatric", "us", "2000-01-03", 5, + "adult", "us", "2000-01-03", 255 + ) %>% + mutate( + age_group = ordered(age_group, c("pediatric", "adult")), + time_value = as.Date(time_value) + ) %>% + # # See + # # https://github.com/cmu-delphi/epiprocess/pull/290#issuecomment-1489099157 + # # and + # # https://github.com/cmu-delphi/epiprocess/pull/311#issuecomment-1535149256 + # # for why this is commented out, pending some design + # # decisions. + # # + # as_epi_df(geo_type = "nation", # bug; want "custom" from NA; issue #242 + # as_of = as.Date("2000-01-03"), + # additional_metadata = list(other_keys = "age_group")) %>% + # # put back in expected order; see issue #166: + # select(age_group, geo_value, time_value, s) %>% + group_by(age_group, geo_value, .drop = FALSE) + ) + expect_identical( + toy_archive %>% + group_by(geo_value, age_group, .drop = FALSE) %>% + epix_slide2(before = 10, s = sum(value)), + tibble::tribble( + ~geo_value, ~age_group, ~time_value, ~s, + "us", "pediatric", "2000-01-02", 0, + "us", "adult", "2000-01-02", 121, + "us", "pediatric", "2000-01-03", 5, + "us", "adult", "2000-01-03", 255 + ) %>% + mutate( + age_group = ordered(age_group, c("pediatric", "adult")), + time_value = as.Date(time_value) + ) %>% + # as_epi_df(as_of = as.Date("2000-01-03"), + # additional_metadata = list(other_keys = "age_group")) %>% + # # put back in expected order; see issue #166: + # select(geo_value, age_group, time_value, s) %>% + group_by(geo_value, age_group, .drop = FALSE) + ) +}) diff --git a/tests/testthat/test-methods-epi_archive_new.R b/tests/testthat/test-methods-epi_archive_new.R new file mode 100644 index 000000000..a267ba58b --- /dev/null +++ b/tests/testthat/test-methods-epi_archive_new.R @@ -0,0 +1,138 @@ +library(dplyr) + +ea <- archive_cases_dv_subset$DT %>% + as_epi_archive2() %>% + clone() %>% + suppressWarnings() + +ea2_data <- tibble::tribble( + ~geo_value, ~time_value, ~version, ~cases, + "ca", "2020-06-01", "2020-06-01", 1, + "ca", "2020-06-01", "2020-06-02", 2, + # + "ca", "2020-06-02", "2020-06-02", 0, + "ca", "2020-06-02", "2020-06-03", 1, + "ca", "2020-06-02", "2020-06-04", 2, + # + "ca", "2020-06-03", "2020-06-03", 1, + # + "ca", "2020-06-04", "2020-06-04", 4, +) %>% + dplyr::mutate(dplyr::across(c(time_value, version), as.Date)) + +# epix_as_of tests +test_that("epix_as_of behaves identically to as_of method", { + expect_identical( + epix_as_of2(ea, max_version = min(ea$DT$version)), + ea %>% as_of(max_version = min(ea$DT$version)) + ) +}) + +test_that("Errors are thrown due to bad as_of inputs", { + # max_version cannot be of string class rather than date class + expect_error(ea %>% as_of("2020-01-01")) + # max_version cannot be later than latest version + expect_error(ea %>% as_of(as.Date("2025-01-01"))) + # max_version cannot be a vector + expect_error(ea %>% as_of(c(as.Date("2020-01-01"), as.Date("2020-01-02")))) +}) + +test_that("Warning against max_version being clobberable", { + # none by default + expect_warning(regexp = NA, ea %>% as_of(max_version = max(ea$DT$version))) + expect_warning(regexp = NA, ea %>% as_of(max_version = min(ea$DT$version))) + # but with `clobberable_versions_start` non-`NA`, yes + ea_with_clobberable <- ea %>% clone() + ea_with_clobberable$clobberable_versions_start <- max(ea_with_clobberable$DT$version) + expect_warning(ea_with_clobberable %>% as_of(max_version = max(ea$DT$version))) + expect_warning(regexp = NA, ea_with_clobberable %>% as_of(max_version = min(ea$DT$version))) +}) + +test_that("as_of properly grabs the data and doesn't mutate key", { + d <- as.Date("2020-06-01") + + ea2 <- ea2_data %>% + as_epi_archive2() + + old_key <- data.table::key(ea2$DT) + + edf_as_of <- ea2 %>% + epix_as_of2(max_version = as.Date("2020-06-03")) + + edf_expected <- as_epi_df(tibble( + geo_value = "ca", + time_value = d + 0:2, + cases = c(2, 1, 1) + ), as_of = as.Date("2020-06-03")) + + expect_equal(edf_as_of, edf_expected, ignore_attr = c(".internal.selfref", "sorted")) + expect_equal(data.table::key(ea2$DT), old_key) +}) + +test_that("Errors are thrown due to bad epix_truncate_versions_after inputs", { + # x must be an archive + expect_error(epix_truncate_versions_after(data.frame(), as.Date("2020-01-01"))) + # max_version cannot be of string class rather than date class + expect_error(epix_truncate_versions_after(ea, "2020-01-01")) + # max_version cannot be a vector + expect_error(epix_truncate_versions_after(ea, c(as.Date("2020-01-01"), as.Date("2020-01-02")))) + # max_version cannot be missing + expect_error(epix_truncate_versions_after(ea, as.Date(NA))) + # max_version cannot be after latest version in archive + expect_error(epix_truncate_versions_after(ea, as.Date("2025-01-01"))) +}) + +test_that("epix_truncate_version_after properly grabs the data and doesn't mutate key", { + ea2 <- ea2_data %>% + as_epi_archive2() + + old_key <- data.table::key(ea2$DT) + + ea_as_of <- ea2 %>% + epix_truncate_versions_after(max_version = as.Date("2020-06-02")) + + ea_expected <- ea2_data[1:3, ] %>% + as_epi_archive2() + + expect_equal(ea_as_of, ea_expected, ignore_attr = c(".internal.selfref", "sorted")) + expect_equal(data.table::key(ea2$DT), old_key) +}) + +test_that("epix_truncate_version_after doesn't filter if max_verion at latest version", { + ea2 <- ea2_data %>% + as_epi_archive2() + + ea_expected <- ea2 %>% clone() + + ea_as_of <- ea2 %>% + epix_truncate_versions_after(max_version = as.Date("2020-06-04")) + expect_equal(ea_as_of, ea_expected, ignore_attr = c(".internal.selfref", "sorted")) +}) + +test_that("epix_truncate_version_after returns the same grouping type as input epi_archive", { + ea2 <- ea2_data %>% + as_epi_archive2() + + ea_as_of <- ea2 %>% + epix_truncate_versions_after(max_version = as.Date("2020-06-04")) + expect_true(is_epi_archive2(ea_as_of, grouped_okay = FALSE)) + + ea2_grouped <- ea2 %>% group_by(geo_value) + + ea_as_of <- ea2_grouped %>% + epix_truncate_versions_after(max_version = as.Date("2020-06-04")) + expect_true(is_grouped_epi_archive2(ea_as_of)) +}) + + +test_that("epix_truncate_version_after returns the same groups as input grouped_epi_archive", { + ea2 <- ea2_data %>% + as_epi_archive2() + ea2 <- ea2 %>% group_by(geo_value) + + ea_expected <- ea2 %>% clone() + + ea_as_of <- ea2 %>% + epix_truncate_versions_after(max_version = as.Date("2020-06-04")) + expect_equal(ea_as_of %>% groups(), ea_expected %>% groups()) +}) From ba58d1a4ef57cfe9e29bf990e13753dd1b0a69a3 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Mon, 18 Mar 2024 11:56:13 -0700 Subject: [PATCH 3/8] fix: docstring examples still not ported --- R/methods-epi_archive_new.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/methods-epi_archive_new.R b/R/methods-epi_archive_new.R index 3af3056f1..9bee5f77c 100644 --- a/R/methods-epi_archive_new.R +++ b/R/methods-epi_archive_new.R @@ -41,7 +41,7 @@ #' #' @examples #' # warning message of data latency shown -#' epix_as_of2( +#' epix_as_of( #' x = archive_cases_dv_subset, #' max_version = max(archive_cases_dv_subset$DT$version) #' ) @@ -50,7 +50,7 @@ #' #' range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 #' -#' epix_as_of2( +#' epix_as_of( #' x = archive_cases_dv_subset, #' max_version = as.Date("2020-06-12") #' ) @@ -65,7 +65,7 @@ #' # muffle such warnings with the following pattern: #' withCallingHandlers( #' { -#' epix_as_of2( +#' epix_as_of( #' x = archive_cases_dv_subset, #' max_version = max(archive_cases_dv_subset$DT$version) #' ) From 36df9777c07aa647d2cbffb41e5bf07f0a6edf74 Mon Sep 17 00:00:00 2001 From: dshemetov Date: Mon, 18 Mar 2024 18:58:17 +0000 Subject: [PATCH 4/8] docs: document (GHA) --- man/epix_as_of2.Rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/epix_as_of2.Rd b/man/epix_as_of2.Rd index 6c3db7170..4bfe32f4d 100644 --- a/man/epix_as_of2.Rd +++ b/man/epix_as_of2.Rd @@ -60,7 +60,7 @@ in the future. } \examples{ # warning message of data latency shown -epix_as_of2( +epix_as_of( x = archive_cases_dv_subset, max_version = max(archive_cases_dv_subset$DT$version) ) @@ -68,7 +68,7 @@ epix_as_of2( range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 -epix_as_of2( +epix_as_of( x = archive_cases_dv_subset, max_version = as.Date("2020-06-12") ) @@ -83,7 +83,7 @@ epix_as_of2( # muffle such warnings with the following pattern: withCallingHandlers( { - epix_as_of2( + epix_as_of( x = archive_cases_dv_subset, max_version = max(archive_cases_dv_subset$DT$version) ) From dfd0105c61d2cb0544d0f3ab9a892751dcb9e239 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Mon, 18 Mar 2024 12:05:29 -0700 Subject: [PATCH 5/8] fix: Min to min_na_rm --- R/methods-epi_archive_new.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/methods-epi_archive_new.R b/R/methods-epi_archive_new.R index 9bee5f77c..2bbdcd462 100644 --- a/R/methods-epi_archive_new.R +++ b/R/methods-epi_archive_new.R @@ -208,7 +208,7 @@ epix_merge2 <- function(x, y, if (all(is.na(c(x$clobberable_versions_start, y$clobberable_versions_start)))) { NA # (any type of NA is fine here) } else { - Min(c(x$clobberable_versions_start, y$clobberable_versions_start)) + min_na_rm(c(x$clobberable_versions_start, y$clobberable_versions_start)) } # The actual merge below may not succeed 100% of the time, so do this From 03df26e0b14f978bf91b0ce15273bfde69f5fd7b Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Mon, 18 Mar 2024 16:16:24 -0700 Subject: [PATCH 6/8] fix: port @examples, add archive_cases_dv_subset_2 --- NAMESPACE | 1 + R/archive_new.R | 26 +++++------ R/data.R | 8 ++++ R/methods-epi_archive_new.R | 44 ++++++++---------- R/sysdata.rda | Bin 709873 -> 709944 bytes man/as_epi_archive2.Rd | 4 +- man/epi_archive.Rd | 2 +- man/epix_as_of2.Rd | 19 ++++---- man/epix_merge2.Rd | 12 ++--- man/epix_slide2.Rd | 12 ++--- man/group_by.epi_archive2.Rd | 10 ++-- man/is_epi_archive2.Rd | 10 ++-- tests/testthat/test-archive_new.R | 2 +- tests/testthat/test-compactify.R | 2 +- tests/testthat/test-compactify_new.R | 2 +- tests/testthat/test-epix_merge_new.R | 6 +-- tests/testthat/test-epix_slide_new.R | 2 +- tests/testthat/test-methods-epi_archive_new.R | 6 +-- 18 files changed, 83 insertions(+), 85 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 51c4091cf..3eeb6b0f1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -49,6 +49,7 @@ S3method(ungroup,grouped_epi_archive2) S3method(unnest,epi_df) export("%>%") export(archive_cases_dv_subset) +export(archive_cases_dv_subset_2) export(arrange) export(as_epi_archive) export(as_epi_archive2) diff --git a/R/archive_new.R b/R/archive_new.R index bcfa84c3d..0b4f3695d 100644 --- a/R/archive_new.R +++ b/R/archive_new.R @@ -197,7 +197,7 @@ next_after.Date <- function(x) x + 1L #' value = rnorm(10, mean = 2, sd = 1) #' ) #' -#' toy_epi_archive <- tib %>% epi_archive$new( +#' toy_epi_archive <- tib %>% new_epi_archive2( #' geo_type = "state", #' time_type = "day" #' ) @@ -743,16 +743,16 @@ merge_epi_archive2 <- function( #' #' @examples #' -#' grouped_archive <- archive_cases_dv_subset %>% group_by(geo_value) +#' grouped_archive <- archive_cases_dv_subset_2 %>% group_by(geo_value) #' #' # `print` for metadata and method listing: #' grouped_archive %>% print() #' #' # The primary use for grouping is to perform a grouped `epix_slide`: #' -#' archive_cases_dv_subset %>% +#' archive_cases_dv_subset_2 %>% #' group_by(geo_value) %>% -#' epix_slide( +#' epix_slide2( #' f = ~ mean(.x$case_rate_7d_av), #' before = 2, #' ref_time_values = as.Date("2020-06-11") + 0:2, @@ -778,7 +778,7 @@ merge_epi_archive2 <- function( #' time_value = as.Date(time_value), #' version = as.Date(version) #' ) %>% -#' as_epi_archive(other_keys = "age_group") +#' as_epi_archive2(other_keys = "age_group") #' #' # The following are equivalent: #' toy_archive %>% group_by(geo_value, age_group) @@ -801,7 +801,7 @@ merge_epi_archive2 <- function( #' #' toy_archive %>% #' group_by(geo_value, age_group, .drop = FALSE) %>% -#' epix_slide(f = ~ sum(.x$value), before = 20) %>% +#' epix_slide2(f = ~ sum(.x$value), before = 20) %>% #' ungroup() #' #' @importFrom dplyr group_by @@ -1030,7 +1030,7 @@ slide.epi_archive2 <- function(epi_archive, f, ..., before, ref_time_values, #' value = rnorm(10, mean = 2, sd = 1) #' ) #' -#' toy_epi_archive <- tib %>% as_epi_archive( +#' toy_epi_archive <- tib %>% as_epi_archive2( #' geo_type = "state", #' time_type = "day" #' ) @@ -1056,7 +1056,7 @@ slide.epi_archive2 <- function(epi_archive, f, ..., before, ref_time_values, #' cases_rate = c(0.01, 0.02, 0.01, 0.05) #' ) #' -#' x <- df %>% as_epi_archive( +#' x <- df %>% as_epi_archive2( #' geo_type = "state", #' time_type = "day", #' other_keys = "county" @@ -1081,15 +1081,15 @@ as_epi_archive2 <- function(x, geo_type, time_type, other_keys, #' #' @export #' @examples -#' is_epi_archive(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) -#' is_epi_archive(archive_cases_dv_subset) # TRUE +#' is_epi_archive2(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) +#' is_epi_archive2(archive_cases_dv_subset_2) # TRUE #' #' # By default, grouped_epi_archives don't count as epi_archives, as they may #' # support a different set of operations from regular `epi_archives`. This #' # behavior can be controlled by `grouped_okay`. -#' grouped_archive <- archive_cases_dv_subset$group_by(geo_value) -#' is_epi_archive(grouped_archive) # FALSE -#' is_epi_archive(grouped_archive, grouped_okay = TRUE) # TRUE +#' grouped_archive <- archive_cases_dv_subset_2 %>% group_by(geo_value) +#' is_epi_archive2(grouped_archive) # FALSE +#' is_epi_archive2(grouped_archive, grouped_okay = TRUE) # TRUE #' #' @seealso [`is_grouped_epi_archive`] is_epi_archive2 <- function(x, grouped_okay = FALSE) { diff --git a/R/data.R b/R/data.R index 26b9f39f5..37ccc5220 100644 --- a/R/data.R +++ b/R/data.R @@ -289,3 +289,11 @@ delayed_assign_with_unregister_awareness( #' * Furthermore, the data has been limited to a very small number of rows, the #' signal names slightly altered, and formatted into a tibble. "jhu_csse_county_level_subset" + +#' @export +"archive_cases_dv_subset_2" + +delayed_assign_with_unregister_awareness( + "archive_cases_dv_subset_2", + as_epi_archive2(archive_cases_dv_subset_dt, compactify = FALSE) +) diff --git a/R/methods-epi_archive_new.R b/R/methods-epi_archive_new.R index 2bbdcd462..3ce39afcc 100644 --- a/R/methods-epi_archive_new.R +++ b/R/methods-epi_archive_new.R @@ -41,17 +41,15 @@ #' #' @examples #' # warning message of data latency shown -#' epix_as_of( -#' x = archive_cases_dv_subset, -#' max_version = max(archive_cases_dv_subset$DT$version) +#' epix_as_of2( +#' archive_cases_dv_subset_2, +#' max_version = max(archive_cases_dv_subset_2$DT$version) #' ) #' -#' @examples -#' -#' range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 +#' range(archive_cases_dv_subset_2$DT$version) # 2020-06-02 -- 2021-12-01 #' -#' epix_as_of( -#' x = archive_cases_dv_subset, +#' epix_as_of2( +#' archive_cases_dv_subset_2, #' max_version = as.Date("2020-06-12") #' ) #' @@ -65,9 +63,9 @@ #' # muffle such warnings with the following pattern: #' withCallingHandlers( #' { -#' epix_as_of( -#' x = archive_cases_dv_subset, -#' max_version = max(archive_cases_dv_subset$DT$version) +#' epix_as_of2( +#' archive_cases_dv_subset_2, +#' max_version = max(archive_cases_dv_subset_2$DT$version) #' ) #' }, #' epiprocess__snapshot_as_of_clobberable_version = function(wrn) invokeRestart("muffleWarning") @@ -164,16 +162,14 @@ epix_fill_through_version2 <- function(epi_archive, fill_versions_end, #' #' @examples #' # create two example epi_archive datasets -#' x <- archive_cases_dv_subset$DT %>% +#' x <- archive_cases_dv_subset_2$DT %>% #' dplyr::select(geo_value, time_value, version, case_rate_7d_av) %>% -#' as_epi_archive(compactify = TRUE) -#' y <- archive_cases_dv_subset$DT %>% +#' as_epi_archive2(compactify = TRUE) +#' y <- archive_cases_dv_subset_2$DT %>% #' dplyr::select(geo_value, time_value, version, percent_cli) %>% -#' as_epi_archive(compactify = TRUE) +#' as_epi_archive2(compactify = TRUE) #' # merge results stored in a third object: -#' xy <- epix_merge(x, y) -#' # vs. mutating x to hold the merge result: -#' x$merge(y) +#' xy <- epix_merge2(x, y) #' #' @importFrom data.table key set setkeyv #' @export @@ -703,9 +699,9 @@ epix_detailed_restricted_mutate2 <- function(.data, ...) { #' #' # A simple (but not very useful) example (see the archive vignette for a more #' # realistic one): -#' archive_cases_dv_subset %>% +#' archive_cases_dv_subset_2 %>% #' group_by(geo_value) %>% -#' epix_slide( +#' epix_slide2( #' f = ~ mean(.x$case_rate_7d_av), #' before = 2, #' ref_time_values = ref_time_values, @@ -727,9 +723,9 @@ epix_detailed_restricted_mutate2 <- function(.data, ...) { #' #' # Examining characteristics of the data passed to each computation with #' # `all_versions=FALSE`. -#' archive_cases_dv_subset %>% +#' archive_cases_dv_subset_2 %>% #' group_by(geo_value) %>% -#' epix_slide( +#' epix_slide2( #' function(x, gk, rtv) { #' tibble( #' time_range = if (nrow(x) == 0L) { @@ -756,9 +752,9 @@ epix_detailed_restricted_mutate2 <- function(.data, ...) { #' # to each computation. In this case, each computation should expect an #' # `epi_archive` containing the relevant version data: #' -#' archive_cases_dv_subset %>% +#' archive_cases_dv_subset_2 %>% #' group_by(geo_value) %>% -#' epix_slide( +#' epix_slide2( #' function(x, gk, rtv) { #' tibble( #' versions_start = if (nrow(x$DT) == 0L) { diff --git a/R/sysdata.rda b/R/sysdata.rda index d100711d1adc967fb453f878e1242dc3f7074e44..a2c5abfdfa7b7d7c504d8778516d9645cf208e63 100644 GIT binary patch delta 184715 zcmV)3K+C`JsVlguD-J?hXgM)KSte6iH2syykq#Gs_@pAKqG^QFG|(di7{X#?z)S!E zN|aAcO{nz%4^V9<4D(P`Qf1G#k0A=GPuxv0&lLq#C-5ZNImTZ&OrEM=}d1S+X8 z*A5sEsZl3{0T2~bNk$$fo?hcEqtAa71Ogv8-^zptZN40{b;%(mS@hWmXdgSGzf|6L)o9 zv?<#ts#m@1-m0p-lgwhf8+6@UXjRV6vNEphqnl*qx~$L{+o~O-4=$)Wt>vq=?m0f1 zdu-Nc%W|p}ciq%gN^aeIH*6MLt5(X|yWZp5Xq#^CtEsJOndfyWU9m5{?|De3%ztya z*3`kRmu9)5sVk;H7g^Bhag90L?F}lQ7+?c1$hot%45w`L(Cbfp0YCzm+eCz@3N$M~ z02%-Q00xl?3v85DgI<8hq3*i56*k_TbfVLHWod~@sjR67x3>WF1FrT+7TPtdY^hYI zb{E^dO?zY~+U!}nuIF>2vc;tATYuSB+6`Ru-PU)zZfMqzuDu&9JvVlC+9c~$CilHZ zqEBlyOS0DPZZ_?ab*e$7GqA0822wz(pc74PUwb_gDO6IGN<9r41psE+I@Q^bpgy-u z7RR=>)gFhd4ZUX;jDYjIsESn!uI+4@nD?>JmF&6QN=j9hI@;PY_r1dQDSy*fSZglZ zs+$IzdL|_Uqlw2cXqbojq>U z55DfHBCO4}k@Wl7?_s8nc2a^`)TeE?TWxK)x4V@nPd0%@ZB-J*sS)>Xk|ncOvlFn? ziKYau?aC!&-I*ff(iO+pa(|WYbCF8x6pFNHRqMU(s;O?{ku7e`L3A_+A(W-NITDv_ zmf3R2F0-vg*v%Lqx?y``-sfGiy?cg4c?!z6ZYWV}I$5i>A$I$;zQcR%(v(`tB#y>N z_!gc`0H)eXhG(vnb(`Chy<@b>+4OEPpkY1P(L=TDZfKJ*81ibWmw$H-RHnuPt&Hr& z+XH5eF;}6z?&=bjW)WF4Ml7}40_l`4?&F!4GZdoi!b07hB~xLbEZU;3?a>+6DC#@6 zJ8Guw$RoSDB2_h@1G{%@M0iFjJK5FkliueDR?SLtw+a=el&WOVRc6$xuYJyns(N8b zS&e;|b}=N~yXlur?0?l&4P{j$Yy>SC3cIz~rJmgOWL~hKcW@okH*OWyxv-*+?Z^u5 z;N&IUx{8f3rEJQG&@o2MNk?~eCF!fZz~b5Wx1@pZyQ-jfyH1JSx}huYXH-*rIS{%r zMDE-vF0G1HQ?n#i*$A#$NTZ`$8@B5SDy~|oRi>yzcRKB)TYtN%R2epdO#2+YYMa@} zr&n{T_SEQPDrCia9mZ8gnw3nobZG2l3hvGlF74DJtl0uq%|NQ%-BeXtVG^CTO(vR> zcW#je+6cPj;-zTjUiXNwaHP-Ub2$=+p3C< zV`05FZAsf>oqvF(2Hn679heS)`*WLRqj|aSI#aE$V+wVbHbhISo!kwBKKDD>f{T|! zkSRz236lT-0E`m=044wc0%XL=fD-~~fB_m{08EUUWME7L$$$WunqUONU;qku0HDf{ zfY8taX@MGPkZ8hbp{7hs5E?XTrh$_QrkY?(1i%UCBYz2rk${Yv69mbEX@-MFguqk4 znN##+zyM4GRR&Zb0Wb-m4JH64000m)!7(sQCLxGq$TVq$&>9AblOs&2_=X{n&>A&1 zfS3TuqfAW+sm;lhk$$$X>7(tPOpo)}K@|Xm`000000000000A%n6A`AGFcVAyU;qFB zOjPqmn1f9WjWS>YX*`(*nqUA_&?umJKNU(S6n}`Q8F+vpybpwI+D{Mw|G~12bWuR+ z4a!tr?dYb(yM=MIQv0jW`Hd=_$$jI5YIzB5r3D+ofu_(%Lq?j9uV<%LT%ScHEV5=T zLcE;?v3Z`^*x&dKD#sl<4=-TiWp@a5pE<7Js8&taFx6?$(7gBv!9x0$IXw!cN-Ujv zjDK3hAS`)vI$fkD&riWj0W{vM!k^Q~Ri649N3L1Rbn)zB+u@Tz+8Ox$T0t|GT&i>3 zr4$8@4PK{*ARSd=aA`FkB0?1;82=)#F96yiF%e&N7SgXCO#l|}K^j^sTbe~DBF!F@ zEVZs+QLD(ZraM>xY3GnFIF27||F$(qe1AxcQgkQ`^1>JQo}~zF z)7m+3q=x3HKEF~M*-&+xH6i;dlyFcxiEh#uJ?ho_3|hWk;-O|E$$ zuB(=)*XD>P9Y59w;tIT>3Alm;&i;Ow)Ei_0aQ)%))M;=#Gz4~vYoJt9Brv+EZlU-1 zc6C)X|GywqpAXkK(MF)`z#rWQwtuT*?K2g3WX=&Z*wpYchvK>)Av{Toie1P4D>&6;ApWAEx>%p_Bh5HjWMoJQ&8n3dR z!KX=}%^Q}H4^J36iEXHE_kScn0`Z)#)oau6)u zyKvFT^%=y!ktEW+MWz<-0T15d;EC?BIEH#us?$6u>g-HILTcDer{ljP`g9w(aAHz?;M zAmVQ{=J8^TXl+0yj-f}xwoYuQ-{u3BqFyCpF~{Gl$$Tg+i<$ZzZuMFo2&>^$tNS(B zn~e*kd_U5viE`lIeNweYwqgrnH=XF{0Tm-ZNvDcr0KoeieSe1fg7wjmaQ=+zgB}{v zs~Ei%{D9PNpBf2AsG4+CaA&e_AM*(d1-wz+6j~}i&j3@)6<}RdTa7zNUVo54qGR^z zcCX?pQKKoD!BqHxEm1e0%)-=)-{OmzA-i<|fk&J~_OFmRdiz9Ffq_5{XcN`}HR=`Q zQDW-4-alX+BY$bKZG?LuRy_WjkEKE7&rMP0ks4qoBfcoNd?oIqH6I4W;u^Fs ziiV?1ExVWmEUlI*QDxjk%>H3ioPevudM$K@-F7>3>C-QoHzSvVjA=Ln(5!L}8 z91knHl?TZ}jc;&dC#5$X$0=vjX${x3X*)NxKx+FZv@*43vo~p|PF5K28(1nmz*c@r^ZQB9`}W%}2~eI> zKZuCv`+uH;&a4&K_&@q%lCn>XiLepvVq6==FbTh=-d_$fJRfn4lc>;CkaX>n=siVn#+*Vw|pq3&8 zK4nKALjes9nMn=ERe^kgw{US#<4S|kSO(}bw|`<=H%*|aHDfn%tM(9quyk~UeJ#X7 zjyim<6r+eSs8LjSv_^i!6YA-6XVWM zF@Yqt%lO0>P(u6b!EZYGBJis7wLM;LI z-M`nVst1sW%^q?(Rtr<8vIT4^KiU3MHhE(jHt2ap`sJZS-g;8VAF-1!mP8K9u)>(? zTOgM`;SeY`n1<3^YN@r5Kj}P@2J%GcKz~RX#DNK`&fXv0og`feT%k39rm=9KTl~A8 z7o@O>+4XcavKOcu)Gu2V4tR!yCm$$U=w=mJhy`ZF6&v7PX!E*N6&@NKccCaAQ4n6? zN6>mfV&$}GO+jtcki!rLPzi+U+%$A2h3 zGjAH}D9_aZ&8g<1cYK)&I7JuNQKDgd!WCL*8u{Mr0PCo-7lDjObcE>wYV!B=f&^&$ zap@R8IBawiX(w4aEtR3D&IDD4f*PYZFQa^@ExQRp|6qaWfHcQU95p_Uh>nIJy4OiV z-QjQH(*3p__H?Ah=cwr@2@j(NP=Am;QATYBTj!K&+1{81pzXf?+fl(xEZG8l7c~k7 zF}4ag%C(4M2)tq5Z#z{@Zp+pC#rC=pI5Ia0+(SmcbZtT6!0+u5qNCEF8^WW?0JSel zADpB*YI=k`GAZ$z%xIY?IP8-|G(ZP$L!Fzxl~2)FA-n(DJRrY)12YTM2Y;L`Z3!xY zyz3${K%uxq#`j=RO@=2*Yh1l5gadl#8YlV$Aax%bO|}Mq1)l_|#ruN_FRMGanshD% z@;*Y4v``Jg9KL(Z*($9zI0u*{IbtD{h86+meHUtAl^WOF1ZJlWFjR@cLk$x+M>TB$ zbX6Kr1KS-hSKUM!!!(-Oqkl?3wV;qsnKLZ|q&G?j0h~7~uRInquV|Ra<)rB#P=6AA ziZ75GRnoswYbVeGLZ8zJPK$6AF})JL>WgFZfu&E=2PoU&@IT{0!Q5%=pFZk}RKFBI zLIt*T-j|C~gXy!Hjy^juWD=TmOWc2nW*3SMK6?NR(H8hn44ig;CV%%)S*KH3p2&vh zO$1HrPbh3~KkN+8+84AEt#T!lFN(uq$+XiV^?~drOe(GqXff|#YkcJsRS=vH4^OYJ z>uMxUsX#nx2)Qs)JN24THnJB&Vhh{~WCa39nK)aJN&A#tvB##&n>;^OC1RhX|13 z^UzyV%l?v7HU%7BfBcryk>Sb(!GpO&mVxjQ1(V1H%%Mvu%ttZ_D}XKD9BdqjAVe}4 zx&f>Z1I9tqziOIAab$lqjJ4475+}GQz|63b^&{ zx_v>Kj_6F$0_{K4cp?{nyEs(25P*M&{*>c)dOGY63p>TuHm0;4+(c~p>Qb~(ZU zqRvw`Pki1ss(+i@Gk_r?s{?KcXD;*NfqE2SiXj4LK?r&zb?M%a*ba}U_=2;rhQNsa z%F)vkSfgr*{xaSI%gqI+dZCH*bwE28blsz zSh=27Y%DKD4BXAm6ZHD3j1S#KfUoexEz`w@ZaeG^2!BHHsP%2byG}lQ%s=b6 z(GMT6DD~%{Q4Z*m+e3qyvMRpEL^!st{^j7#x;(;OboV3KVr;4vF~*0UjDA;~wDvo5Ydf zW10QqLw^B|%he3?g@j;leVdl6fgV7Qd5QB5yh)OroDDiL#`N_MtP#*h3}lKt1oPnY zP`gSHI^;rPC4xc^yk8Yh$0QFSU~*gC6ESMrFukCotK#>2R;mvh3%|fkZj>$GxSev@ zJuHh=P9OC3EEd7QyL|Q_kYW&8icIBkpAg}9NPlZ|3gRhlmr(B!wyLDyp?wRnS5=yV zi=L>B%`d9CbyprCnamoFLDB_owHtIbN~JoJ2CD*QA7#=Z7PmUxDni}@L$luR^-WTT z|3$&i!WHns71as3!Ez;{08&H^y$HIHixAgR366%y1TTn7{2~1F#W#w=(GEEUhSEc- zRDX2g0)g==Fy^Mh6EhB42PNoZGG;PZyuiprr0ily8IvVI*vLIxHR$R_(?$X@4?-_; z%$ySj+vPU6ZNh{KPBwiRnu>zuA2WTR>s(riNA!9*m;qm<&Z9DtjBe9lVXkSSo=4+J%3PvnD$Vp-{Kko0N||3o|XlwYn@v{=0{Am zQZOG!g!ZaV9LG@1fUxJboDYsyjfL_B#`8&sr(@<(Robpp4L&@yG72*4s25s3OtcU! zlV6VVM5p%A51)DwXqOJ5QK50nQXJhhc=b$f^35P@Q7#bC5G)#DuT;DeM_KAENSArxTn?(J`hbESasWQKoG-h=xUzc-g2PF!G3`bah-Fv*ni9zsYQt? zRc7aAo!Hg;}GfLg)y*{fN6Q_U_cQ|;#0P(tjq&i_~*RAeIS`PVtba^d6Xi#1qVbS!hTjmQ|8wOynow`K>o%wH5*aU{q`Odj zIe$KC2O&0CU;XDug;+EaFHsGw5t|IC;%?Nb&F|w#BFpGU_tE(O`qq7DuAf8qoR5p| zbXE025bI%PTj)Ko0|!%b0GMI9%dSNfn5y21J$3DO=F`$Ia-bi54aluv^r2gn&he% z%T*IBkkcW+BsNL5&8A42CUsCWvz$R`n2!De!um(j1Yx2v(FLH~A^g3;LUanyIe2qA zfeIc(@c>*M_7ztH8NT{OP2MIm+5rIsc0dq;kI+xO;6K66Vt-!UOuorUTIzOeC}LpN zuWaqjPV;>2&)WtWizUw)CEE@G{6e74k+xwLUjLb&uGT9i^jLyv{zz#n@3~7x^ zzD_j-ueKqk$Mlw&_lU=A2s)wxJ*Zp+up(YsymOSIgYyKxLvLi4h??p!!apq>tae-e z4^6D(Fqxk=qQB%toYDVx|I(HFC?$#pQbG#6d@=%$6@N!z*&#wjX%F7 zcMz%FqpZajih;7>Fn$YOyA8EakLIe5G6KHkP$GI?cj&&|{IFa1f>RapoxMP>uO3qU zC}XBt2cNS%mU~kyK9}lJLoW;0+ECmgD`~X(aix$r*Uc7b03(_ZMu-R)h{VN#boA&v zzI$Q7_kZe?&nU6Mp>W`MGf*sh{pQtCn79ZuL~Zl6IcY?-Y!oz{e`0>>r!c5X1NMc} z)2RDQEdzsL=$$9uQ)3OTUSc3tbc&A^j0&H?_WdeV$RB58yw)h=9+M(cqY7N8{MvAf z>S#i@O(&_PN(jAKmP9UfbD%TS!*G>v1o7_PUVrW2STwj_`Rh-yT!s2>(i&HNQt>{o zlWtHrU*~MX`pv6ZM8?qjygD6#&X#Pm?%~>LWcd(hW9U<>p2~nv*nodw4UcmuXN4KY zPq}+}Mem?p2PaHC4~82KO{9|qlt9y7Ks3$^&tW_!!!|V#5i$Db%~rWyDrcH>9qUK` zDt|x{3wP0!T*JL`sa>^}jml0R)jYi|ZQKj6nd_k62I|a!{qhFAt%?DN&WRtpr4aS_ zx=h3bNWN89|9*W-S_7Zc9V3DH?-eU~dOH@L3F`=uFnt{`^k^I`?N@Ipc`x*7!B7A+ zrD2Rd%_gtkhVf89sQAJYfwqbTL5Q0>8h=5!>a@wuecArOLYK`%uos{qrC>~rRLls| z85{&8#znWx^#4eVGZ-2N?g$#~09~#U2Mr#90J&@3l^Wf$29$t7!!R&VOtgD46Ir63 z;)@W&B9|VZY7+m7_^M4NJd++mc5%DI_K=?FDHr@#4YYbn0Z}zt zA$*t-eBzFe9jGIGf&sdE)Zb}9Z#XJjHY{yHk@RR74sxDgLr;bvhWVyb@qbL2tyNS` zv=E=Z>reDc{_Vbp#p}_wSzKUVt0p0V|Pi@WpWV1MQzNbwCYmGWhh$*x-E9M+1K`$Tm2sK2B?zG3v~5D)JK zBp8AuIKl?|bMZ5n0~t1r*IlbgREPT+l@=aEH8VpgCtwh`sU03X@}NYzWKZs=A->SW zD}OYrx~W?rXp$X5fK8Sg$fVTg>Hh6{q3A=j6>O8*AfvT;R4ll<27llA_8p;L5}**_ zCaie;56Cs@b4DSy^y;vnZ{5nNMcep^L%5G~z0-W1_Ge=%H)03b4gv?w2l^Ctt@`!} zSR(&%%|h?F6g+>d{l=j3hz2|%#my=&dlP`vy1mfDsOvUMwGcS@wd(nvj4KVk2h>E& z5q~6*&MQm&aM4wK{(qK$9aK!p68aEa3D6emlKn7xnMBZ#%_tG;`d8t|)^lSN(84iI zW&*ED6MGJpi-v*kL;etiL=6l-eM*6h>BR^-l7_;87YRR}G87ZtB61TT!R%mm5Pxg>=vPLGr$^$q6kwwS zsvYAL$4~MS56}c&Yu0Ey^z|Yg{}DnFZJox?Qmgeb`8S4&F1rHXJL$;*0sKIL<3spv zl)cVRhM;t;*cFl{Am%8S?`fbycJNJ*kKO>mSG7n!*LDpPf>eiN-utCWt>lj};nG9C ziN*l1GAA2EPJacTR;}4orrb^yxllK)Mu`Xt>0o52rwkBW2!jFWg-CbMJ`qw69UQ3x z0TszaE&@lU^rJxYm4U?15+*2zm4u^lkAz2~k7dO)Q*xacBMy#2KDwbCMelyuvARyl zUJA$h#oD*NQrDT>sD{X9;?v+LRkZmv8_0YMM$;D47Jq<{aZ;qJcT)h(tSfJSuG%H9 z_3e-VE`@|gB4hbqsPc#YDxPPp6%8AGtpt;BJp2232uOJ3&`eYg`%x)48Yf(Bz_b$c zwt2Ha)}GP_MMXWR7!xZ1S^&Lt9(pDDk2|z@=%TI=md%P znqJ#Z538gitJR$S0?>fNQy3j63m=U}0d~OtUu9v5B3M*|{_rXv4jU`-Fr|`X@X95#~sr zRD%PDmf+!cDu*Y*lm%!31h)z?i4z~Wb>&2ZcYp!UPX#0<3I(#&LF%`Xnz_Z(mFxv* z2pyn6z>qr;gZx{2T2yYzFdl$`*Uv17EagqgtF%#XI(<7RqU|w1f*6qxttbk&h#j02 zZGX&7G>2sq+a3CXi`c>JdR@YW=&U%=V4Zn`qe;NWwLzVfc_=FLJxw20I$1NsL4KWD zQ0K^|8X~{rsC0BHP~oB3O`PYchJx$9t3mC^xJQ|zqbNO)08xxY3q8u~tVQj=**zr3w=r5}+I+DMUOd?0?-Y4Yn?|5EuRPWhh5XnZG?Kq8jWD3oGD- zS%N3qyogXa8>)#zNg?;K>>&CB5d*pifEb7-=s_0L9_O9wS0MMuPe;3p0Dlot z88D(^J6+P-p)tSlFLI=v) z>vL%CiGrK&F+mLRl0#om;we4bOSd2AT&lPlUZsGy>L8|TMiq5NT92t;zVQaj!v8Ma z0HfenV;8Kg@}45tQCV@kP$7uUZ+}L$Iq_(OlI!3|cZj!ms{0RPLBw5vT58Zc5fUe^ zNW(J|aE+`;bNjvNsgM9OBt>&D6}dpz$q^um+kP;h=Aw6*DhMlrH4R-RK|~ z3^PY17u+>SQL#T|7C+F7hUU9QyL=Olk9GO96@TbKMcezhLj)lWcZ+G4?F4(a(4iW`{t?oc}5BbgT6>jr*6@Or4PD&IFmVM%zg&*BUYZ(@oy)Kq`PkNOzFi_M9 zmgXFd%so42Kw^T+B0%)X-=xrx+4%pOM*POo8R- zXy3Mb4nkm{^PEnAsegY?)zUN|0ZP#Wua|gUdV3GQ89sbRl?8|0abu3?+UcRU8 zrQt}bj;IgZ9Pk{p-5ppyOjngw?PXw9&4_#%=&2D;q&ab4;(yv3k}nT zxkqv6XdoANdVhri`y3+;tP{m9pJqgLL>K5x*}?v_wb~_sK%ci&NG)uK$Vk~yor{J#tJ1!6LJ3_s+j6@F%hA4oqbeP3x?FyyC3awf$pF1B#1;AJizgYH#rBDA&TFRKVVxe*P zkf8cn&&yGjJ~g6ZS)@esU+lP&r^k<#@ltY%(SJPNG8_R=7vmX6rh|*gy6@oD2j+ki z{Spv4fPwz~>IYmy;DQ0y5#C{C&g$GoR-WN!yxw$aCED4(L?W4M{r=7c+i^(51EnAf z8^5=#<%f{*&HxkOZk(kUpKQy@clu?LB2KO%XY&6*%OXr;g@kW>c@km901kkFP@Y5+Z}Tfe|71{VwIDQ#hj~Z26ka|aDkC}mo7yVZ)#WIdu56~w>VIj=5z6(a8 zX+6CjT@itHjtqIO+$vj<<4RmTnlH&d?nI(~ob4UT1ZAcU0^CK~Ab(`fYZ^2S3V*QM zC~eix0I|LN4zC`^)fh%C5F0ySYG&1vNy{%j0rl5cR@RlFBDOINF5P%p}HzT zK<&aASZ;gA%v44gq8Xxgo5u^fRbDUwmewM?7{|Cpds~4~>x?%Wm+Mp`Xk+JwN3x+) z?!zto6vagQx;@^lN(u&K&t^{!>woOh%RC6rXoNtUxFA4RWBV!r^_*l)hG?mZ@$J+s@K#5Yr>xnUI_ND?LhjmCnd&IQY8v zro%|pA9?3&rZdwdg4Lxb%!JF9%kA4+bN$?&v;qQ#8^8%W3ozUdf1tvdA^<@k3iT*1 z{eQ!%H-p$s-nUbZSx7ej$A2nRdLk?@L8pn+sa9ePCeA0GK$9)RLC@Ok6u_|EVCfvmM{vbZ{lN)^2<3)#3XH|DoGQ7BkFf|^IY6QrnEQJ59)2O&PLgli zf}=p&NbB;|yi!8Tuc4gAjR(~1C~Mpe6XFlL6g-VpF5AS-b?8h;e$=z<>$JeWMh z3($oA7;%seQ-p_eP@rZNg#r>fthGZuKa>_4)03ujm^k~8j8A$NxaNTaxqO!MGvoRqTumV3{Im*L~4{#50rob!a~|WK;D)<*0KsvFJR>; z0_2YrD1MItD8G#J;-iJ0o_I!=NlwN96v;!JLNDV$5|*+>LI}N|FNjnsG;f%oTVy8l z9nO0GeH#;S{its}@!#917d}SFJ`Q(}YBorJ?n;5Z^Aen^2Y*_f=y0?(P=l=cB|k~+ zew@83=fNKE(ds_`28&+7I!!)`Ry_c9G^Ue8)S=C+b&aK@!0Eb#l8uQ<{^!zS!*U zQOyrQe#&=P@_*&EPBy{bPUV74mm{fw(lCr#$p^9sEF*uxGMmNRII9@(!ywoaWc*AP zJq6(=&Hxo1hwsDe*c`W96mwBky@Q1*mIMu?c`|Xwc=_vExdI7j!t2Vz@Qh!WLd98Pxse5t?2Fs`#uWwn2 z1Yq?A){$DOJ~XO`hpE%)_DRifwxnwEIcea zcx7FJQ4SElWm=zzMg8dafDNvnr?&y8kaVb1V}DU#i^~8rnE`*q#g{tXPCj>WLPq%m ztb$+Rq;kz97kc>b)h-eQkD~zAPy;`P^Yj)FLwraRn+2dAG;{wcMBHL+etkb}L_(28 zk3wtPG9XmC@eS%WNR0elMvvrP$|>JN%~X1@?)FMGr-UkFictm!Pm%Mg6Rm)Oyu+V> zUw`s6WKj)NpBxQDLIKH6=^`EUPzTb5;yd&L>opby$7H6hyIZu)KI==}%d72Z7UDCR zqR2yOvg~q*el%?x5(r@7LSO(M*v@NouN}~_+4=vdNpmIo6zP<-vBLCNeO|$Cfpa%Itx0W>_4q8|)7V2& zAK=-2{2C#z1 zTjltMsSaKVg8f#Ae<351lmlSqHp-sLLN5Fw5fBW-ZNCobS8B`}3oV4@rtqvwC?#J> zM$ZC9^H64D0(LwJ3%x)Ig^!V#pnin5M6-_w0iNjms@seMuaF?4lZ)}e$ba^qflzW$ zaJ-R3(N1E82ff?MNT3}N4ni6;DiLW-W1XR=Zu{DUSL=~Dz!s_>jSWf$$<1eqm+MG6 z-dreqG7#+H?EVjfVr+-EWc5kyl=j6LCBxgNKu>4q2VpQ94S~?}zQ+ZmjA4wdtnG47?ETZ@rcREMffqGnX2*1G`qi;;FcsFDt(@rproAGx*2qdSCWB zm&Tq$J$~B_dJCi8l)q=IJK*P!@@15ezUv=KFXQRSi*1a&m)IF@OQm z37Q=ZkwD!jv8-S)I2x-TYF9`C__6Vba>iDM)9;20e@|!pP>qPk=_aU^Ti7`k)mJW+jxaK5*NESeX6Je=73xUCFQ8cv1+1s z7JVQDVU>YU@B5_UI)jxt>_jr8MomS5 z7Fj{k3jxOSa*c@ZBt>#?L^44k3%uOCek&nHvAMw5Ab))_LCJA4h;;k^(Xf@iq&}b* zRVZ_lEFDE8bhQ%GKvwmEw$+juamd$JU&ARng;v>9piw@QxB+WgtAT+$os z|CDrcqaPSaOp71^FZGj@*#yXC;4K`fwv)3|z-*5|!y6t!Y{BrhN(=!{K4U~;#3T=M|~ViDmB*Y#enhNHB=@L+M+W7~zfRj)oznTh?Jj{O>(pbI>eS2zeB z$81)1P=5W41p1&=yg}N=2RSpplSj!wh-ipeTYu#O>P#}NKE40^ck3g+5n^@RxkE{a zcu1sGez_)K_0<|2jC4dj->x)AoQrUSr}&Vf-Jtu2%=n%yD^v|GS#bYMp;HKEpoQK6 z`M;S80tY!ivJbF;_AL$y9i&YZ=e}Va>qHDnDAZ zOMiwF{HkvhL;nyp+2dyD>8i0h)Qj^fv9bLW3q)VV(TWGU8MH?NeFHm+d3TKoB`OSTmtWbg&Kmg^ui?d7r>EJFayo2Xhqz?~igv z-(YBZ;YXMdDl*=+84p{5q=r%+E_vpVF@LRnJn;STq1{C9u=0gW?_tvGc~dD^caIO0 zFhDN2T}cwzni}SW2}t{C7kL2}{7?uTT^vT|{xdP2Xrl)G4&-6uPS7E$!B=5Odi*X~ z3Y|HMj*@iwWLBeDmVMNwY>JO!Pk0g}nx=#|>W(^oAORW9-{RIs=cEN+7n!F%GJiV% z5YrdPr*J>;BbMlH>R74DQ_fI+2p%BE4^XSX~Y$N8LMZ11hJbvmPY)peF*7 zat}FhmycO`sDO+Mpra4CLP!RR-+!Abh2nv_&W}d$H_2?MEC2^#!>Y6}pAktMsWAlj zxe@Y|Vhu+n_sSlsqiLq=12G{JT%~npeg7MJ6au*{TfrzI`opc@KE|^kD8n*{&4inu zR8Txle{3p4yZ7jLriPa7Muz_%Q6hZ{|i*z3FJ^Rahs> zz~2KDRo@^2T_P1!63tjMWPheHlb|rzhuM{?9qC2gzXpnII-!K9=DX5?wM~M2$fUo2 zCtIslo#78ZnUoNFv&7SC?s0TFkyiWel>x|>nmbg(jBVZJ4>#Q?0371(gF{?}nr^f) zN{mzwt{ZKn5uxAVsyr$cf`{rV@PR^g^wi+=(RyuvzPxI73>5EtihmAHNSr>fln-f9 zpT(I#SHC0s?$o5fd-T*M6%m2@|1|fZyXd@1jce#Zr-%?9r~3*8(gKGLK=}whHbqkk z6?TNb%xs|~_yC71ywK!HgNLybU*Ua9swPcEfvmtalW{0!)^@6lcuvuvi>l4q2g-Eg zPCgpD1NMWIb{anvEPwszQ(4n#i1GT$jV=a`K)7{c+&wktBFQa$*!S5&5UpIR6Jwp~2P`1_y#~3e$pvxTv4mC~`;v2ks75ona=rtqwf^ zAa;s43^pLI^M4yvKd5%a_L_F^QV`6|S{5{G;^ukI{>bBD+aTUHI29_j&ITEi{O0&- z$9nn%DF*VO9*szSOwAdrc3Br@>9oYOeIXpjM?pS=X!EF4HWVSkqIlcByM4&kHb&bI zQXBP{QrvaLgoKHxfRPRlkqTftN&tnt?{8Hn6l%0T z0)H?y_`i^jT}N7lNw@+N{c|%eRCHwEfLLpUxf~ozQat5nhB3i}UHTe?cCS!H#?;ep z?kS0SHDT|C_6m_L#GJw=b)6< z;)BRdvYVw(Qoz|AMu>sb5c+{h`%g{}`8N)+D1V*4~;e%?# z*;%pRhrW{pbq4g-U=a0bavV*?uROwDcq?hQTz3*mG5H`gb{sK7P zNl~Cxi%~wDVCtKdfk5M@A3M$;R=a9F?SGJV5i+NT3LU||A4ahn%d#l|&nmuY8xgC1 zRc)9x7g}p`rVUZ;j{vN}YPs+#deAuB{a23QruvA?^v|PBbM7OzA_lCX5gov%1YA3` z;EYjpDvVsx41Z(5muM8C;{hD*nisGoFGxhRUR z=pr@61dEnZwZ31CdGaKmT%;XffGG z{r;Za?;?c;Un0E)(Y>eJ4>YVw7rC?mnIzGPU+evEg6b+=M=9S{h1wA;Fn=I6*t1fL zKmeiYq7Vdw3K;v-1O}!0)b{<5BU*FN)GuWnDP#-$r$8DxsAubPTJTdC=jiWyh4b7ix=yzXM`Kle zunnKQn8E-IkY7{IZ~wQ~iX!n}OacsNi@gcC7QTFF>VfrkE?iir zTGGKMk&}q~^}V?`?`!!y;x#niE2i-F5)AgO=jn}vBnuaykxs0!slpM=p7w>?`hVDo z7)yS?`%)t66%0}<;^EXx+bwToy^&;~9Gzkj4Ok8kRkx8`JCb?Cdo+*A&wo&dZM&4jdY#w9LbKJ?sCQYChiXUm25Nvq-ahL$BUqqPQGteu zQ@ilT+9?TSIJ8>t{3*Qu)%R2F!b(!#4uj->5vRn0dchU9!GRvH`$e#Cw-LUT2%-=G z5czz_^(70*oX&JutSTmFD0L8;#w$>}V%}vI+6tq|-E1Pr|vov8X}INQ$RmkD=b}hpRlO03Y;87#LtkQ07>V zE|~e18fASHy+$Ch-!udQ5^+BuMuOM+2(NGLsIeOR8{ymls#{H!(g>PlJ8+00T7`e* z{^^8t*rj?S8-KK*LN6ywdnF(7L1h2*1YOw0tmhI&XCLd=nsgX9@DHV z`tdwQc;4+{ih{2IKS030C*ww*T90ml=!n_=yxBF zB&Z(lblxnF{KustE3ui53Y8hyc*zb*7b(%Q)WgvJ>cndIn-TnV`P&`%fJysXL6bIQ zCRuLmZTtmZb&TdlJU;9~E%3zqwP~5UeMI(<4v`j~5L-c7dgAAQH4>o!;E6`)CG}B| zS7W|UaJ|YZJ!F4@F(@WgLa*mAl+^gHDyLW#dKxw}hvQa(QJE7+R3$Y(*Oi zX8pA9P)L0aTcVlR^Jrl6U>Uh~{bV1vmz<2i5GN?Fgs6YUHA!$1|42^(UVvXn#_dDG zq;}>qQKW}^8@7bbpL;(1@0pER&0T8-r2q-TmWxV#vgc;9Zk(vj+_1GlD=P5)m3d+` zuhnlZFp;OBAPH4~0)9d^*9jz)4QxfPVo!lp`-LT?4)!402lJy%DHh8_U$%(E&I7F_ z$VIC!6Tp8!Cg*>oCL}v?X>QMZuTYJF0>PQ$y8XcBK^*>7SLt-KV)Q>HOKtR?%-HAs zhPxG5$Mk}(EPo@X^9u4)y5zPxm03HyPRGjE<4+Fv{uMfoyn^k0vZG$OkkmU_N4A-g z7)X7ffdB*h>TlIIB^J@~YzpNub%HFGIZWT8HE4g#>Vrj%&ZZ72$~As|c`J@4L!hxe zDvgQeTG0=bIC zKA}hK!RHiQ(u?x?_}E(B;(lG#1J0M`df#V9IC7bRsL4mZLZ3(n_l**&K5UloJ_eXy$W-|1szN(fE$Pg-X`SK+#*q^V7uWb>1 z+#EdMk5z%%yfE2 z5*16eEgm5MV_{Sc$!m$CDnoH^6+8}gRgqIGxDjqUiW&u<84O*R=6q0Soh6!9CU(a8 z90ij<_pf%WvIoeBK)RrWUGNu$HS&LyUCfs-!r_&QT7rkWiWOsn6QT@SJ{?v)Z|Z}L zjy3YlW>}?m1=`p}j`YkWI@}fltC}S2>Za;<`!U~4LLaCBHrI^$K5K&v!SL4kDvWYD zfTn=veZsC>6UWT82El-7ro~g`mZ^LAzG}Bo+%wej@56}FZ~hQ$-CoDy22Ot#?Qi)g zS%@>B&YF!|7JXVDsA$(ZkpuEP@>4GkyuknP1FtA)2M88QzCdUMT?e8F$K)zBzhL}h z`mjkVZNlpxpk?y0R-=l#jI;YI<%;^Bf2In)f_(&pwu~=d#STpEsVlUK)#c0N(zm~Q zqtyJoI)gjWVka3Zb`023-Ti+W=DAslXE+RW&;W(kKy#2PIizOhj5}TC0Yp=I>b^3q zJV1`*k$i}BktpSW;gNr1p}pa-aSwt^n&KCA6{IP-RO0g4=*WkHp0$R2XQjeXm{9&X?N^ zF}8t+QuVvjgmL%oeBbE6%m7ci^C8%{YW>cue)XD;PcJE@&_sH|kGLOJ97Op)9@>%q zqP~`}T>1s)^q-#TpDlm+9thgaLOFm3k@*UgK+VPI*_w)>c1RyGa(_sLP7%%1DiipI zD24OGplqjE(Nuik>HpnIuL&^b5X_B8uA+d?{jAfso)-265FgMGHOhSLmFIn~*{@KB z?M*un(+3oAPyxBxjkT!Srz5#-8xW~oUQhsHsshjIpn>d!6CZ!F1qVmWG(`dA2p%jx zbDN}hjmxj5)LU$e?Vll0WI#u15Z+}RTvZR(=4b}7%=zGftJinhcD~@OURa6s8~vt@ zRGw&y$At`mA01Q11PUHZQF@_Q@BU9VzpjsxRjW+Z$DH{}-=PJZeAW38R+_(sOXcXG z=EgW%(o^jj$b)|loj@&=IeRjSAqZw*tFp&f%Th-!q<@XZfC01pI&MOhy0C#A(h-1P zbqWXa!{;FgeuP1LgjRO1SxRiEg#!{jVfgq3V}7{?k5kYbDc}QBbM0tyuq{zJNO~!J zr|WB-okFhANC?FLG`5O3NM4B$Ciery7z*=n$B4TX7rTFgBlv_S=|xj!f~K^3RD4M0 zg;>aTk|G8ch$*vev{hmRK0QdK$^bsyodsTgKRh4B%+iEI$cH~P?tX#K6Ur4m9@n8x zgs>WDEEEs?kmM%{K|K}{cb)A+lZR_G?m z`|&U2t1iddZgW zVuJ_rx>=|aZmOns&TIq%%p&g4TX+Q>1*Du*1^@v`JGv{M-8rLavw*wwhr>^aKd~q%YUshf#m16f1dnH;ejEVv#+FYiH>~k>22O zgBQ6YwRlvaF;e+EsNZ;QTC2P+-A1e@n4a;s7D0drAF_@kSkP_Ndf?k_8hm~E%FTmz z3}|8+-!^O{y+GPzCwfet0g)NbSt ztymiy1BIUm!YOzGXl|VkUX?q%e^{7uAKHH%1p`q2K^lGEVN9?X@gAtCxbE5ppv{|M zLqHJ6{BB)9&)30Dk2KOjHjtbLCR3t8e#SJA1?5IrVJID{fj$i8L%goFMhH4~AWCSH zjK5SJvP1C%4Ac}#9kCDa3F4&5$0HG6&yE6wXEJ*rG!M>5f7J*WS$_Z2hu_daCtLwww4y$+0Wa_gR)aa1BdrXTC$x_ zL7hTR3M;7*lc$)lB*-^AYzPmS6;AQv{^AolqF6Ml0)4 zE4#GmAuk)TG8K7XttAEU4g3T{{~QswP^jyn_niWZek$$>x<~&J?a7-`0=R$fQkTF} z3Q;$m_MG3B3Uma!fHXvCo9xxzdXCDO`X}DO(xG?6=~w2lgEkgAr+tFrfm+o9xH?QW zbw&lSlRmCJ1*>$AEx^iMpa__``hOI{^0J9_vTzd!S8>nK_(`9h>|q%MTa-Fd7dQeQ z7hv$!Yyzw<;{%#I=uiy{1L%J?p99#atiSR_Ydufvmu3}JeoISW$>?_;2>?e-m({K zR#qBPx9=vT03A8KcC{T`^FGZiDm5PaQcAa(zcTCaZ3p<3puNct)t0IABYCZr6iISc$C=fgw>N(%2it=?xPV^FVQ27 zx^rUg;(PXqWt;LvVqaolud_)$%`3pIqo@HAlW3diCi;$wiSQg$PV8K4f4Oc!VZP*| zk`F-Pa3T=;G**8A3kJLZI9m_Uu)M;uUIAeRLNcIiKo}K@%eVKEvI5vQ_xR@M!G94+ zQ96iz^%#pNfD!|pwu%H&O)UGc6Hr#kHW#;zI-Ng|HNXCyY3K(`(LcV!{@q_@OC&H@Jc zPVT2rDijT`VckP$)i#{f;4MG4JBXoCk?!faihxB2kG-H#KM$ILXo7+3Ai-y>4&sZW z6@S1MN^XDY_!>M3N`Wk7OR-MEnQ0D+8-zz(F|q~VX4H%kmK1itgZD}K1U6tN$h0|d z+q)XPBnDUUs1_}+aAQperS7sYBIP6lFl!=U7lnx|R(FPjh zC`gE%kpQg&q3Vip-|m{IdUQW?c+OP$d0GY0Mp`ERM`rywkw>tsw_MsBIw>SRS=HjV zp~a`2`PmA9Z{%G3&#DnF7fz(9+@`G!@3OMV87pmG=fiDi2bhT68-yq-V%rTlsP%{FVoe|#wUkE=<9q` z-lE%mGYAw~eb+7VSFgp*uQ%Bv$B~8xhk%lq&S`?Ky+^=NG?+CQCzS(gOfy>bc1R5? zCSugh03HkFAVSf`74NMjFe0R4tEVBSAzy#}qXzK&BCZ0g5%M89`kCbJSOdFd~0uAVu+xM%))i#=k@T+L(O*zw$(!wQB_Esh!Y7*#%GG%n&LfnImpXrq zqqORRS*nz!a6tpPK~Qxc8ml8)Nm!}Bgh(M=#*qj^xvcekpPRIb$tN_(Z6gYrPyqAF zZ@0RYt{quD$=a&_CT{2$1(E;@fT>UW`^cqQ!YI#Vx#8_Vh||GU*VdLRQ~(+OHH*+x zWlFUtlm8qdcVh)*;w-bAhcz{JSyX>VF5Pff-e-feu1okbCtAY01r|X(B6n0+{qM~; z$HstU2nv{_3Ti8Ev3gB3)1ErXUAv^#c`i^58#0S%8QY9a8o06iKT0Rzc8j(p`kvG> zvi@(>2wEr^`F#`I-H%I>#pLYmwU0la{=LB_!Yr@1;9dZWU$EJ37XU;43`~E1rz3^n zGWj>=L=T)*%nIldI%Yuv7B6x#t5w3*U63( zE}Rm0rWqmBX4ilTwk;f>NH7KA69lOsG$*zHx1V3EBF5!?`~AM#1gP~45tj5ID*dyj z9zF^!5QA`s&ZyP`dgW`jm~MZL%_=RNcQ6a>C6+ z%hIw+uQ3sU_WMkplx^ z=+m!CyXgL$r}{8GmK}c}!W!PeRY7=GYUG{D9qRU`Ar~Xhb+FsJax*ajK&x#UC{#^U zVuGK`=T(~HZ~(ItToZT9u7N~!S6hMRjoVcU$UQ=AKA{iw@7jOebOY*BZXrKm&n>17n2y*-SDN&r) z=(ev?f{!-@L-0g+iXeyaH05+|IN<953uRQdur097YpPP+A5_>w1WXPO-$zzkL84=Z zB8Yp0Hi&{6?A9^#6{ASJ_vu10S>$f^MWirj~d?MH_h!*uOO5$Zj9fgG3PXh<1^@6MW$>)Gs&m zLcz*vX-3al1Ffif*zG_l5H9oGhB^;Q0TLqwv=~tqEfaQ#{?&0&KA;PsE@fXWZAjnq z!&{&qdIMgK8iXqlsczyWf%{@DX%UW#5OfHTQGb7<&}e^h(mznq{U;#}KRZmi6j%tKnt)0l`J5dGmxjAElO-JCV) zPzjjS^=_D~KsH_z>Xi>QMwfCJXeC4{qz+no)lJtiMtpr?z!q<7-Yp zhhKl=Q#`2Z14PZl4@jL+tO5lcp#=G8sCb@lC2{rD4O8bfzdQ0I0|bPN^NY%)9i|h- zHq?X~#Eo3sx|_pA`YnElatRuA&YPs#czbp`OqF5tZ~9d>Y0Pgu4}Wc^ zaGE$t(|$RTLP($zyrfMb{!fkKgQR)_sB^2WgO+YPBs8Ql- z;7LbsNa_rF`i=qh^pHyD**l8(5g4Q~lud3I2=@jmj{iG?9dta7R*3O%?uxhBWRi#DM^!8co4)P0wF5s8}p&X~ve6z`O>1P(#vzRH6efGEjmhSd}^_T_(R zvOz%I6^}XWe!lrc{y+{QgX09zrwV%zZek9ZSwJ8Qg3M_3CKrEw{*6w) zZ9{+Uu?7Ca-2LLT0SyZal_=gjo@Wi(hy}{ap)OQ>A_;YxUaSASI^ND{kw7tA>3h=k z{}14_8B!t#Hm?*S(Jv_pU+n>j5x;F;SyhZ`;qMm7@&h)h+w6q`OyPhqhCoMksWRTb z0F`@tFm5$yNGK8jKBmq58BTw$76PMTnu<3sc}3*7vkQgfnxJK(anxtHv%DC|1pod9flJa9LCUzHWqed>BAQ$KHQ2DwKdg`Yb1l zB`riNcoqb|yRMR+^U7?OXL#hlxSRb3MAQi1Ram9p6#0#&BCGHMI3(Uc1F)>SA94$l zt99Hd$fyR_lst_##j4Dv>WgML1Qy!|RY9?N4(p|(RkH?v@lXSYr^>t=l4UcImq=z~ z#ZU&60@OlID1BB?jiZ0{sK_PA@j%XW<#>p$Q`v;zmmGBY;xuM15nS9+scUlng;P2v z6u6WbXm}a7BD;m>mv~Nf=m+#-rd$ZxkM~ZS`|gJ<2B`VI3Asv#xeS*tJzVI29Uq84 zu>gz+9bCgT>IOMb*q9Xu`#)G(%b0BD$gLAY9qKv3R;sAT>F|F=F0GT0Q4LQXnn*xV+F$=8hw|R!c5Zb*Dko_G`8=l+KAa4tGpX*L^iQjvs z9UJs@M~a^$GuwiIAoLBakcV>eM261q_Zn<^NEMTQb2kjokVR)9r{!g&-jX+Yg7QT~ z2zWPzpmQ7WMooWF=^!$w0c`$C+`>c>gdmEhgd&7QR`;L)dV(*K@%zS#9b#E_u>ba# zrQH6{mvnbBv+i77D}r6xL~F@2J!NH#Pdke>FDU0JK$Q8)V1r8een!(6D$ zke^)6Dx-gJpVRb`LXSZg_D)tnI#BQ{Q-1rr+bMtjP5EK+!_>BRD!RVE$g06x-o4Lu zbHJ~HOMi3*Ywrw4gEO7T&)Dvh3JnLX^e*cD-NG2DuZcp~%7p@@-RG4(x_BO5rKIiH>TI~AT6J(t`f=8fBB#*&Pa~@} zz}7R?zz*K!et&0wwy}HeDjKw+T|rIll)-;Vy+S-wK}AeKs@PWCs!*dE`EK+A*5q@{ z&8l0wnPa4Pj2FKyGnsfmQTsBpUUr|wU~~cJ)nQc zZiwnHnaosZ0rA2{3e+=H`&dU-y=O`FHcJ^`xTMcgz*WQyhnqB}rYD0R!>~LJD*hT}P$`mZ^Smq?TZ%l_i5NH5@Idhr^dK#m}MI8wd6h>m}P)?#XX z=;|z~HpQF&GPl0gZAAh)BK+Y2Qlx%gaIJ@fOM697Zg@{6p!KoQHDuYqc^A0QX=ft@~B4%xS(|4U5tNefJQ-3Cb$Tn z!Y|IM-}!)tY!o;Wbx=wG3thlKjqZ`Sl~S}Z5!`goi|psgyd6TqL=khK$GapDLLc1% zF>Fu_gA;bqZ^e+0#K@b6KjeOJjQ4d{sXqXtIpRX-D)>=U$(`Qy+Jgc zGFV(lJ*Y$7Viq_bcI1C)7pGKeR?y+t13M_%@)#9)|>AkA&II#%O zK(7H#5bh|QSFI?@ZN8}PB*PIAOo7L_Au;~ah57>|2pmX5UPONa$ug>#iSKu@21T%> zIo0RzZ5pTmMjec*5f!E#ljeEoj(o_TXV=ju2Y>O(W%iGCYh2fdY{)fl+_%4BKi?*; zIxK37=JfC@K@B!w5NFXH`5-9NG~$!~!QLbea-mF%x+-#eS(xAr+tJ!rx46CRm!np@ ze`*gu&g!hvpD2HS=rm4nL?|0jhdLiU1%5A}BZ3CCZKgn)yJ)fhD^z-Ms)uLl9C}n5 zS_C)s2X?#YMR$SwzH_$92)$gjlwzQEK#VtI!Uf;^D*C-9=njbdz)lGV*pR!KLb5hL ztVso<C|cRi2|$wZ~2r1 zK~w+fBbuNa@+Ej=6kSk>?m&qUKEW2T(7gz;)K{bah5(EOet+uS^h|&YhXi;Af%I)9 z6kI41V+emph#V%h0bCvpT!fo4s>6|0?;iiLf`%w1Z44ijTJ1V3J3QhKfZK`4Da}P6`%A1R(WU%@<|!6AssU{P z4>^!QGJki$9z+ibvjE{N>RK#Vw z2#(M9@OxAiGL}KzKJm)qft@-hT-v=(J0zmzDpxI>>p%oq9RPdd20>k|%`+R?WRn|-Cm;YNC$p15GVxNWjPTS_DCm0K4+p7|M+? zQPO;y19S@hqKs=d#J_-_XUE(+`H11)kNZS_6_Aa-;esN8>MT@La#&o4wp#L0@ofio zTRg-^n+$PMAXq+68d=mR6swO<()NFJsxH=DgGo(NBLG>|OSpE76h75fM`(tNf;9d< z?_?l!f8$0IT;OT?SjyCX;vVy@f)yg0G_uU(Wm^`Z>1W=lKsX8Q0-x{#(gnZVJQ{=9 zMJ6Fo)v2m*U4z#Zq6NNi2L&jLiBe}QP!Ky29RP&^9wmSW9}s!=`$rqTr3HUf!GZ^< zG%tyKfFlx{(Ein_{4w$&1Qr0-Hx~nfZe&DGqdd_a)Q{kx6WN*aDhAr9?v(ei;eQj@ z1Ph&3ML;so#}$ZFgZx3HxbVJ~Elu_@#6HndyxPS6;E-~}F9$aEfEbf$fglK(I~@dl z54)VrRXtS7KX-rZ9_mb1e#%y=z1Ojn%qqt$7M?{#t4FsjUoF!&O-rqQ z+{Nd}ra{PaxdfJms&t~D5jJ!0msW~Zhelw;4nnITv2)7=(rEF3UFJC_uHXnM+9orddyQk5p%$SSXE?gyG4Hkp3xY)38)O% z!(g8stShyuGo#Ytp~-SwJ%eii2pY>}Bf!lcEt~F)8*fu2Ab$M~a%pSQs4tVj=^6n8 zet{TsgfSVjI!tXC>Q>x8iiLc! z>Xj+7^+4+=o-O~g8IG#rHGSJ&1dI3O4>nCvnzIUhrrN0Og7c`yU=yB=N84=y~h?P^@crh5;98a!;2M}>I4XWknes%xLpb6OWS{=i6 zvQ%nNKu|CCz|5bS9S+nL0)pm&({-~A zZDu7rH{bI@p{{><+f29q%2r{g&u@B4VfADj+7VDb;yCa;*5CqWvZ`!2I4_!8IoT>a zS-~lpQF2*s0W12{OYkG}>%wQCf+r?^YZct?=SZg%5mI~65QVIbfK+ox0mPQ71o`uP zt~Gd%4N3BwVHdyl&v}_VmYTM$;`XR~n0jhg!y_g{43&RnhzLJUHB_ZBNL0%Y)79Zw zN>Q2Opauk!esn-_x`|Lgnj{6Fcp(=dMaEP->u`sNWa+nV*I=z)G+)$hq&Pc0?G+p-I?2>6f7FdQPrNOmIQxp7Jup%N`WE^_kGkRSOeYvE9;2f zNTT*wbw)QY5IxX<0TEjO6pr{@-BfhQeW?|v>_m&xI51HPslCc~O(7(x_i*uBY!N61 zcgYpS2aPYqjOQyW%_y)eo``7X9XKE#tsZF^5CpH4S(Q;JMmNZ$87bTr`m{jGZ=ro)+5&q=mS!T+pW0-TYg?|8j_R}$PqsM zyh_|Bo+ivxiw#UhhrpjMqI*SqhBs^f1TFr-WD47%%uX^WIhj)kkkLbncEbp@CeQ;7SiX`s0L9^db}9`ST#BzVY zR?`v-fA(wqNi-eEiy~TJOFkki5Fk~+Sd?>tM2Quy=k(AJ;;5Zu2et})nI6MWR6Yf- zbiiDE&p(<0Vxnio8^I=%Lr@41{0!#RP_)O_;GC3XMx<<&w?R?8oTA~kngTau$z$LVjr){oX)1Fr3+MVZhfCxt{hUDKXAIO+^ zt-C&Xys!QVcfn3S^`t=H`|>={2ZD>r;Q}${Q0e)eF%d#kd14R|d=6y!6ZL;EaHC?4 zK9hgjO2LvvYHFoBZ!Z9?kY?f(?znyc<|}f93(B+HRQ~A+vfOw2haNy2c{w&Hz5*lM z<$wAG>cXkl#5r;tZj=71R{J%82aTo2PAW+PXKBL+8@*@XNNj2G+X&F3{o&xLbr{Kg zx+(PAc1SW4C?bwySt`+fHzR-O^K=rCiZs;)miK0Jylh18t2O}B&-1feI;pCK7hhGj zfCd~(lw}n9_ZqA9G!eMyyFvAGFG3iQP2?|}E+~Vu_OV8@$E2EH*m1Q>02Xt~ujAX% z9XgN=H!en{98fs7EvS9aBZB9_Agy?^{bB(X4Si&Ko};jW+7M%9s)v6{y%8G@LfebC zq4F463)P?g=0sX91M(6=t)K?`u7$9q$S1o}58OnkSg1k`_vnckH@&Ng5Pkz=+TuhJ zfLP)A7wM>|1Yk3O0o_R*X4DhY>cyAwpvqQwUwdx_aPkLh+A@)x5d|$WO?v979Vq!T zYGpR0f}_R~c@fy*wVQv2iLiJcUUsWgd7RnLLko8P%OUg&r9UUr?ZsM?j3RIY;yv0< zN-$**S)FA>h-!i;x&ki*ynjrkD#dBO5 zQ2j*+YP^3Lb@q!N(2Fy$D?kxsJh@+vWaFI`{$%f!dmYnZLaTbsJ_{G&_boP z>#pl)wX@4~>6jFjbu-;AX{l&TyEfV%>yynqYhcIrGw|2oZ5f0j#`mT>K`bZe2_s^S zUM!8<^>cu$W8vN;8m#JKKmr;&>~6->H%2Ggs=A;`UJrji<>-Xq9Oz`?_8=$*H2XTX z5;*TXqwFJqF7l+25RFz-k|bnXrLV)_3V31rg@eRgagwsoY=3%pX#t$r`}SgOQGwEN zdV!k6H+Z}Q^dyv8*`m3fC~mOefw)lq1SQdX4Z}PYOUk3R1Ppb?xpk9&f50b-DY_aK zGVc}UUMPPOF=BppFsbQ^9Xn)U7q9Rg=jJCo4v~KC59MMXAfWl^rtqVmI->`8s6FGE zmg}IkydC`+&Sbdn6H^9dK2d4RNO-gQticXLM{K6gs7IjD5Q(or+VaYWsHyJKuMR059$0{%PByHgYi=Xjm1 z)e{Gs<;=Ji-Le8yKI#SLh28>mr;YtodkGv+1mCraT1!ullNEbHymE8?=sqy~9RPu0 znP7kMQoJ)s64gi+MPLHym4tFniWsOGPyozCKjNgKR0m@FcDgQ*0MZ86`C11#0zk*` zL7uLq`LO&%7UCo8=jT;^itE{3YATcAQ+H5{9Cj&@2`xq2{D5e~8Wl2hnScqamU!2< zg~|d6QioS5f=D5iD)I>ppJH-zx#V7&f!=?FJLoyYM-r&c#>fC1Kh=ODA%wjzlfrfh+<|pu8r(kDj<9} zb74T%s8NcL+z;-v`}sDHl*VcSAIaIEvY;%qkx_V$=*Ue(kk^Q3cRoofHNyvvtHOWz zgJ%#8xdibpf-hK=AGao1;<#JkN>`Ac!gg}7P+~Wc?ZoV>={$r{0N1@LW`KuD>%bCP%X4P8)PPFE8xQ6xg4}a5Lk9Vk#D_! z5b15x1e21%#7Wia(EysM01qHhxI}-3+TA`Mn3s<3N5VF78s4m4V`PG5Kl}W)q=<{9 zC?!6B(Lu}jDe4GG$z96E?3wCeVCP3saQ}{hU$AGm8m_V~0HZbujLm4l>ViIg?~RYg zcvv9LD?;aIHlEod5oL3T#8Z4KSMZu3?8~q_TFWxRf0dsRSPf_g3tSQ!{CR)K(q~aG ziDfojd~sn>gKf?B)Lm$cxG~b?N93o=z`@f$@P%`%j>8@dRSC{*jw!RC?W?_sKyeV&&JDf2|Q_Oo@xDygM-*xF`qt$;jiZcbOp4?jj!twFtb>0O)`GnQP8QMxpUj z$jUDZt%d-$_-uo`wi4Xs7-TP3KN>KV^z-Mv;f^R6r3gC?;&92WTMN z`YLVAL^M!NYG=R#MTo&!KgAYHgQ@qqK_C&AK}^lzW)V=a=7k&Y5d!%mB2L6yBB7c5 zVl;LGn^E9+IWU&bpa_2(PnDpk=^z?~?DJ(v1pExC=ic$%c-r&^;cM&Q?$HFwATYKL z_i_)%*Pf-5I|T-cA>^ha0>0sRtPrcgPsD{2flPDajX!8cfN^NPIJ#sPa;!_y7HBGQ zx{#?>iNIP6XXKOtFTkX2FD}>`?JtGNPtgN zl60L&6rQZ-P~KNQA^;~HLw4;}E1x}45A?)O3T`-u!RI`C9e!wC_eD>}oOJUUxaCTw zKmz&ViF?3$NVojF2lU9t0MEi(^wTH0BR3+6`&eS-_Sk=w69i8==|&j-ggm|7WsTA* zys7JeIuG};St$<0QKM(M-|E;uj*Nj&AZE~5aKf(rL`SXJ8YmM}z?xxM*UYjcsYXge$4_jF{FlGZV7g0w_O7lJNM?+Ep5d&eOx?}|Y-jax~{s?$N zr-Rj)O2>bCph-l4ol}7nUA|5VCOUW(S^bUk%|wce!{54mvBd;Hjvv%H0Q_>*Q+t0Cwp3$`eyizTta0mmv;gMcA~N%v z_fBR?2HxEf>3y+n$%m76>(jRqRttzDGCSn0_9IfsdPAZ0LKmvx+IBta8x)gl{_3IW`8R4T2c8E>!`p0FfUHf2TEgwNH24VUS0Iq@?gLdrdOFDJDEVQK)lCAw`y+_r(?f*`(0# zb7YZ%4>6#0F_+|iL@sJKo`|8R@(HY{12TV6xqQ2wW+-1^vmLt7aX>FFcAbl5Ij<7) zt~Ln~T;-nYR$x$uv~ykk3c3;qcmL>93F?KsrmgPLL$W%7c{~M2R2L0+%_HR8%1b_JQbfOH@FojGW|dYn1F%(0`EOwhTvB=Tz7w; zWndKlIk*TERbTpHsDNcfSRfbU3BT+Wf-9Z}}dnfR2GhbnzmA z*J3X~rY9O$>(gx%Axwwc;fg(h!g+MEKn-FhKJnX#jDTstC@GDG$Jv^EGC(c&PDGku zf^HZcz=)3H_fSplBEK0*7@hO#spWs7pln1tB$xebYp6NHdG$<6i=NmAs7V!$R8O2s zz;z;}XqXM}={}4^pua9w{c*r4ioO@PuTe@9s0_^RxIX(w$#bNU7Ww_L31u;7mNh88 zSfFTWs>{%W6%NC}_WSzE`kiR|{=?U@&;7mhjH=`Tn5Z!TAMu{=dYNwnX;Vfd*6x!* z-N=6)_3ACZ_oCdaD2!@UzaM`xgq;pVchhB zs2?=wA-wELj%orv*{$!iN`XU5JctIu5cf=Rq>N#Ew3V9}sRa%UoID8Ex-3cV8%SF$ z(d!%9Q5Pu$v-m%i0Ez*oWmT|?Ke*V#tGJ9vkf7Coh-q_Zr7lfTX!G1@>WYJ|bI z59uU6@w0;y1Aq|v2;OT}01yNI$fLpJ#(g0*CS!}_QT2u~ zXzjvkQ00jw_(hr+0_K0ig3HtXctK%R=Ln+lE!W9r)eDh;x2XMdRZxG2?$!F|#tuu9w;qa7G z+k|yr1DoM*4N3qeq`X4gCbap_Ix<2dzz9 z74azfTD`Wb5m5X$SwUCd4fN5ci2x7TucV95weM9x#a(9DMEy4s^6AyhYVPp9OQin% zTe1#nlDk`jp0j^*$)dDgG;6#31oIDQ(S;n~0Wp$qp00s9EH$ssH#Hwn1xNSS1ewk3 zK>!+`6ZYL~vpy!z+g?#kf|SJylVxWA$wB_|?OT4k#ik>W&%cvt420JC_@R1tqFfyxE(ZOx#ua5$Y-Q`(|+ zU=p$E7s_~tOk?{hj10&ibOlV%ERv%t6ks(eHaUP6 z^LxrTeUl;vmkA8qFn#_RQuW3=cd)ThT(;#=*ND#8{U;q& zpxSyz=(>N(Rw81^se&MhYxi%*O-jXI?0{e(iqYLTsnJx8u%`9AIO{itL;Ot7M_2kN z2ivXovAJzoARs~;2!ftcv8}W93~FiYlMazg>JknjA%CzU0R<`=+Srhr}TLJ~GFcWsL6t5NB)Qp zd*N(LGA+357MvtnimY}gX9_qTgM0vLG>t=xs6(*;hflPFLEPc*0KT0< z5}R_ofg&~30Mcx9u?R8$P#WFtGJ}6?(D#)so5|%g*+Orz*GogHRUl<|aO%09O0q+v zp~NEBsi_i=#He$W9c0RLtC1u@cRhFX5o; zDh`n5GYvq2f2T}bE_MqyAK_}1hWU(?H+X8juU*g$VkU0QDCJ3`EdG=nOP)2`}m1c@HHp)LMk?&+a&%u|`N-f(s&0v;nekL+Yx`jJd zYi!_w&cF7;!NIzSb5KnEs;{RJPiCGKg-b0Bv}vgok#~aeEckvU=p_8{~JUsDgkj7Dl%}Ff(G!*ghGF;`f=%czL7(x z?^GHO5c@3Mr^t;C(jXqd3+4wa6J4^dGm#ew#Nz7!a6pg0LRI~Msk?lQ$lm#Ydt=CkYjQ@C6?9(NrPt ziU#q{gRWs&*Lk9L_Uw$(qH4FU4#vPqgs?4kD)|U4f;{_y;=gk5CDCs0Zts&xR_M}A_dlC^Bo*^joDGe z9qOZK5y<}`LgZZOjJF=D3v&n5!pQRJ5dsB2$o2h_I)?fk^X9U|##9(G(e1f$=iXvlv1!3X%{bqDKu6Cq(OT%5cbNE_>L2v zsa0VB=3e{0dDgS@q3DBqOu$G06p-5VP&+^k4=5tp6&xmS_l91UYh~uQyU&9drz^uq zgj>6k>uutHuVJ;R?Hbdts@n53mxy#(n+{sQYI3Ivs$+qor%*%lKw_sx3;}F=$PF<> z_ldDZQz_|o_|DiYO~!(z$=i84L0No&o|FY}5C`2Y#q*@TSbOGb{byd)kwDi9$V;QB zvrlIV5v);YE{co@@>CAjU_*72kx@TSp8V8oq5lGZgo~nJZRH|O7g8>86r@KpO+q-Y zsQ_0TsKf0&g!hv1_aHimhE~u5+yNilH4Xsu<%5X;Cl-7Pp$GSPK)I<2qppJ&~}ZtUZ%D%0N@~Dd|)jkDgozB4&+0AUx%tALsVfW)I~2l zMMf~OgkXs|`F5^>>Sap5ohGW>)f~l`pkJEQUTa(^8z}?HQD#Kw0ZJD;OQ1z6=q!~3 zw>Go_v{Up&>Q&BP>p4lZ#ICB7ZnI(lqlg55fMQh{D3M0GsA+yEf}_EnzyrL~py(!4 zVq|f9Dyz((n@PF=+PQqVsy4fv%POGI5Rp|Wm?k6<&V;ifU@k(f9Z$CBjrjzK>mst-qAezWFBO7H zCPO5#fB@1THL54%{uMg6xW~h6)ml^``+F)SR3N?kHMtsZQ#0FMn(>kZkYm^+{@Px* z?)Sa419%EI8Js3nEuD9{zeLxRNd>AIS~3J@*JwNq`vM6+iIb%4^D%ZuO`c&FA|djq zd4)FV2H0&K5c#YK%l2jA2(!Uh(>SoPepM(eIS!4mOG{{$xm7E7AN!0<-@N3+hW(kA>>HO9p^|EaCm73WxZ>$_n|% z%WvS08v#PdFybdD6xFdRjR%c@-_Zhl1)x>|+G=}{ zSb#3Z09t8r<2Y)S2mm1RVycCbd1(}0)fMTzb8oCTa739g=qOo77%bs)i9ti1V`2d= zVl2N%0`{6TC9^G-W3GbNrJ#W~IUtNn;l%)$Uwvjv$zppz5f27iL05palHHQ@1eU0X zXXSaYkI2O9MvOqg2mvrwNyrVOnASWQB%z~P|XtHRq*4Ccv60QKThx{-HJam0q_ zU?Vi~dsO_6N}KT(uk@+-vNlQ_;w5rXBK#3sDvU9DgbLz+sZNBZ*{#C~t3V6T33^H= z_bEhbbmWGb2!S())4ZI9r+@;;DBCI(8nP59qTQ?fdAI;NdIg{WlB8O+%z5Eagg;)p~_fe=3HjU|6|={bJ?9T0kS;p!H4?;nxSEOQ))_!@v#b+ zG+-*+{-Fout*Q}c@bd~ZBNB6H8gl4;tLMK@xl18a52j!iIwr_lLQVDAbWp38akr~D^<{cEUe@UT1yzDGPV0}JIcu9uXEGc*YvL^ z(5sA2(!-t}a44?6h+P)J;fhe}*<`Zo^I0GX38t?*j-U}LHt4Z($~4Z2Kgwq5G(DL` z=)Ckl-zS9fSqQv-S1$Ge-d{6foOO1WoBty)+8$lmt7Cl!#DvAHHA+!OTvo3zFnm z!#n0lDwl6JeR0wabB?1LvSy_YWj6os5z!7;`#6XdqhCdJhTvp{PU}st(RJ~#gq3$` zDIr7d;4<Bb&=Z2nnAR*yLElG=9GWjns|sULYR0C?f8 zh?bB*8;uL9##K-9u@b3sPzy0>>d$ z2g(3y04#I|FIz!*k zAfZ*4v250N=-_CP%&)Pm#!40_XrPL4pITP5(bA286Q4En$Z8PDpb5l&JO13Y+2o{i2 zK2Yv|kV~yIOHZIAs;&Ab+QAKfAP_CQk<->I(~<-gc6gqXi|NXe1flr9kHxT12-jmf z!ju|u!bqsl7aVLiTlHh2z1Og+a|-ASe2`8P;@1-uCZ?oX*E|uE{dPEcwod=(St8iP zO{QO1@1cCzs-e)h*IQ*Cg}Qxy;@3)qy=rHsU#&}sFTwd+p3)NdJ> zSjL|97*N4>$r(E)haw0bUorBR$dk2&tjmahnwd~qv<0zY z%Vbjb-ss0rrvg$6kYzZ3ssWz=$~~)PTHPNNV|;*(ItUu#S(LUS#%MXQnn9S9(?=cDy?qb-pTKQnCv2a2e3f9SP;hz8BJ>p^5%J^;E* zg=hiQs<=>XbRPS_k)WP+Qy4IGoMA>ukWzaAVyZbHxNGe zbbi1AQZvT6_^Y+Kf3tcd6ap4Wd76^w0BEC&9ej~owd~S=VY_Z>pY&DP@&fWe9}B`D z1mBQ3SdC=-K$K`LtNoj)C|~xnN)~FPg?V7ASON@^6KU!CjNJxty1g!v5h&LUrymdi z6H~IRaKH60y05ShPWE^L0cjI7AWgS9)0OK=j?Ip|D%#Z+SffM=H$&v7fHqBCh@t|aXuxv12rfQC0L;N%*Oelm9NlOh{7|e7w}61u zQaWd{WmOQ~4VFAQR*Ygs>w51_ZkZ zF#;c`qfp}bX|j;sdZ`^PDSJ9J4__sJ+Pi2OxgJ1wUk(v1>I89kh_&dH0+CEY zVQipPwB68?K-i*?1mg9%9Alo+>G3y!dc03ZouL2>s4GHNVkOI7AZR#1kOL<%77a`Q z)(UQ5ctA*O8Ybmca8KQAbE+RcsS6845rjaJYt4GHnCp@v5%oav$%;kAkH*2-3Rir8 z^!+64#2ch)L>l}m6swPJiL~g{7uQ7)J8;`!S%slj@3K(-8E;<~71&X_aP`S#RN?Q+ zUPQ!zA^=@Xuz4az0tb8$J4H-G6>0=_V0%~63T}vuy6woR?x(#B5<~%ZCkX|tXJP#i z^bk-sR)_|g-M`d+Mh>AocNAjmlW)U zm5SZnkdjm+_N6ka1J%@Cm5N=6loa!Mk|t{lNtnqB>?bU;0xv?ScY>-wk^y9YPKN{% z2abyQrsMvc+^)p$wkppNU5>_MyT!v4DE-mjn`C%YUrgx8;(bphqYW&80BLpDxW+mP z9~TjjqVcysAl5r_kw65O)-{3-z6u|`xDY#&I=rGNS~R#a-b37w3_cSh3qBTBL;xx~ z7)gL^N{EgZd^+?Y6?VJ$!pqu>#3J@2D8?<;<$ z*kytTvQT>9m-0G~yMCop0sD;ba$rjpA16s)(jL4mYK~F|{CD@fY`$3D>|G zl&<$beX7sa|K9JS!+k_zb=YD+3bKohN>vMpugPku(@pOuX~86G2}70uCKzA=!|may zkbUSISnh~GE|+jX_lahI+-aVMl3nj$wQRkyYg5^L*zg-I1Q~%Dch!cu6l2H%BLAUH zE5!XkDEcmRN}XRGR6;-*v(R7zE1rp=aI|m(c|@6!@J*kFu@V6{yHp>dY2V*^TX`$8 zbLh}KMp)2_v@HT-r62*69)I(SRKlEyQ``nWdV!>tTiJFLH&;`C)b%W`v@D7NCQLPs zAW$+H!ja5abLAH7rOG z*?&{3A{1s}b`gCt3!Wr1MbbEk>cmI@a|8mnG_ibE%}w945|9d0Iz^zIYN=TOawl@r zBh1Psh^+Kfh={3wYCbt^Qb(0U50>_R5VA;%ROXAiNx+M#qDw6tVGI_aQNR+?WC%dh z2tKka3#IJEToF#yP#}jn%Y#4`ofkE>em5)Go7DYusS&%Mim7Q8aeNF4A#Qa|_$UY( zO$dO5hCS)$IQutnkOBqk%*TLRVx#HJz#^hn3o(h~1+`XxLZLSMqYxox#x``_J8i)| z6nMG67slf5h^Q)<4b(b8`_n2ov`28-lv&l@ba>PYL=tZz$N;%gUyoxyWaeN+O`+XL zzwlkwAE;F%oDYuNBEz8`6fvn- zR4gdI_<&@8fKG7gD}lMR08Rhen15o->idBe-t7h~NiQesp)PwM;t#Yrw;k*YrU(EF zoQwtM5ThcwYRptPKWC<{+xJK0Uz8qLd=krqywTAMWhgXdUoq)4lCV|;s8=y#A}Y6i z{hpKKPz{ZDNpDmjTuEGzZH@Y3b$!@rod@wG)~wbY=hM^* zjMyx|dWeXlMS-<#w{ju+N3ej8Lk@N0ppojF@k14y>_4xXe*~oOb3OIVc|?&>Xxd@Z z&mbE08w`jqY`f9EjGG{9tHCmLN zEAAgOwxChS3 zATEPaR&W}H9E}EG7p*_l{6InTS$J;+U3|!0fA^6(v;JB^JEu34J1|Pexb=KPx|%dD z00gp8>nc8oimjM{3+4y{Xw^(j<&;Bes74cio4FDp$G!E8e=meTQl{sGX9lXE6Aoyg zOsrf(#QkC#N~1RTaU)9lP+4YxoqKApNQ%}d8}D)t#0UpQ*C%^1Sc~;Xv_S_WU#GuX zqFX?=?{$){mWPOT04?hR31yepMh>wo>zeXmV~QH_2z?@_;{ftwXQ4m^F{+MO05rM^9m@-={@#4F6I!f79OVqf3Y--w zAyZiZK&IGcH^aU%042oBPCR$@zeb-EoTu@OqyxqCiw7$ls{KNy&B$DN4N{7mJlH}= zZ`g_)TLWe-Xe~U?j4~W}o^P(EucPiqp`DUi703qi04}>qZ^aAQ9^33a;Zi7nBoJX% zh!%7H*Z6=xujsNsp3lCKS1IaBtoM7#l93h6q3+EpKY1h{R)=v#ju=;$Q;5A@f0LK6 zlM(JVL4n>F#CQu#ATJI{%7fSxe4jGuB&ij$rGdTp9X$-5#8JX{(%9j>Q6I$y6dIR3 zwi`taUag>nVGasg?>BlntZqqv7I}^Y9zXg`K&^^a`1SqypCHbxqP1*esTjKYi?f>V znS-+6Z5BBgcHC$E7ARA9`!Ce+%u&^dod1udwsESrQl9eHGU6xwx#y83SB)E2f_Ea44#tS4QHDpwIQ}SmL^z|sN?s_bJoc<@Le3#~i|}A`TF;Ym;z|D;a=y)b zQ$@`K)1y+1up zDd00Zy*eSVReq{OIRh5KufLi>`< z>9-W*WPI%aze~ln}oR^pO7r0wCb$l3CB!s6U&M;}$PV_>lBgNqy&!?V!@T@yq967$+ z(EP2*bk1)*`B=`__Y1FU@IL7=TIJ$}{X<5(T!Q?~qKxZL28V~0=ZrH~c8|-eW_ys< zaOoW26?C2@KK#{x8eCu6=i?1IBAu3s?w8zC|7XH7e1_xTUJq~&3uQJ}LAXnZJ2r~9 z`_r29S+jR`5ALVJ$=z;brXV@he7)`qMEKsLGMQH|BZHkK>?YA=T4&Zzfs5trbz#JGi6%l$H#Gn3n&7c~5& z!3BBEirv`xz9*uKJ!>%sXYz%}piH~ovDxeFhoSMZWzCd3vtOA>mtlFWIk+WUWuZ*{ za4|WQY1f5l?w(H_Ie%GSt>f@sacnZVB}k4>AF|KQa{Ktr@#PA8oXIela?&d~P8<@iniLDdde8RuxunyjDCm|vY`g>aS-#EfBSu5=Rm47wIC zcB5gvySv&wgSR|@06-ra^gQV^@3P*+Y;fXGlJ$iriHrSyE%Mgny<%c>UcogmJ-8xm ze_5y~<3&82MWVsx>L_@&d!{dQG*EQwo`O>z<0?XblPgs6yir~Ihw(Bd`Jy;9ug8uT zF&WqQn5mfl+yoFe3saP`--v0LCcoM6^RiDgP7Jh1#qz>#@L2zP?d{r?;hz2YwNjh# zfahxifN3Ysu>t(|6_p%{)14^ynSHD?+On#Bd_T9_*ituTRxB&ND@lQOh2Q3xqXxmR zf+CfFNm4iYsg?gplr?+t6N`P*oWmE9(CoejF6Lh4T9_Dj!jm?ggh7^eDLq^>lmgK` z=4FNlF7^6aOc7|sC8M@?zBdDU$r&#P+*94!AZW2 zb5jJ4|Ha2m2zY7n1cK#r@B{}Q)z;&++wnAiy}z%1aP}5hmoN3P-+MKMaj=T#W|-SB zobRi5f`cI`F_7!4$L+kE7|l^A>4Pj@{B&q36=}K_L6T%kM^{C?taOos)kE0s!m9IA9Sph=eR3;A&3J zao3?8#4e^V>2?eoZ;r#lu-Ikqv zTavAJ2PU6-z2$XX1cJ8x5J3k2q&;99+eIeOhvpwoid^G=q40RUMG z&bz_@fGs_Jj+J~|1nPVii(^7)=``=hBkcs0NkVAbH@z;M5AEiS`LmDT6K|D&%7`aa z(|SGQ+Aaz}2tX1O)j89>lT0h~DIs+)4*{pMwO{7!)x$Xvta{HhRL|jdKunrZ@PGjT zaaSP##c-CF(sq@?Uoy#ak#+Q24^QiwO4*ZqZN_|Qx9v>~)wWemiEug9OO|!TV96Z( z#qWfKg#d&8T|r>|m(IixVPo=t8--QOf?r3oLpdoP&$Nd8IO?LAtQ=PIJFHBn%b#f| zm9{h9SShak;gYiD{>vL^Rq1Eq%aG)wTy8!mfp^LbK(!ni5Cn+7a$_R z4v6@us>w{7$8*B(dKo5}ZY8#TIROYl9ph$dbTL*9Mt0hdB=S9NO-^Bd_~cyrm8q_E z-Ymf)tWtY_A6BX7&Zz^PA^rqN00;xVV?@g1WNKWyvsR}+RGn2GVDux->(aMR1}B^fLI8j>7Dq=v z;;G@!_;oQ~PjvOfTEa>~CwXX2%HxS>rK;yMX5nLgKYhRxo8(I1F)6_$!!j&e!F{dqj|CUVyKG33fa7j^-RvIrauh(y%(UnfisPA_q)m5-*9iz$yxMQ zX5f5_xX&7E&$biz6kp=XY&lO5+a)HyHyM{Q`Cg;}#F=e9Q{;Io>+lf8E3)mzSQ#&P zPO$|lRa;zt3R@BBv~meA6KPs(GMJ~dt{#~m;;;e>ZF~J>Py`-#C(qx`x6RJ7?-qB} z?NeRl_a5V8gi~5?#`r=22d)#qEfgW4K2#w91EHw<4BR`sLpI~Xd@KI(WqS-uNYu;( zilSIt$zhl)k_N7gwt&88BO3An0Eqx(U za)^X>L$L2`y>6m5gysD8{uHS*+95be)7@78zz6^zr4y{D(;$(5sna=mNpH+&XR4pc z)Xelhj_g|~sNIE^ok&OqGX?ht&Kxd&BR~i@k6M`CYHow-FxJF8eLR#^!w%zv3sZ@w zrpM%ee8V@1wlZ`@F4%r2wh)8?{PLpVOl0n&~6|2hWgN9I3fBOBE?mnzR zjNqJznQMNG&mVPDA?ZzQ)@v**{d&LKM!?IGRHb8(N z4U$lt*Z>d)^j6Lvoa@CgVfBMkfpWi#BS+nT`)+S!-6)>Zb)^^jIV$Lgc=~p1$qE`D zQLAN4FOQwXv)=*`04Y(^9E`*I~@PJ(F=?*?yi5V#;7KTooF)bBFTwSWBr_t{}TChrw&iF*xV;j4(Ao0ODLz|N8Z^>}Y)TN{5Kwr~C8 zaC`CiqA319HhBDGGGzUbFfeKM#Kdkr$)0Iek4Acg67#^ewLhK~TxiZpES5Wd*6`&t zr(oSM`vUgY`t(H@P*Tue#7^IqMQ|X0@7aPaX9o;aFs1o2(zlV&c6$}v2tl0vtq~FR zI2}(I{pD;5rg)*(^>Rt)-hdDQIKI+6-^<3f`uX@m00xZ<{Nhr;`x1P%00aSYH6St| zHgQ}&gXkTm*L}2loA7DYNt{BfRDLMumw%0&Cb$v}-ci!_zZxR(5bbtG?UAE@L9;5k zT_i=VWs{B8<4^z)20Al}*dPc3)q0^i?{l(2hi~N4>c&2k9?mdvkc@X*C5$Q=8SqK9 zQut_vSES(>@2r+N$NcC=c-fmdX@{DE$y6c51c)Ep=MN7&#^sn!vqygBwzpmdDJJ1Q{#3t zMW2qHs@lA8DXUo!u>LjbNms@~j2twVk~X#WH^ER(I6Iq17SSt6=?Yo+T^;}4H|#&p z23Pa4WcF@in~IHFr6(7g1&jK;E!pQP>4eyPpfsEQA7IW_5j{>hm|G)%dX|!TGA;}? z*AYl0$CUi_78U|k3Y&E^$nxvfX>hgwcU4M`(d>q=F5N_4d6KR7?fmrQs9D7ueJ_1{ zR}8UWzLy}*+@%asC5VeGd8w@XkWky9#`XAavYzYaVn_Hmj^p`Oj=Eh;VoMGWr1*$t zKBgYn#Xiat*S?y>$B);4!6?L(q4;V&+lb|)v-1qK(xHWX{U$^Z00H#=*e+s=&z7H% ztgz{!uC(zH?eq7sm==b-J2sjdb|Hd z$M4Q3ZUf5$DFZRL_JI$bp=wq9>7e7SUzSa&lD4t=#}|BhJgGi^4avVw*szMk0SE){ z?Ybkr*ZL~VEo544dTHf4-_agKLc?m%4rrBlj_%R@meq>-b-yKN#sw=o4EG&LuN4?T z5C^ln;enJl4=SyRV{XiS3UhuE#MslRr z5Zn`s*YNMOc?j))|Kf~(20BVLLied7Sk51nGKvqsA};m!u`<%%Hdm)p2awsPzs^i? zuI;*CHG|W5inuAw-QS^qC931ocOuxhCsbaNyBfB*zAe%uX48%KCcvG)nG z%pR|G6I9Bqqa}XXf%XIZz@w2HwiFSIci-ueAKzU)z}aJe<~vW!Ha^?s>WCuU$@=(qUnU%TEzf`h+f;L;X9O=Hru@lUGF z*I|y`2gR3vvWadko;y$WS%97@SwhE*S2aY_AceYaZ#&~Jc%_f0!L`XIdQwt6W;NO+ zi{R`(?$)MocASB%jm37u|Ksw7;9I0syi{bsPvP&i^W@&$aisXd-EeTr4S2{z0AqWEmXFoV0 zl&?UasyOY*Yw;xj`&}AaQ{*HIg zsdyJ~pI#po7fy3j7;-xa{rBS@Yobzq{%ai}tzEVOe$V!t7_}>iLM6#$RLJX6je_wI<=j5Mt`6O7Tya<2O(zcv` zQD%kvk7%r(1Txk9e`lGa9!B(6VK$!-_6>c**HZ~uXnS{T?cbhzos!TOn!c!r05vNo0|mI|Y~O#Ya=86`Sv3!0T_*^0GA|A4P%|HC?f^U1G6Sx%m` zy#&u<*(mj+VBzM)X|hr+>0U=CyotDfL5Xw-0syBujbVfr)uiVi_f+qaT7r=$H`&>t zLvPbXlJ4oZAq#TweUQ*gqvDXuke?Xp0 z*oEpif}h0rFR7S)_f9uM0}5B?oJw3yfBF1*j-+z>-qN+7n&Vjh{_EU-bMHAiU)W-j zF<*@jRCyb{5|jo|m%lcnaD0wu7n#;GB-t4AvjgfYsQ!UOL)OL z+&#mS70xmE^IiGjm^coql(d_5O3F5mBBo?H)9_@qsuSJBhBe-*0V%FRQuac;RpZ#rW&IV#ubY^O)(IQdN6Rm5;+ljvIl1B!ZJ|AIpS?WWg+L zr(9;In0K2io}@cI9R9IPC2-QAOKN^srS15ixZPM9twpkna$Z{6otIUE+I9@a9ADjq4U)M z0RTlVDcc!;^EJ!m@QqE9I}(BbfGGmwKb7e}jCDTL6n?A6=;n2j`0 z>N;F^4Ufy}2A}sfV*cOP24Z^C&5;Ifo^+hPJg*XysJ-%!I&8Eja@i=F6>7J$mOuQM zmyXH{E0ojd+S#vU51 zGkRoypmLeUM2p)Dmm8HuVp58mXq9)kIC9f%dA3l*-iWZ(SnpFd|Rand0YdaTw*ZrJg+jn_#%?(yd?&J2m%98fF1z>1K8`^ zoUaL`)g%RwADEj)n^fHq7Csk~GBXowt)PYL4}j zVo`&4;Ev<{%-#0xRz_NSB!5>cv_e)VH52WMo?gudGf9WoQd2o^_W4jofdnam0E7e; zIv_y!PfBC<8X8#j5w6TbL)}JFcl{&)AiwH;jv7ob`JUsYppqB@DjjA!c9=G~ev=)4 zPZsygV4uCbiH3b0%4NAyYI1tc<7k(`Oi>k~%RjBDSdBlO{9s!)@UqE^ZNVXvLc{jl zv5##Y{?nA%X*}v3PiD`Yn*C8#nCeM!fEVNiU<8CSIZQLEqGU zAIFS@Lrh0BmQF>NKUK7Em#LTT{oDJtY&$GA6)wl&YT4RVX8M2BZn#mA)v7;#1oWL< zuN|i0W%A4Xc<#XMFd3d@2Ch%R$h!5l-(|Yg@2VGin#))&8h(8l1RE=((*HCttln;h zrVrV14;Wj-O$$N*fH6S`0t3K; zs6az7v9~dWNn>lKH)g$S>a>u5(SUI%^EfEF_up^esL*z^VRzhH*AU}nic%VlGJK+K z%JCNb?PjUio`n~)_Eel=n;7LR_!KGv394<}+)_lTcBv?Wpqp=Iu2+J&s;OL&z5>*4{0il&S@PFM=sN@c%)b zf1BSYL19ljbY|F~_-P9Y+YD6EEId7jO>uPI130=tr(?`1ToO|UEY9yfFKP(**KI)BKPl;d}{g< zlROW&II$_NnN`o!dMN2-;$FOS-v`3F+4}lyf)m=k;#hh$dnDyP9#&S2-Q6qls*Fl` z!S49uElBH^5op+6mOd0Y9+!G1DQ+6YNf2AP%(UpgW*&_S5k6f5?6DJx zXO8k}e@2FX0fu?USKRAAOFJ{LKYncv>Tp(^i^rAv?6bz`JC`43MlJOQa5}x(%NXWr z;&I3@2LJMWZcZ+;pAHDoO#;`DtA{8641(~OKn1V_Arbe!gtZ_aFk6b=MXHt@?sHIX z^P!w=X^Iq)ujI}3A;o0+OLz8~^2e^N8hi;4_Sb`din>P)6!Cbhh!DD1=TKk>e99k@ zAb(>!qWca%ujO>|Fm%D{J$IFRh30r1(@YBxQB^_3@rsdxC1h1Q7Cx!E2?; zNC*og5D=Omgf~?B4!(S02O|g*W(@S6y>E4&Rl5xM; zF{fmIw&S!jR(3z%?3n&bnoQel*a8p)?gRo9ak#o^8Qkrv03V=25QzjJxex$OVMN?d zA=|Ae59049fw6CsAJCaA6){ZTrQjI(F^(ju=FlEe`kIKV+8p=!AG68lI66E`M?af6EgR};TOpk-x}n7tKf)`o>D?=9WmK z$;j$-4=;LC483wioQQCG`OgZr-s!jIujGXeM<>T%00;t|vL*(wGd)^yY4AD@N!1;H zWOSPSwyWC6oNzbQqiXZCpfWl-|1de!mucK5{IA{%8UK zgj7!>v08Z-Gshmg-e_JcLD<_cvZ<%1ey2&t2FHW4pS^({v_&knC1e1#ga7~pr9=QU zq5u=jJO!+PAtnPBG6;P(F8?x4tcqoSwfE?d>pBWHljPv<>NyNxr>`?s9EBKhK_Q&} z;s{Fo_KybAVYro5zdcnGi<0?dQYoi`Uyr8WW!T^!)SifT;zJ+Zx#qDmUza`F^o-Y&=$;y?(9@1Rc3s`cXXH@h+Ktx1^9p=^k*TiCvhnd-!oZ_T~K zd&!YA+%m+L3xgR&`5~m2u_D!fA3=-LdNP2%rk?}vjF&fBnAc9-tq1@Bi17fdNC5b$ z{w;r*=@Lf|_d9Yr0}6Yps4_787ae^i1->e22f2}sj0EM0Dvu9uKdra!UM?b?_f_wm zNC4N#tdK!zV1z{YCRwX;c~u2o96ZGJC%DZ+@upDHVQi?2nVLOUur|c@1Sq*mVgg-ynqnxAV61|zUMpr$(db( z0o{pkeT0HFrRlqZ2m%1&czNszQ}k6Zo-mdF-OWCxj^R9?Sx>G{(u*Hx#*4KO;j;@( zdx9w+Rh$G(dZ!LtruXt@`NjmMOXC7OEKP^#j?*KG=&N2K}3<$P}%1AqWP6%c?8Rv344OcptFc3VWW zHY(hyPq!a5#9SZ)c)HV*8mUz0PN(JCiUMvqYBy; z+vm^fqp)e+wVyqGGljZbs?2Q~ZB^?_X?T~F1&qCo+6-X;0w4eYK&x1IdPgN3wYljT zIey1~Fg)%`KB6w%PKDJ$8l0*j7SP3nW$R(^y3fKksZj(W07}k)Bcziq-}{*q)#h5y zaH5A85=7^YT@V4FN;o(A_m8XJu78lItErZrMIfJ+NdiQX&(MAu#dmYO5Nut`4LJq3 z%&hSWAGAA!3qX!{#o_&vNza`Rj_9;?UEuD29zK13)$uWakWk5Zd}~_?-~bOw2*DMk zh&ukd%wne2GePy(v$UtSb+)&^=bEp}#1qUO0uSX80`@f?cXN-++-1Qf#5I6vgn|Hl zZ@Vm)&67UQEW15i22lCMr}ZF#6V7Orq;n`@E2k4y)W*9VQ!&*#B7daNkSf;WwwQu{ zS=9FS)`=Xi`NLRsz_3I(vhS10K=T61g^9sHfeiy|8|P!QX}h_3lIbkSUMS=C zQ)LS2xy^!K2f zAMD$q3vQ?sxcaz-^R+ABWz35b(~q@$QNTHgXKYBcheOgM#YUv1Cf^_~O+yW`enzkl?C46f!y z{X+-gDW@>>g%yfd5-d7^7ku<2{DFTC)?;Q#;* ze={bh?GXzWbA!IGO|CYn^%ptHq+!_IJmtKK=5$NnCd$eNTiLk_{Q^J;Hv&26h!b7wJDVnbfAjB} zUMiOJ8L-x6-uUk{5m_xHHA!A}HmdytFdXLoQl~c+8mIjvZ~gLC&N$v;6D$Nnm?2Aq zQdOF28Fb2#=!1i;=Mt3NlJ{vpvWP$s14tkUcs;$me8;s6CrqPj(H@!gGJ`!qVXkdd z?@6_{hoxA;KqqPI2nbH??ygTSe?51*epIzl(6nCevOiVz8aC^_hbe! zY4RR%)fBB_&>aozvPK5;2Fq~VY8O(4IiX16hgeIY@5a|?$J?ZRq4eU};eiUUc0E48bw`OGqeJWln73}4&ZqyxsEH_|J?e{Jn)S_a2Q z_uMd0uKXOx1oRr(_CAWtoZujsplzjbyY#8$sPf%PEUdO~df2C$Z~klFSk*EU?!-i{yBF$dZhmL z-VCN6X(_&$QUDV^WmqA?e>qyE5Ar9JhsWCZ*|~FbtLCh-tXMACg76m0nZsjowX{?Z zGPypinBasU0AYqU}z4PC0BKS9ZI9us1e{$BF#h}P9Y=dYZ z4R`!Y2c{93h1N<+FtRu6wCWfPtwijfe{2?WrMbrVE)eYo$Xtqh zk0l5WK_c3mEvxtze{5nA)yWmYy@cJd(bu**wK4RK+$b^4OT)oy@#0Tvq{dr$aPfZf zYi)K)4dqTF5KJby(w%9(W5m;IQXz)ZifO)kGjx&ZE~a&$gdhxJ*g#*<3rm(s*m-fdyAv0g7d^6VmvpTXc)e=(_6<6LZK;&4%l zH3ZCF5QHKC5C9U~#`blqFG(g2`OK_ux!E3?Dt8>;S&iQ-?x>NCQQzEivfXI(z*>Mw zLWeOcH$<;slKbS>Mai*+=XCr0q}k{ws|QAxE@FxSN1Vm=7rK{icj;QHn1BcPKmq?i zv+#M>`6E<;e)xq(eo%S|El5|Q&SE0M!G}Drkg-FlT;3U2P1Octu zmjD0|!9HWt{C<|UAFB_mw5#Wv$~XIWu*M&GEZVlCll!(4-o{R9NE*i0PMp9${9vq; zO>)2h1U7hU^|tjTtY#M(hoZan1R{Bq@q?vg{~A&zIy^tG(X2+!tmH*cuOTPzv#LUxYoUlIq^nfrQ305||Z zyW3s!I?4<05z+ayG?_PigC7MQa-#G1r=!~S#{EbDc8LS?+M*fY1H}8O0FFY5Mb7*` ztuw*IZ+_VIu3t*AMAT-thkK=K%6nZpsWd9@e~18WfdF+g?qsr0N#`v)IUl>q@EBpb ztyl7|m6eT4DciouS&ygMAaei$0HQ=o%B>9mA^5$3Apl1|SGzm2@ci-??5ElqNw;Of zknLqP5nYxVr$`?St9!BpI?Ta2md~8B;p21z&l|ZW1$eN?_q|$~MppkSXaNWS;t+&3 zf6Nc#r8VzM$NvPsEm?t1zo+$l?%3IOwk7V8TX^m<$P^)ioifpG-*oZ(6;$r`ZD6Xt zOqp=M5%l70ep^DKyt^fWXqqp1_GEb`K6$u?D|WSoPqy!ay{z5NMt8cz#8Ec6=xKBB z-BJMRcNn3itnzxd1+>oG-sI5EMD9qHd#-OFtX?{ikf88{nG`ifHTT>`yuAEJ-&IPTs7B(-y6+k2>lucTx z^=8dSSh?k+wpz}9WF^olU{qQ8SbWkNiS`xDH*!%39S||9ld(#dH15hv4Js4$e-?FW zG1hE?0EM(62mm3H%ghh}A!EQ|{nTpXPC8QxPC@kid=)m0>aK@4boM{nJ-#_*&HW$6 zN~x>hc_BN;T7XCb(R#Pf@6URWa;Ue7cG5?{%-GOKC<7XifhJDfWU%4y9esQCB3bx2 zSMm3mvN)sa5fLW{WbJ?u064zdf3>X_$AsH1w{7oF{ZjEMK9q;$&|#CScF8Y&Mg?Oa z+zYqf8E3&(+z^BT_5d}gzCa1mVpcOYkY>(qA0lS0FNl)atXrQm=w~ZYJicx9)#&|8pX49DZ6DyEXl)e@tE;6u71KnOq)>$I3ficeh? z;efhzs&@`wdZQAsn(3}?tC_!M`G<;C(WT_A zXPUdra7#9_i|anWZeFK5&bR(*Kj4X=yU(~Z>~5p>x&pfy+@|(ce=cVCp=(rgT5qSN zThn69b+&cpDDttrlz|^JruQ`;ACUWKNd?=&=J`rCo$CB-og1c|h`K@nJ*}5U#k`kuC`uA^u~|;F7FwUZKFhFI%MI@1fS^?jnL>~d%K@Fr1>8`;@l zd$-XbiJgZ{dtLokD3V65{!Wd2EYy?8ZGj-2%HOf>^+tL#e;W&iq0NvD>(tZM=Kq+Z zWR&Wlzy5T4WPp2|n+OJ5q#pSGa5ioDVjo$!N1J+&fj*=l@*4w!q z?;x!7UU{XDf9ufOe1xlz)Lt+I0T0_vZfY;kwT_niTdl7FtqJuY&0(#R1OJQf_4;@+ zK4-JWdd78x_|yiqCf`3%@UF!N#f6-#Apuhu0uThTRQ~odXz?KCvW+D0auV3^L08m$ z>(cA^BRO@eI*u7zXQP>_NEZM=5Wr0<$C)SNJE_dfe`ZmL%YE%L(P7{P0DVI-9Wl)P0SK4{WC;aBX-((d|TEk|%cc7i1oM?J+pm#kCec`5cpB1+w`} zNKchy*!t>-t=3;8$LT#a9mloAKeX<$N!d&g1OYAKt!gHqmRC)S5Y?c;rhie>YvUd1 zypn54ec5@E4Fpe*xfiP^d7`+v#N^HMS-iR{lt;ue|>vhEp`EadWTIJH~;_z z1B2{ZTL=r}ZGWE{F;<8Z`+@0jdiE@Z&E%G03j&|0yTJuj^Te#w{4`D zr;;_rlrh0IxKm_N|z{~k} zmQ>n$U zb}9$YvVKd#rtP2Bc6g<1UT~vVdZ&{y=YN_zk)<2H+}W7?NkE41LJVilXdnmzV6=0r z0TS)+NbbxcvlqGU0?PfG$>q+1~u?Cg5O!yK?FuNA|RDf^bczrvRvf3WF?&Hqr3_`k2U zpZ&m>wj_f^%Lok`1g6*T<*2I?@%cSj!+99ewZm29dFTt-e_~nxY>yY z1gT%Df5xdZkXdKG5E~+C8Eg7=v7FAsKgZnPul6FJ4x7eVdkC>YRU5`V&?we!&BEXp_P&FGdy4}vZJfBWr3+{)%@VH)Kl;5P4u zr?1)0xL_^!Bx`wdCqz~Zo~k)>vSI9f^cDb6CLDYAUPjeOwDr08j+SxCW;curDn>ax!pLDu44Dt9h%x{tTlh&Y%lLPsjM$ARi`GA*1&#_OfW_xz%z zf1KqwWgeK{mP!xc+C|ZDXE!o*#GAyoQGa{q6eBv^f240nL>KJUxk4_lY&Q5@@x|$q zXP%zja1VPiq&D@Cd~>%y1!ek~=o9PR_SIy?bC84}4C#mj0i^;0K73A_sS|sV^C+@) zU-rMw^VhogXL0aU&m95jSfo!007xmPf0`F+r`d#GO5@~YHhUfoqesT~KkS36(;^7o zCi{`le{EcT#l&i!zXGV(lu#VMJd~86DHzw5ytn4+MW|?s;NkJ1q4^nquuERuKL)e@ z`APB9guNG20Wd%ifI_8<=JICW*Xw$-%{^Y%M>}4HU$7;hMjRT%@`bez`n@Ws;sKb* zECh1Z`j2z2chs?i!9sFK1n__rPdY3>AmEUyd8fP3?YCH22M>fRha>i>^H^JS zUx+0B$oQO60W>;KMp?IT!1ezT2m7E&1s3H%5(^50f1gvuk%*_@X(KoMkK^aDX#Qmq ze|qF_Pb{yj@)}K?-BQt_ZLjrFW+?Qf^i)H_9-0Zy6lGs$Q;uiLVGr>0olm{}ue#B3e?KKgw2}-t1>%()=$w{`=T<@~& z=BF4q`w8q;h%`-rj0H4^fFR)z;pZ{h+J{OGNd$xeA>oI%&uM_^E@uHC`|$hZe_07O z{43%rIp}Zeoavcuue$uFrrT|I8`y=P;J$z3RS_Uff}p2-00bbLgm2eAaJ50&+x2ueZ_2wbI{OYx;}a&KY@fFKA&0fAGk{!9O&MqaKmZXUV8Q2r8(vm+>*J~K#-3s~ z@`z|o`J(8TtG;{Bl# z@yM!LD`vFp(N=lq_Kt^U6QW56S`iK^1R45?Kiy)THmI}NAVz&nC7=Lbpk9;_Wxj=;5`r#D_6M$ zzO8npQ7Rc-a<)Z22x~qC6McQ`Y2wwshNTmAw3^q50~keHDKTat2q8iclf@O^&!8lc zTl-3MrZ0xuxhnz?03iq(f9aoMkOuWS!%x3YMT_&k-g8yUWj06rZB$CN%9sCHW^~N- zlD>(XRTR9rj_q6)!qDUXZ5?Ko#UBdOX}V7dq0J>UwM`&-nMYcw;Ve0y=gH(``0-jd zu2BF285oNX#udco9UmhH=$!$EjQPihG}~c3X$~s{AqWB>Ar1RIe-H%C5qSO#AOJ!f zi~izQ2;?Wai?HK?e0Bw+3 zU7Xv0f5iNP?IxoePqVkd{oAVoE?k04mU#NA&Y}SrynFx%LlW#J6G6A_$ME}Pga`_F zTK<=(g6HF?p1}XMf7tRtJ@*Y$D@=1qD$NBoQ7G`0%X0a|UjK(7AKh0JfRb5lpD%u~ zaluJl0zJ&S0-n7tk3i-#a zOh0ppjJx|Wt+K=9YEN{ZRy;x|dCi)*7`{X$&RtdikN^-Te}Di0dHlBnI>(c9e?;+95+fkEw#SWqQ?&AqOXO**LJ`p{_ODgZwi--s+nxhcH4e0bB#$g+zS!0 zUvBwXeK7e2v~)ru?!-Ea1L4E6fAj$WLL>l!0Hx^_9B_gU5?233Wrp*uuV>nH`_&0f z!@D*MVvBWoe{=tTtZ2yurKtG3#?RwlSLHC;pFxtAPu(b+tMQ!D(+N3bpNvcE6C(VW z!1YzV6MQqWvppz429vWcl+D4js`4VUOQc6X?Ud$6X3aaEC(%I1D8?Su9J zDmSoFAQun)Is^ktyWd=N6FMgkhl9mTF;mT^=@E|7a~P_B_6orZ4!YSo=v}qyAV`8< z(S55o*lPQaO`j(rGLo;cQsw#*LBL|Ew0;X0%vB!J-I1^YLq1=No#}WLAUgPyj%*HE z6U2Guf4Pq0&~>7qTx>hM9zQF^+4H;}#85%RxPO=e3u9O&Qg%NgZ-fB|0zkg_+vQenjh~+CT@VQD{(H&{N9LX! zZr^p;rERFn`ErXoax$!(!&$>i5JArREx1bXf0~I6+IE*Qu3FcGcUtlC zK~tdcKSuDPD2-q%p+gG_QZMa^&X*PY;S zL<%2H7Aek8iO1qxeK{?jW9{-~o_JcelTw5dP$9f-^ijpEj?qXa=40Hbd9qOSyz6p+ zkX@KRwBU{xUKEnc*(3supA|o2k@2~Y^%s29Ybrc+5G0UL03GrcFBfa!={8qh_A{8> zOkTIGZ8azTD*SYQvxv%?PM+3?f0ht|5ZG4+VNaXsa5EgQ|{Z?J7{kv`LR<37r11$vC7ZAXN9toYdo|dqZ zNh6($Z$Mw&;DBkSbx%6y{Ccq?(oPx*;S=l^ zlloq=;5kK1qg>KmGsJ=ce~oNzNJlshPB$YQnpQR!h~{QOpuhr&x8KlE8<>XsTkY|( znyF5tLA2ZdcNX(L|G?YAmUsXVgh(N|DF{u{W?A!1ojiZ%HNGRFbO!43?|cZX0Ig?j3PC(-Z$f2g@g$`#;HTr#%Br^6 z8zwgBD%Y?7imA(zNvj9#GE`zkIhFh-7&fX{v1%p)E%uI$Fu=s>Tr2%{`pcW%GVUcM-92;*DYvb&-;< z{lAYW-4zT+)kvJEuoHv6^yw&?@Cj7qLF>+sUlknp>^%wIk5jdo(J6DT{wm0K-4Sd3 z6*Ac;e>b+PcFXlwqQgs{fL_E@ej4RHFg<_?I=WaaUVE0DfG$Y@&80#d;RdsixBE3P zSMup!qq0rse$I;eEL1cW0PAcOPPW%$jYCm4nA?H^{=O9~q-8W;QlAr8?Pt(-%IGR} zwPcboNi(q6dh0w_N&R+3LM4pR5o-yFV5g$Qf3cSo0RTcEAqOIO$DLI@e??%;NqP$3 zUoRWVG65y0QqnZiOg@5DF}FnEb|e!y=BfQ~1L9iun_VBcIhR!7`-_YX`i{*W5ld2w zvzq88ObG-OT|q#Q39XydtkYImK=>LXhj8c73${dNf^t>VJhCX6473N`+&4;}uhogDr4Kug}9 zWAq@9QN+|LcZtZ94Mnmw7Q4%tbz8H&2uh6)UuxL>qwO-sYc3NHxEA*Uf15*E&W zhScavi2P=aSC|Co>bIbhfglES_y*}K8O`f`9`lj#B$NRFR?BTfOp2bwZWL0gQr+bEma2Ade;d0_ zKjaE$oB~>qC`x%AHcp@ZW@MdoE#N(d_w1z}W)nJ~ug~Xr(NDYI1b_#!Kmq>aQ31g4 zJURVMRGMt*wy0hv@o|5m0eKK66&hL~Tjta)w()M}Jv+{EDf5Z}3nCB_~Pzf<@KfI5TlcSWl7W}tf$}43o-)8|J z`&-DLlh1K58`PrDVd#(m_Q4O9S^wHhC0bXN`fs;PM6Yj&O8q`pV~Irpn249IPNL21 zs1N`$8P8z$EVMdxhg=BEX_mUA!nrx#X6BVhvljgqVGx3@%F$g_C3E#}e>cpr&cx&* zm>(!RimhuSJNPeiSzbTQ73gYvuc*g3RVWM7A;m#qy3ahG*YUXIAF^eBR|E>& zMs_m>NB}xkDR87!5-Q4&LAzO0wf#D3q`r~-Ri(2!eFAnWX(9x@V0+nVYJgs86d^{x z<5;T{;Gk3|GzAkbqba-6-zYhhMqxbs!~*$R-ri}_brEYH3JY)jZN91iLiL&BsL&8d zN#Ln!4pwVke;R0`x!-7al8;n&bFcwpB>bf3!6ls-Yz{x7t0L5U0J}Pz>LR-tIT>=O! ze{AwuI`$Tdo}Jiw+;TuZ=e7sm?xY0d;RG2rU;CNZcbl+AReY0ya+BhB8f2QkI%kjKDl4+X)n|2jGGE=fl8*%MWO;#Y+FD7d#a1s9 zK}NqJtW-b=q5%u{Vzw*fYA1X!0*atQZmXeCC2lmTPys>^A!nELM3??^KP>*UGv2QU z+Q5ZtY3ubgfVry7goyn}kC{CCeSS2PYOrYaMyjd10&cC&Ftx~}EK^_nFA$ju*M*HRM(^Y3Et+i>m z91w2|ImP}uHmN=XLp%HZkH|^5N~9u>9{W<>YHfRJw~L*#COcvu^zV=ox-T~=a*zJ) zXR`33dzG+_;(ftXRbeMqe?YaD#YZEB0c4kIuuT6s6{vh_}ENNI(F2)fmq&_B2VpkRX@)DJ<$iECpN-b5 z;-I;FHAE!mx%ttDRCqfNG$ghe{*{FVyg<|{0uk z^ucaa;H|_g(;19F6qZ@<9=!k5yG&;4`EtKa{9bMU;~q-BCV*LONfqXyG>wr)(sv+8 z=Q(_(7t2XN4{(;sd=Ys-jyHxNQMLK2XKzJOP1JT-e^-y+fCz%d$UjvNFU_MtWtER| zwo{XvmPw#%ylFD501(9BrxxiT^u%2+(yYVoz$tl^oeSd5?g)?9I0=l8mn)=3aRc74 zQv5&wu!PU=w*~-I%*!#g=K|WIpxZstVg0^hBR?stFPrE1k3QQZ$Kne71!74vy{|!3 zX$AZef5d|M2+<>W-prXIa%Etrxqk7?KrkQ;Iy0}J&7XgpfrZaf{n+}6uz=avC5ODD zdGH3AOiQbW``G*cfC5?2QX~@%(3Ds1;Rpo&+T3GE9RPz^pl@q+`wcq$pi_1fp$GWw zijwM0CX5P5qC+vN(x{rq!jHTEsdYqBS_uqse}0t5D$QtO8P!s+fKXS17N8>9dstmx z<^fXfNkOywzpdk12z)u=rK`Q%RDdbI_ybcG6WN@{^wHj^7`s4=ZKQ_&KNs^6oam=D_0DB*XJ|9AAK*Cr|ft)_}U`d*;u<^M(a z0%dWyQ$-ohl1gzs&f;{p4;N#Z_mN-EfB06A0uEZm%z>C#)CIXXl1`7_y#f#J_0(x& zo7i^s-UjRv3zQ{OB>>Ila{!E<8R_^Vd+^NXcz}@tvMUFgts68Ugr-*hL130hlSKgM z>u1&+kEhA_e>G~VqgU@rL|$Z~N44!C_i}>ottKsNKBiE<8 z1QK7SzF1_w&n{ii6lxP?0L9%gx$1zhNp??0k>UEQ^^)xGX2dKL(27b(cgo+t6c<_V zaKKOZSR<>&dnhJOm@hvpEE6vht|R;10AG@5pc(4SpD}V*gRekwQe9?me~8U5GPW28 z78Qqb)D#irJ8qxB27(j@(wlHj{Sp|ZE{Fu0VhJ|T7aoVHUd!})Oh6^y8~Rki%|py{ z9?W!*ApELmVd96FNd_$qw^6bsxhQqMZ_-E*V!ir~`>Bt$RR};HkI(8*i9c#4%ivcC zLa5xi3P-jFgEar{muBbnf1moZYe9N+0UIAj#;Ho6cPF+~M=gMsiv*d)a@F`$RZ?4Q*U{)>bh6+@Uz%Tq z{*nY`7!;NEg&kSpx9l_7xwr+|$K+?WQ+tD*su6xVJG}0{`_HQ2ENv9VXPW;f z{J_X4xU7yJfB&Z2gdOf$Ww)d#1X?hL!cj81VhNb&0#T%pARz4ge%y~gKN8nTVn8gN zZ&8QG$XYodj;niH1$)u2z9I|S-&Qr+))f<#OKbt}DK~dh| z<06%$7HOB++8M7e@6>Bn@){f`KoT9K8Nz;Ef9cED_;J5l zlwXhJlI)64^WD%=Cs3yv>$3-y|L_r}J2R_qeZ0AWQZ1(>405;HlaU1K%+T=IT z+7#(X1ooj6A~my_f1fMNMJg1|J%0)r;mMDU7YRz9J6)oU40NF5ea1!1i<&$YgqF%rY7qjaEnEUPOe~CBW ziZonbR=F*)$)q|-=AQMgwA?4agu{BMQ4|ALdAG?p`pW_-^i!si8x*P|i>_7YmkngX zlY*d4u=DRKoS+%sv&+MK;x@mfQ1sDVW_3T^nB;;ql}@x&80nMJ<-wv(S{)5I*@Bq48xAN|tC*wH-+| zaRO8OjZIypux2;#vd>WsU@x_i<+K@yfmBqJ?rK0UlL{mwk}e`&?rJeEe?nt>=%h)$ z*d`O;iQG-XD>+sq-ZG|}yj4{dh%8;*O%p+J*rKzq%~8b9MGIGiicoL!?bnFR??A2| z1r1P&U6A(p`D7CF^(mVbe5lg-`YSo8h?&nk1g&dpf`&8YrJ|K7T^cE7sv@{*75}{) zMJF3R03lZS6{esaS-OB zTGApEq!RBz#yD;|fkzc~vVPzpdYa2OZN5e-eB~?mx%3TA}4N7CKYvg z#8P#9#&tFG>v}6h5GZm>3IvTroZoKfxN9x`aV148TD%LFmV*eef0sdAHG2D}0CF~2 z<-;496lxHi`(aK+Db=a$dRXzqoLW8)&-U(!o)qt=c&h(WIiX2qUNURinxMp;mKYMP%)$ z5^^CRi&Kl`Nt!T`@`Kpzh!K1#e^wYeqNyG4s5wyfW~0EVe`pX1hl*SGBknjWj@`&X5U&+sIWc(m)6IHR?qy@&nQoW)rWdRorku3u393{CndBk3^XWAAbU% ztL$cG$^mn*0w1jx&<1KM)+s_W-W4Pem~ZrgjLZPKNB5F&0MU6;;aTFTO1<->=ZJ)i z-B$B4q9sUGf5TK&SkpBErz$8^?h>j2RhK9lO8Bd~w17Dazv7Man8=F06~e+SBgrUV zaJH0xJW|F4rcKds(%cs-cWU3xKnryuuclKi(-m=jg%h#ls?3EBjCy(`2*S(K(O+cEO`Kmk+g zARd-HM$t$Wrc*@EPt_kbvn;g=x62P)K$g`p!mS=X#_$wFdVxMwWpO)SUC)=XoZKaJ ziGAHB+{8vGBS?vFNvE!bO8>tERPanNKiV=+z!ZvsA(aX^AFh!O46#54a%mC(XB0pN zn2Pmae-Oem+@peIwgR6B0t=KqX%%okukN#sh}!yvSscrzsONCvm$WWYJC+d;-levvohzEbq z0l~~>p4`V(^ffuq4}luPM-(fuRh92g1stt^e-t12Lmh0EXBhyF!ul%QDL2JZfe47d zRc<_D0P-#y(EvbaAr1*A!J}?S1!Ih@%EqsIIr}p4Wq_AWLq(WHB~$`NNl@`;N&(1` z!YEXwnCoQv>yCg(gT|HrT~6FD`S-->RAQf|u)pmHAo-XM-)x}(Af@My&mG+`K0li+ ze?`Yx)^!3Baqp-;IYr=U2sD>+G0=Loc3aRqD{ z3dPoO16=vJSFxsQNq%0`<=p{l`y#IRfAaQeWaABE>A9dnMluVGL^}E0#TH>`ux^|^ zH;gJzspt@p-dca(olyPISay%HU}_0>-XZL+83!*}RhZc%w&DnnnE*Xo+9C_~Y50?g zf9+;N;jw}=NLxPK9!ht3RdDv@RBF%++9NN;b*KO*5A~b*7Kt8rJsS>B7AbP%f1z>p z5eYGQpAO4@0VRc!z}3~ebQLOA&cdTQgzN_QIMxaleb1q?L^E4ZByAg4YL}_bx+YF#-lNgph7Z5R#hYU zuP()q)#6af5CmDm1d;@&8n24>fBD;FcQaXKAUxU-qfP&P`wdr@Cv-z+2W^waO=Z9j zN{gISHGE-fGX&l3!o~e7yTG=&ng&y2TtKnu=P-{acvX2@s~D*_%5e8==BK$pglV^y zfY~OLkeygu59Fl##*w%)JBrbDkRcw9Dwcnnt0<}j?g13A!|JFtA0P3Cf4Cq*LUF@T zW}7gh*ORqNa8j~11mxg8iZGkKU?skvF~ohF>0YUyK)la0-=i%4KsFro2B*76D{Mf7 zopymf&GXtFy&9c~0#WRQSlK={$u1Ivpc2VH$(mIqa)glOha?m&u$GkatiTNlb3pM! zTbD$eM%@I?=mDjvBA8kge?>qvxxhwGS}Pe_P8c0dbs40y){&!WmWwmph8z4tC?~>X)T~nluHa;;mETg0H*A*-mryMe}8lR4cD^~M7&th zNtl37KUtc9OtDHOI#s?%|F)7(^GK>qVL?#qbWu25>1~Y3OX%n=CU1tsd>>r*TA!TJ zN+_u{ntx!XN_AKO4lnIW6mU{qa7qvv+je<>-eJkb-z!#SUNCsUVE>8&6v`OPZEE;0EzROUu>*S%FEcu>_e=!3ku^ zKrGc^0Ki$5Tx{$_p=l{>)@x4+7eg;eK)!o=`C^GUnR@YPe=4TRmMT+ZUwGn*M5q9i zcEmoL5Q$7s4Qziq#GLZO(-kLm&vvz;nfb~DooijZbMvJFao3%oLPEbkK=dq?;Sc>j zmL#soK$`B9dKz#;ufYD1S$9Q`AQR40x5uDDGFM#<{5biH@4st6z3dPR6>2g^B*sxt zTpXeSKAy-be-zLHd-zvmxl}P$XG7Q`&%ZW5EG7E^82LIfEB;95(mX6*`h&6hKpIV$ zK%#D{il(Yfked9pf0PJFN_F)deFL%B@949n2uM&* za&xEs(OH+){93CwZ317Vvm&yQdz)+}BgO$`Wt}<*qtcji&>0a+CV)iOUv1cYv_i?^ z_+n)C2!>lz-P}#(QInOa|2Ns?7EM-PRH;v;^bV+@ES;dg6?&COp9lw6`t$_}=&ZM4 z-${Zje}^YOjm-)Xv)~p!3l@%w@h7p=7ddnE3K8`fRsQ===f%O+08>D$zYt8KslAw@ zxXAt8jI%G~YH5_3ulZ;C{*+d+t3usm{qmCO3{o|{BB7q;T>%-)B!Brtqln2*QCupk zGs)eybCefjEal?4)o$ofpLE6;T=DCOfRi1nH)(zyd#F zv-4^|2dfC$eYpUZi!~@{4WCSPRlPPuBMV$Z!4};S| zDniqxkmz1zpd{s0qT%&GrT;vtRDfmj$R#8I5$aUZ-5$}s>?V* zeOo6_fS;B)%ssKx;O03tvRnI9c@x>;cJU}BgRc3e(XV~mVuG18gmgYoBmqN`c zs*Awg&EzKPjPA^-EvKo9|0CZme7{8)Esk)i;ADDpWJYN+f&f_Nf{(v1+v3r&%BV&k z(tm1*@}|nIc2;C4&LtydRTUri3^%TQ?^H|c+Myo9We|d7N zMV4Yg8FW0^?c7wAmGTiAUN4-C_ZJy2c-#!oNyK@7r$I!06;mBz5;yJr0Grg`QoZun zcs>;(a46em>a8oY)S0LQTcB&u8QKegw104DdErvA!~PMP*FjnWvgpEvFI8jy&Vp;D znFs-1gw9Eg!eLQ>M84fCij2+?y7Xb9rhZQuE!xi2>)0Crp)t!9@zqJQ3n zPDSuhmTfF(P-UK00TGP~8Vf6G{wEx;7u~SVJHS^&lFd+Ga(i2q)N?ypl-w1zN)=mV z*af`MIk)=7ic?|a9%C$~hr#EnlMXbHCK5VQ0DXQNgqBx?muLseuc(+)qDrV|tv@ixngDD`;| zUaXry8ion@1P0pb{`Y?V0041a9CEz=Gc|h5_#~NPNgd>!qhF#eNC7HU>$2ZZnW3F( z5n9Z${|cy!C8V9_D8NWoVt+)HKnx^VfESgfP<^>HV#)9>_vxIf0AOyHp+ZWCDpO;4 z5uc)eb=i)OPzcKC5};!5{dEA9Wj4RoHaZ{^EL>(9eI?`yZs94khy|}}>hoP^e-vb@ zAR!#<_A#bQ%fiv9vGs-8)`-sWa{7u(6ata5q^T$S@hV>zy{QFhI)6DCihy-$J@G~? zeH>*b>PU8eE)Hc;lTZ$1wMgIh^Q^b(^|IvvqfmZ{)LHDE-0(JFe1zT*zK>AW*k>u0^8(RKQN_2Gqm{Wc}fGg);{H^AHZ8+niM4K9K;j)GN}=jiSo&!zcx+T76{z z@+>4(<91q49e+@j&IrzP05Zwfg&`>+Hxi?K?TguXl^z{Czp% z!!YtyqV4i30Zpo?1ja(38BKEj7NAM@Hh=rQMK23yuk_1RXccnECL0wVAqfBg zA2fu;GO|Dgn+Gj@H9p3|IqYK80||*x2%YMn7+5yg6@O?bfqb6FCz?1C+JcOJpr8>g zk~p|N*I)bN{rtGJUyGr;)JZzJiCz6BsXDdYvQk?QgVhCQ02@g~3+K1kme-{7 zUm!1s`hUlYHpMxd2=b{|^E1tJxCACyF_zgtpMwcoH zO43X~n*Dg+v+}iiDg#gfGhOH(L=t|x8h?e#`!9aCps)3(fKmYm!srn7c{@nHNB7e2 z^f26C-u#mn^(!HViZuX|lYE7C~VG!=rywj*4gY=@ZOGKf5AR6zj<|Yf^ z)A#UJlu8}}R!&+d$F?LVzJ#-@|4K>QY@#l=+=Oh#ieW1LnqNHAIn3yJywhOy!w`=T%3!zO$ga#u77-1AmnPau`KMo|rrY znn-Mrk65i$mWS4zvtUGT)h7P-r|76fPU^ee@vJ*e%U+1{vvjHcZ$}q0z6ga|h0UeQ zKY!btPEv!?-p8hMuXH_S(NdwKq<^INJdYO6sn)p?*#%6@prqGMsVP$4G!-Q(WxkspCAhn5`PAJ5YlG2 zloZPdWIo9_w%{t9QsHlkmVm>VxA0(mc3Ei+Ra17y0EJByzR@Fq`yop6qXH%;t^`Vk zw_4bUUeW)lSt~-zt=-<7xYFgC2i$@v zbVf9MW~=PA0=)kuqcyHUBY*P3xwr=w1c^cXr6VzsOBvkzG}|5Sc@QLoOPmB9PGvwb zF;)BN9q`<3t23{nJ&}(J2A&9wuaw9vw@Abb*#M`Av0bO0poE54Lu2ti_f+YtvH)+p zms_jxG;CjI8Im(NA5Oqv`>GT06@6-yFCDsz;2}_j*#UwY95?dgm46!D;zdWp6ezFi z?tZ~lw6Sl){Jf!L02=;MXR24#RGq0J)Nr>Ic;uKjl zOPsPA_{q_>`k_^305!B64H$6eTQGga{$2TBfIZ+q;~&QW#}iNu!B9}Wf)%o-0S5IC z)K$38%?@vcpps2lP8Y{iZE?bsD!>@Xz@Fs)6h7m6)}sqitQg>dq43UE30fmR_&?k# zYJ&8z16%iB(Lqg9*lY{E2p8e~&XlcP`&{jIyj&~*h<{w^jN}YFx#UDNd$~XW{voA+ zqtFjNG-Oli8zjU=GNuC0j?>@6*_LXg)EYLZh(9pHz=#m(mkZ2c6IWLvI6#3c=b|`% zX^QU(yAlv9S`ZBBEqk}S-OUw_9((%AV`B*fFtcC{|-5@j-V9)AflT+dFTS3 zsRDf>sDJSRStrxWm1On_)+?^zbD=0*u>lf#WQKYzznQvGws$_Qhqo1x|_S22!$t6;zX zl?kn+W8bN`=h2R&h(Hn#v*vy17ud)^LOM@K;~z%0r}3H}9wc_C0ixH^b8|32x6Fuw z4$wi;1YFGv&aFUH=XL^}s@^wkR|(DZ)_}%E7bZ=nQB5N30JwPcHOH@TXus~t8h`01d#;E`+fdChHX&Y2j;a06HN}NfE2BHD| zF=b8o0Uuvk@O*F9eyI7R{qxctPPtRwxr_w+K*92bU;DLsYBJJQ0;u(7B7)1WW zA99WC{}~z_k|jn6r2+~FZ$2J%I4aZv5CAlIs&f7XIdIr0x~60(p~%Hkwul3$7=L;Q zpZi$JR4UxhL+7K-DY!%(_viHbHvVc$K>}$Ete7GGMm2W7rPw*Tpqcqusf`)ilInh?s3eiB@ z^lLf=NCDMFSKTu(&4QeE#qC*zp??I>mVjCab(oy_3 ze4yCC%F0vqpaI6xYD66=NZ=3@VV}esZFjZPlS`ncB(Vs-5|%2;a7>=Df+GMY1vz3W zg;Hi-*|@x=0I(bpkf2R|;|sbgSPtI-FEA6W-g_abP}KbjO{x>0ip@+U$>JkXn^cxR zu?5y7euxWjvIaGg1lrl@eSZQ9YWxIR-gWJv z71MWATZVT+p3tiy2^9ty>v#ZWztBQNRrSyhfmP|N8TJ7lFMAQE)X11D_QNDctctJ% zswzI0=YozZ+>DS|x82|$4 za?o5h(-&dOfgYKOMSpVL)jsf-1P?^v{8-`tW}`FnYJR>(x2?@H6#=~vmP3>JhNKUz z7mfBE3;yai#U4-#atU@HF%?kPoQ)v0eW9u-rL|8;^-zcpe@C|Xk;LMRv{e@gB}6U% zk`d5K$IK1-kWuN0hqe1whLA{wX=WV-(M3Pr3t30+16)>jz9%w&> zTGkj_anGFe+kYKvNT^`q+3I7<&WM@q&vit(plyQ4i-P(Ph$`8E8YRvKN=>#waki^9 zN6M@yJK``vD1S%^Q$Cky)n?L~S%lMZR-7ojeRf9$J&qY%_R8Y`3SLN-sumy%&74$` zUqA!mv6h(5R({OTyNcZDH#{?W5qDW?_#kZEp3EE!w}0KROTlIP09IjWH#-2>lZpyl zOd>Vu?}<_E_s()zo3BR=15RhfTS$vJ$hE6>usw^3LB6d24TzTJ_H&7fAX@V?sW@{@ zjQKgSzz1ZhV43)KVhiDzvxq2~a~=P-aljk`cT#Ymb>NkG3A;1IV|DDcabIROv6 z+MtIHi2k0iV&VWtK?je2^Z=FgLoeF$rr7qRet+S2_vYFGYk#g2c?0afioL9C06HQB ztpzAC5Dgz{MF_=K#{$^}7l3{sWip>+uyI*lIRj^`wfmVs$`z(-;lFqFhNYC+15i}T zZ+J*P06zG9A^|YZi?-VazAnuG`oZZjC;X?R z<$p2oOLtB27W!a-DfAm2z&#pPIuwZn`-;Br^5p=7@*TYJO^Kg2-HjnfP;Vlyy*%I# zxin3HyFpgMpxvfU3Md7_uhW~)7{mFS1*2v!P(kyu2rf|-+(PmgoE5L`fiOf3cS0FH z1Vw|*29Z%VM*7pxdA+2Q5y#r4P(qLHaeqaAa)tn2%N|w(l1Y||K3zNceojaNF-4dP zwoI;u(MFOWm_u(JK$0l8x3vwwt=^()#avub5B(r`n;#siQVy9|(?Y3T>6t6AwInbq zvk*t?&Tb9HUO^Shc&}qE^@epd=_cZ77-YHow{aPH-A8Oedecok0c}M$N@+JuoPPzM zskC_qtdSBm05=LQFLA_0W{Mp!Bu&ceAl4%wGdl+(8Nr0l zbtIr3PUEmmWO}X$FyM@s3yI>Jc*-pgO?4v(2JQfjPZ6DjLMQ-A{pA-|z9I%{dmfsDp>%RCJ+Dx%+II)6@m7C56e3izup-SPomO1MB4s;6P=s6SNRgD(II zxM48D()zvt76ToxoBD9Qk2zreA`(AfN2av?4oyLdH|^Zh*F`UFS|O7h)Jg&HQAg?T zt}_UG5=9To^&=fXfCGU=^)wC=I;j@RV+USL1sbN>_x!tl4?jo(=@CoL2!Dy}3R-sT zLq-U1Qs!7R=y*e*Ci$y&Sdj5YD&?H)6f?~8Q3|D&St)kVybu9v*Y31&kR&XL zr^Y6ItGuSmWb>0u*)xbI=8rSd4WbpOM;xW;{WqA78Yp=n5DjdUQ1dIB0dZB^cnR=# zRUEJbUDK%qQXcMDx*>H=gnzBugGNnd9^s(c>efX=s0;;3`RYK{1Yk}q4j4c!gYJ*w zid6r6cmGhTmV>0rKmw#y1Ui;TnJEHtA`vMTcdUG1A=4k%5J@l@G%$yi4Zcu?kd zz6ju(F?J#mC_J#i%71)xrn{>d+oB<#g1=HbFfL$QPylhEIhJ^y@B_815+smNed)Q6 z_(~41FDK$+XVf}$6&;?Qo(k0lbEfZ3;9SOvBHl8mgGR}J0510B#wRE48^s7s>3O)M z5g4~~Q{wKNn;8+ilf+EO5et_cD5+lIuq!e3ijvx`X z(W+EYNB?Ne_>1jZfdhg_O92m09UT*j&?q)VBlhO>aSIRwFSnh*JTFxGQq5_S(abMc z)Vlo@$*Chs22_l4!{ z1UVQaqu>U|A`9MSvh+b_lU49l^VJ=IG?C(!9q1rVxuiKDh66bzVL+i%yc`ug`0m;$ z%$NX6Y4J)OsQ-6;k&#d@fDJI6W8et-!X$7`s%qh2Y=4rQVOHbv-nD*wt}D$+l(7-2 z*h6RH#{deV9*T)xD(9p-@bYAW-I{<#j4$GlQ7O_F zF%S*h+gqR0dE43P>cz6EO8>b0ssN1bEejggT^g3>5qKyG2j*i zJmQZmt#Bi-IYB$ehNzB!s%Zw-(&YwzKn3EN@_+rzrCn&h_b$yr!3$_Uhg{9dG?Q zhEg7b?px}7ISa|UvAxBb($HK`ag?tlf}hQmOs5Vd-i2TR=eJxW-V+)GjGgOpNqLm= zAb&jjai}`-f-Mk1)99fLtnVN0qB!JmfY$}MS9%pZUM?bTeZ0<6OVsQlxlbV#n4W&W zND!A}r0QAbUcjlmLi-w9cD27gYoIp=*^iu>X;xvM7mNeQ#^d%j!`ZTk+|gQisp_6T zR;~*+@#jJ&h^zZMte^=LpVILuR!fYA=zn)hnVUSH1Zi{$$;|ePxkRRE68|jFAPR!ac(B!Zb305H4c zK+Q-h0olzLeF0lS4qT8q1B?$6lF4Kw2I;n{o&Mb#9a7bM6@zh8PGIN(c`m}@*9H8#?cpr~?2pe+p zDE4)v2gwi*d!O>ug1{~5QSXl$3Ka^6IxxNv>_JFg;q?kQd$3^hf+ctmBje*D+fC)m zPrp3hnqUAKFDoZxE9D(gsDFm;b5@~av>6N~VdWq70?WSSgjxP}ymFk@D1Sf_*;o$Z z+V-eAOE)PL0?L8XxEvK^aBIYdIi+s| ziSu;+2;PP&gjpwF=Pj1~LND#og!iOKaNAWn02VzZxBWJOR)4X+4F?_idX=g+6k5Z3 z#CUm%@ODd~KLk_VbMq=7cHWvGS^-#ZlPOR+PJ3;h*GkFvQB6}#Plve8JtXRxrYgPi zs12HZ_J-P#i+2j@6m)V}j?IvH*)Dy?NmL#91?lq>3ONyj(?gU{Wj7--}hICiW^}Ekq8> z0ag>d2S`MZPS1to_>O|XQP%SmjHejZpLc_$mXaU~;D11#X$_u!?t*#cM(q(L9Tznb zMZ=~~T+xGX(I)7q$>$6n|LwUjE1v81#?XqVI_6fL6EP&>l?y3Iq_)Gq?iKy3!d1*%b9;)B`c=m*24c zxFUUlBntZp;HwY|{u50Pi!{0W#i~zX+9;rnT{(3kXlOt@NeP|L>-%zesL!=7_)mQ` z**S(vuv9|FV3Okcf&_4$7l7FCmC(m@JWr$}Y=8Znsxga?3xrrYsz@9!&T~kPmY4uE znSGZ9{@7$Gx!F3=K&(q(LT+wkf2lfE z$WS{#0e()iO5Av%<93@^qo!&$;Vy7CVj{Id-dD>Y81xp>AlAH$a&B#B~?N6=Z~8 zCYuTT>P25*U?S+DqA_-O$C@B1+Qy5p5cXxqwVQI1oM-$vv75oy@=zj0GO+?S?|+L8 z2H_^ITl}F2X;nz*0qQB%01Ya)q5zNoc$y?e{$`;x&(JZUZzciz*)RTDa%bc&g%c3N0^TmqnOQY=5%~Kc)PxyW?ONt_Vp09y){wyC32|E{rcgjt76= zzL2mW8rRJ8pJ7|7@+U9XO39SlM0NnjZ~Y5sFe)rOSW|!l<-0&B9+&VO5f|Q?9w$SK z_2u5RE>uT1;s7IkHl*)A*)e;DdH}WmQunO)GK2=B0PzYR3GEzcmN{$1a?P^Zx zZh>jsUmyM870D=+Ty~`MGc>Px0k&3Tp(bLKU|c-aCDU*Tl`{4M?Z$cMYhv<;0pj^a zUzBbN&0ra7@=#xjs#_~6gnzXUNTEEevE)r&bhsEb3|WiW`Z13SW8XSaqb+;5^D4 zEI(+o&3+F2s0&&Fd5YJ2B@&kDPGGv$%?B7UdxxA1yb->9qHTj?t$$WwPv(7gh`hr$ zz%Kc$u!~Xe5vCq3gz4z!U0~7ln*7~Sm?ygK`v=)!;q8WCrFZd)iV z9(f->n7R+(r|I+Y5n2wz>#5^`StgSO@`2Nn1tK?PrT}r~3i16HIq%bNl+?l5b?lot zu$*5_C5-ze20m6G6Mx=V3YQ?-ZS^Rr!Vt!iCd{wP5K3^|rFbB%KKml7Ozj>Dwwl?| zb=!0RN&i#_)agYW{+E3UlAI&Fa?EIHn14nynT{t#2^F1!2QU?;A8-LS!%-vQ&t&!# z0-!9P+^T%SJ1OX?g6U{QW`k^xUZ-6A>DFeiN%X4GUFXsm%zuVSP}pY$MgG_TOG)KA zybixI`E?6Q6kcy0*)7gU`B~SG44IkxzZ1fJBo9K`1N|UzK5b&ma(O!p$<$rWdI`Sg zTK{)aR1d7do0+^$#aAkH9CS5EhNMxT^gWz$$yH)Y%(-AF;(_o&rg9M;E$_=*1t2(c zH*=&vWfHDTMSq`bH9rTzG>TkNTy5`5ci-6}|9~zQ9`kIrX}RW~p4xQ)foJGtz4r-0 z^$NLDz2fHzIRYO6Am~mq1`kD8x^O&Y=T^=UBT*c+6Kw9lG65kdda<=$`5p5Id_c?H zrB5JV3m7W&8F$hNK~!i4o<4SUpYaQ>Nn!g+Dwn+G@u_zDIi!+wDodq5{ra{i*@Pzv`+%WKK4 z^HfdJ+5+H3NzVMr8eikf*aABOmGhzp1dsdUpmx4Wnl%y}d5^irV}b{rVKFb`3HP$l z{;yH0g@2EMq2JZCtXWCb=B1CXl}RbVDb((-`2&zk&njL2`YAXIii6+Ebc#j8mXXB( z%i`#z)SUUi8b{5Ak-?XkYpmz+8w8llbmEin^d)$kgwp9!mBRcIUY2W*X`x`QvoIHw zh{#69d7_cw|66N|F?r;Ta`#PFN_Y8KaY^`Jv46JKZ%WHI;0Zi*KCgI^4toUgV3P|O z%YviD==<6mseaIJpblWSbkcgJW9bFgy-W6FxcNd|0~KWjX-9m&(LrDOMSEq1Qs`Aj zf+bF6y6{yCOziZw(4hdh#XypiRBSr-1uMnZmdfEZD@L=cNi}EKqQhNjG8Ll7o`y*P z^?w>1QR@Brkt}j`0Lr2}H!X>LM#9+o<^C3<&WfPcW!V!`XQtX{T@zuL1b96F4ETvB zRX;T7p45T?OM-!8=;rsei8q9r$feG?ASirvH9(T8JHWx@WKCHIu1l{!`T?o$l7KYv zNGicp_H{d|#s7Asbwi>G_5cERGBTdwRDZJrByB(9BuoCW^~a~|OMzW*&O6Euo_9J7 zVgtuPIo`5dFny}dle4n&_B-edW%a7;_C<~ZIRl&QLiY`Z0;N8Z6m_eu01F}7>vucnsv$92UEi9Rn$&L5=P8qaNYrUX5C%Q;mU7 zuu;lLYU8od#E@HO*hD=tZI~ozD1T>hamhDd#uxnKX4=)eE@E8=Vo~&TNECdGZ2^2n zY5Pbj6uF@-QS0C9qAzJv+bANXHtwqQ$%KyIERxEo0K8BJZgqOtfl{9)^%W#mnL?@+ zI2M_7I+xkyByplL6WBD)9Cufb+LLdvSDh2}GlybGr=@;0C zjJwCd0~K%B$tzxf*;JK2u@|-Nza83t5|=^GOuZqKRBlMJpS!?g_(B~uLO)5KcZ!zq zG+GjsZtCx4Q_cLS1m*U%RZ~9#r@ro#Fm~b34(;(#=J4=*);TjFQ-9^2&zW{m^oMx? zllO@CDCcr5`CmVfB!M-fq(DH(1Qk9`PkVs}*DaUqucp%#P3okgKnNTFZa{&r3zn!O z9(Y?mea|yZs0#n_!OY$TOQyBPka;;+YCmG=g#g$MHL%2SkA3sm`|k)LDD^UM^=$iI zB%%%o`7-p2^RxCZu79&Nl^H;)qQ?gsj%mX+KPQJ$tm`*mQtNJYYVq)iJ2j1bec=Fy z_W+0j0df!t+M#T$&_piaI{IA>XsU1LqqMN)C7rYrQudyg=Yez26%A3?P*`avvY_O| zQ`J_$i^AFHYAt$~=wm3DV#_uWu*63M3Qs7SWUJ(WI&feDr+*93t(cxXf|f8w;LzjT zy^3KrB-CDU{_@L5_Dyu3>EVC`=gJg)#`m=>@Fus3k|1?)GV(AXsON&aI$)8+rQN_B zocR#bUp_L+* zSgOFi0tApCR(Bc~;S5rv7zh)&xTL+d<-oL>V##_$!3U`KBnW2i*Y<;!IYB^eF1E|57YYoZ0D9EP=A66=>+#-+hym|cZE7IX!h1P zk5|P<&sZ~J&cLExeY?3zXSDbMA!6>QVQ{Y%lST7kr z3RL?dN(#A)--)J=ip!;Xanm0Z;nNXp7#b3*aeqrnxR5M_#1JKJP6zXjyDKx2_T52h z3FR)q%RNiuCQ=i+b)osdp#Fe`kKjn#SyvTh52)EmdLfn|6zryb^8B#1U$$ zy04ED5yIy_rMt#ca!vfd5T6jOfHZrEAXl-7g`P+dEgklAgpMFSk1^v7c{Bm0&UIrl zSAQCsq1V@2Kca+omqu;o`}mr_sq+4lkYK7}zHThfJPFvrd6GwT@oRm8JtANT6~@3H zvG}tWa%fQ>XlI!J`+-|uH^xR`=5st2(aUxpEQD1RiD z**%HsmCL45nRc@)h3e0y-5yGYTcL;iryH#RAX1QS7(^E|&JX}Ui|qMj6OC0QF3_wF zI28}=#Yum|D1+TDwTAZ`04%2VAb&>IqiF}DQEX(sL_jO0w@!1(>=7IHOSI?AA{MYf z-L14vA_4|{=sg1Xein{A`bh3&s1Pq$3%#r^hYE=#8fCA3+8*&Uz^as~FhIGZqaqL` zVYM^~lNVhgBTpkn4W^XW|JG-v00x348J&>A$!WqKG{#5L?V+PQ^&DSrV}Ap|RHhW4 z%s}M#dzcAaS;o5rXYJkPA$;eAf(bRr2)9do!6YjENxWnB+TVd+bzQWB&ml4dcM`6N zEzX4OsrAM>2ps(x>;s{nb8%SxWs*EI8b-SfHLZW~ExqT>IZ20(RcOORiu(oN`gdXh zi!hLeX*ZLM2h8Rzh>WVw_c@H9P#RgCpHjmMr>r2-uL+HF5 z^UrRT&Y`|#L#h<_8`20He_LA|a5s1iQi3N~*%jbHE0A~p`s0sfW`CC;uiEvvvH$6! zNf$tn7`eP*UsOsE=m7)bpJgr+V3~ngrst{Q9B0Z0eDo)wK~Su~ok`hrf`7u0J2h!q zs2RCTVjxg^&>{@jRjOq~C}pp7LLdtLZqrP7C4EUwxl)-w(s(kMZe@U0o9_Bq&#=h? zn=fe%GzRDCYZ98LA%9^&HxIE<;ZmcY-Ajf84peQxoKgZ%nMljcfgqmNHc}LjT_*2P z5s{(1Rc7cb*9K1N30#$C<`n90ff(Q*eE)2D#Q?e^@6iEdvS_6|3P#$_oNXZ&T7dss zP|*BlG9a>{K(HOygP65M04Tl3dZPI{5%K_BsA9=96A$v99eUx#rQmG`Xpe#qk3iUBY3_6-KsVS4z^40yd zA2R$ej20ZpLxDL#d)~cmRcBQGGzsU)m@VoA+z=@!j!96~sJW8Syvx%OUs{>#bWCU? zNibbCm8gu~jDJ7&Le8r9wD2UvX}vWA8-XK|L-H1|E-dphr;BB<)+D<)x%}!qrfVT< zv~+0HW~3N*uX@&6Afq)32nXOKPC;Rk5?-H=qKE&lS9K^l0~reWX5^zXh0h~T%v=v& z1@FTcfMir(B4i7i1S5dO4dAJH7qDrGAq#fkD}mbfx_^|oyxE`fRKNp0;?>obnSs31 z9Nu<7q{55T_oK(&h<>0iuqZ+IlwO2@ck&>CO0Wkz!1zx4{ED7$7VSN!p3T>Mqrp_| z%OTO=6FnTRSL1&jz1@@H}A+5nIQ3-*Lh)cLKAN_oRn{N(`yNp*xkGV?9ZC)E~3 zJVXt5zklts5~(|+;-wwTsPc(2D~PyzqNn5`rUfo?Bk37ls7-Jvq=BY8DnEVVAkz{C znAOB(xRW0gJxPnAd3`}&=k^TD8kEL9OHZj3!}*BmYAV&ng8nm#uP1$PJL-*$B$W#Lav5SETi_I10I3hQIsFfFaf$0vHP}7C zOT*}~fo?YaDP9(D;{*zMQ%jLOIye~^AX3?UKZ0~mgj_%ak=_xXBl1!#JB@abBw&GQ zGJkxc(RGMDp}n4T6&ub&4-ukOaO1zWdohpL^1KsWiw z3NX#8ouB~5N``C<+9Ubt0Jy&{7erRj0_#qPA*(+$IwZ4s6c^(frxW<;vmijM;9{$Y z5?8JiYz_+%ZD(jMw5dV#B<6rW*Bywz(!Te|79c@h>X1Z13v}Y>F-krJK>@N^W`7UH z_tPZHu<4it+kL(@S0?+gLWXJvsrThWwzPKZ7wRDHRZGSqjdXU?wemj9*F$eKB7insD6~c4Kw$_pH488Om zV5=?0Q}9XLyH_G_McdtE_kf+dq%FIjcFWHZdWt!4Ger6Dwttml#rZNb4oYc7Pg*w= zRrd7pAtglM;kYvWuVQo?S5-k)p?2@LU;xT~E^$QJ2O+tT+?ojjVj2xG4S$w0SS%~P zy1f}R0Sq-ZNEH2Rxs^lRG}OqjCe=mX00tlR-=F>8!7kU}yHWPQj23%8a6!%u z001BXI9ON6SxfUFub_+)o|%~y1a|X64hZd?nEwGGC)P;XIt*Go>j$2r)fHpXb^)i{ z{k)Jzaz5`Dh9@UvEF$m6RDX~f5^Db<2|5kRhydJ+?p6Q~U{~ivZO8#@H9&zizkL}H z7bAS32gG(zUAnD21)n0c0@Uq?Iq@G7048ozK0koR0=Ulp`jnF${vlEA|8d@;8o)=iu4}Z%B+i~|IKgZV&uE(6jg>~L zM^s_}eD{BMhKff@>Z9n&r|M$nYbF#up#}>e~v4tDFz) z)fA5A&fy2dKb04ntAE`2LP<@;Zh-EhoW*!x0p-MZ!{Ltx`Mp7iKFOy?A=6ljrSDXK zholq8bR)oqx|Qq2P(J|P_EZAixl;+gBaq?(u`?SpF>wFvtR44(-yK;j56?HTha{tD zhXk1rN9i8!X1_o+s4aA;PHF3xMRX!AHSfEy-|=O`IOBFV*MCub&nUnj&Jrbb#fo)+ z)EP>5Sdu81J@F6I?hPtsx+piF5eA{QX+xA6w)ms!Ge->t=Y-bLAXy^*5;at}Nlqz}6=hs% zM|oYcSO3Q^Kmlo`G;vtz=-aG`A&n1jBS(u3@3x5d=WJptFjO(y>13~!Zn!YVR1x7^Q&?29oEGd-5)I3iWM1K?b?5YIj`urj3rr@mLtOLKR zq3_V0{}Od6(^z-CIFM%2z*iNjV?j=NiO#F35i!KWBZKua!Gs%ed`>QSS@u5*HR7n0 z0RVx2ZJyC=nL`9xYJ9qgB%E}qB+?8emr)Yw_f#ZQ-+roT!tezSJ3vHY%$K)L3c5^y z+=#rsuzw3l#TYzfcBfnv3Nj#@2c`B}w!;6U069rT3Q=o|8FM;*JG`-X} zv;lgEoid9DqhG~Cm(ZACrCm@jQfMO9zmeGJyxO1(4cUE_$9Znp5H)zu&DDYh<_b!v z5o(1E)k$CIu*sM}d+y}E{1Yjpn?9gT(OB_<$pP9tw7-bW)DJ1KIxsZS-&yOI!dAh+Bs@G^W3V580nxbe=MjA4H^0|P;k zPz^1f>mmSaIp_`gFaTShz9a&S01bb`2!W+(eWu5^8LVuezkgxX!_V7oVX$9q|v4{I;AR8P2)A^L5 z2v5i$JPu`|&>szg<3O9rARdLTAkKso13RncF^P;U+c1j22$kMoOm#q#1O1|wzo<1) z#~wTl=0vkhwNgSGd>6OLBi4v7t9M0y9UrBl*Fym(-#`g9LM(4Xz)`PV1n?-KB!8-Q zfCC4L^?e*q)5|Q=k$3osa{U1W%E7p}Z2-kp2R;gi#t0cq`dA=sqh=qO?f(+J=hmfQ zRq;+yvq@^9g9}VS$$m<#QJA4IF(RdVPdC2y%d9u03Z#nOR31j3a&XB|4(0|Ls=td6 zXK^A7l8Z5b05jI7tN<0LpxEs$8Gr6%=C^S11sqdtVz(m-l+kyb52tIarAedq2qX>^``U_}NHfmSzL1V+vL8~L(He)u*Xue z*d&MKtMOGI-N&xJMrHe-J96`+0bONIBlv=5(EV<^G{BM)9ta>P$zuZ0pMSbWt0(uC z0HJY~S81YEDLIsn^xo+6`p&=9C$>Ml0%b3`br?!OAV9V6Yw+!+{8weF=)fT2y)wzv z0zO_$2Em64NlT$tN;)oOG5pj+*G!qbUNL9vM+r^JM@UOV>Penc4dg(P6*^tx39%=2 z15YINF!Yd2i67GeeGyhDh<`P(o@oS%s7DUJ*-(x3pcPW6CNNRSa={xp|8*nA2A~p|KwRUzk()%7 zK@tD%aztG!A$y1)M>!MC;sIc)X%FoH*cGyR08K!$zejZZ?u0|OAiaN8Nd|AFiUlF? zw2CBjx5NB1BnX1YRq>y0j~8W_T8aR@z*rsCLhGrAqm@7G&LaAb+eZ?PB@o#BJ3<qN5bU=h?hsf9AF_J^fweopU;A#qPpg_X-1c;?Gv}r(C%87s8&ye*7xdrM5OT^27 zNG7M%@CDd(6x8wx>I2wQ3lEn}L@k!QK^_#^qMICl$JSKdOOtURQF@^YjWi+$Y1~a# z*`LE4PH+4={t_kQ$W7MFG<|!q0HqJLDgHr2V27t6!qXR=`lBKhtxe*tqfeI+kxKTL zwI1xt0Q|gn<5hoQ7inOKSBjYs*&2bx05MQ`KEjKU8TbQg)03M*uI)HN%IkH;V<7Py z-y^U_(dw69t>=qy@a^QF8Ix3o3=lf|Ug*y8a~fdRzKS2!OZn1NMfPq*u~ChRRW0;2 z2yvl#*J9)xL1kj&;pN^r<8(*{LQNRyT(_&vN!g@)?DcL*{z@iv6( zwXZ~G(~2eEMpCI1GJPkJ!J6ce01N=5JdP^CSH(C~PDj=h*90Zf_KISV0>$L{f(bM1V(;*sfDRNhNDQKpHv-Y?=!NPQb{ZyWgVeX7x8l*-@T^mt-&A-%R%YhTLP_yg{z({pCz0+v5eWqJt3X=`Y#gWy zZJR}rRV2sL&t4|@Gvj%htL55=_@#$R!>A}fL`Vq$*RD|lTU-yK2|pFk_fQPI1xQM? zeRvieH#bO|LCI9=kL3-VsC}LAMYZ(afchW%sFr`807Z+L@Hl@NEszuLO7vIkfsj0| z;rfjNOU?uc6#EC_V~+-ZcpM+lS~i$15Ayu{YQ8o+Wi2F}I|%`;dv_awJ~;plNKie` z_ke&zCOr-4UOz9>uBTFKQUW#ttKPYHFzTMARcbM=)gaa7HtPU0~1L<;<`;hJgnfLZy{qBvJgZNUSQ-~`DjJJ zI>pg^zy$dJdBk2ZB(jf3Kd$_!j=hdKLRWv9lS^VztsRQY5g80x@Jqlp6A~}zc!VRV z7=*Y`>kDn6pt*hsf#Y&n+Sxn>_(4vzUsc3?(S;-wn!Q%s15Jh6eqPvG^Kve@GZA>aG1G=n3RCjFUP^@Rb!|Xn%1Hsd+~o& zoq162aP7*W=eA!+aC0u`Rn;4m-9Yr^p_P?HuuM7@E+&GXn(wMOj0R&sivC_6>I~ zp<+5T-a3b8`k%=Zb{j%@aPwbCq>q1xrTzQuxagJ6Cb5@74<}naw@Pw&PYdwk6Uab_-sLsSUUTSh-F*MCsk+px9n=3hmK~v70r6<&SG+vqDZADF#Bc^aj<{Ns057N zsyLMr`SN#*N())T(aC6m3ro$T&3ZqxB?fFwaNSxK-A}9+E}^~_NT_t`NH1^Xn^km}m6m&Mf=SY_wyCb2#6u>OGd;T`*@r4VB-@|xf*1XL@dO_F z^Hs-C^v)Ab@Z_l{0@x#IDqJ<^D9Yo%DOEcZ5gb8Gv&D>wcS0HU(myg8vwS zks{4;hU-Y^>-MPS8sz!CL5^(^{1Bm>U* zBzTlW0=eM8`BZX9j1*0wl*M$+)8y8s8K zMYlNi@DO(LdsMnXp#wSy)`P@|dQ$5Zzv65_F28~-tN&0p*{hle8$RngM0T(4ib^;D zua7o*Q;Q2<3^_Q;2Z4X#cGTTTbhFVHf^GD@;BAY{Im=$_qSAiL-N!&Oh(H$dATL`Bp_q3Uln0MJC58?t5&_A)BzsY}~a^NifvG5U79iH8) zvJD!KvC9nf^TzM9M2-@f(Awz6Wk_aj^D0b$m+|LQAE%gt54U%lI(ak{SHN?xdL9zo zF*z)|b1F)b00@8!6){>83AoGayPtB;pDj0hhUA>|-)ZRf;n z#@Qs#M8*KuaOJ*(F-Sq_FVQJL(OPW9M}{s5UP4lKgT&K9r}u3DvE_#Iif z?s0iWU=-6uU73K%5<#jdG`g1>$AT8Eit%*^)$|HKKQ#r$ozOtkBtMS;%o9_c=^jiS zVDWbzl(T=efT3@9*}8QWLv}eso4Lc*E^du4qsWW0f8YT5E{K8hD^b-tWk)ov z+)=ffzFYp3ES455lgZgPk&W~K3F&H0#wSKOFR6cDwJLtS>RBCcPjEE{lxV;j*Pd!( zKqwyAAdz|k>UI5rgoA!yae<(nhSJn<2_U{sVSU<+A$2JP!rKXe8Avn`YQ7`;-+O)u!|<6bWeocptOWN{|K(lEilvHFqE@#o^H?q zBj?%J0inBYDVII%tuvmI6ys)ExBpHhtho)X>{8R}Y=s{_t{EJ!8AY_W+?{IGYB?r$ z&dI2tz2g;;WxeN5F$8fr>(|gLpTvG?@a(sNvQ>ZW zVc<*5Or(OLg9NfPdGC%J!)TN618H7_lO!X@*=sqbfNR)n^{|nA`Wob``!WZNKd=D1 z?Y>4={aUC@(99s-4aFC56}f?JELkn6ZSzHR?kD|sjv$9<(R{qhoB-8PKSR`*Gt(bI zdcn7A=VGL&)U^Bf8$PEMkN^M)2nc^begG6u2MQP&P(ue|J7+J6U{}Yj$*#!x*W$9ZZuuJJ07)>{!Tw+nL;fQF&-g%qOi9OnTq^dx zaZ+f29)L$WA%WNy@5un0?PbOy&*}mNuGhckKlw%RuNtz~wWozmklz|TDkFb=u;T3U z8ydh$Q2A3)!`m^Vx;*_yaSFjXL1_(M8GJ2+`1HiolI(14D< zmq{Ov%z1V&7MOftCX}dgkvy(aTp{d-RN6r*+jKhU`$!(ZxnT#KsMbATbN%9=DCN;F zM`!$J<=H!lo<(xMW)5r2JcNH14aFCneK%7OKn0&x@sm1k%q#RH*-Z*}n=anLzw`W!vLvgbE&UKs8h?F{MdTurHb~9- z)s-SZBmLa1cl$bm0A)IxwNu6sHiz}CG;|{wNs_kD;%adwAdel_QNvnl{-{&IxK-Vn zxLI_aFe7j|!#wo$0*0WZZ~cK%B%Jo5nVa1^HN|SERzSld9tM9ssG>dP6HfpK5$}pR ziHg{)g{7g^`oF9oqn7~RIjx+B3Y)Y3?hk*P>K0J)GV88AcW8?)mI-vF6`zor~{u}YyEPwPb zGrxb`Ks7r3am>& z`zCoG4phP4ViPI8$TlLcHRlHq5U1;LIf+?i=!m^qQ^A&Lzi_5$r$Fctb}YeDYb1co zJ=nzd(pd!_1=)3?-$>t9k357SK$%} zjEm3!q8Bb&51$XDdPoz{6ZS-AzyZ=Y$OmiZPX?ikphc{Xg4Q2SpD@0H(aQa7qfmbg z+&^p-2@mV`>P_8tRH)+V+Dbr4LBi!iASp;PMJkm*W7cGjbNwevw7 znv?mkZD_vMK>_xF0#w#|v^x&^dD(_$A8vy_+~0WI+5V2cbaA=-h4xXYMwH zQ~lN9BEVtKtEh2hdEPW~0xZj@pq9?IxD9YS7RchrK?j}p5IcdioeJzfOb$(DQc-(F zQudqngqGsOsP(pax0FM&yqkYb6wFpWHid28lVXd+aUnhtp6a-$|eC_n$%sP7-46cA%v6tD`&tYc*sgxC`zNeZf= ze2&{GhLY)^wd;?5sdmbvO8`&Qs|=UK z7tTY&5DsfR3nQDpsJ&7@Cg6Gk*$$cNvl`$)w)a*;tWnXWd=M$Qy;~&wd;%U?^@^%` zUika$}!j<;o^U{>{ZGqQDFeWg+J z&@)txYb8ZHV7OPeh(ld@H${eyO?lC5a+VN{e`F`iefV=mqCk7196N>DX0fyR3iJ*{r1^#7)5-*|a`` zQA1E-;QJZqKUn;EN7EZ&ZCxtMTs;1{>W}PLl5K(j0xfcKUmzqNOfplNI*l`g$ga9i zrkPVIp-p)_y?T5f-^0u!%p?Pa@~MAKK|RTO$hF{r35%1}uyWVvN0s5xY3f#Cu_tGW zg4|UYd4R2Reer)M*`%-#!3q-Jd=MKT?vPJ_N+LI^-Jwzcv}Em7@uU<2qLfaFmQ`RM zu~Q2^C_+8^>EabNAEXc|k9>50UH_B;ACWf=+(tfor zwMVWZ+Vw~+uQ#eSK#xr3hMdPDIJby00PmGfrL0l&%*VWBxpcruG`FRvYty9H8nFpd z_6fd@@MfvW?^wYJX+V_5+w{Syc~-izqx91V(Ad+(IzDJa;FrSAs^E+#;li85;~$pl zD$hh%^)!F&C zvRbvT18`T)09E;keyNr;1KkyJxpfm46F#69VpaK+V`05D#Ln_mdqR$9U+ji!Ky<$C z{3xCg2k6xIW>Hxtd0F@%O1A0RBgKhPn%YdA^do<`%6@1(6Td78o&iuRMk8BXjhj#n zn2YaOpwK2+%$9D`yS(vL8YU0KkR_O_tp8xDB}M-|LmRbgsvdwK>Xkz@!&5P{@(^&j zqc8w86j{@gdbkDir9jm8w$B>IKt=Q`=0OzMPXrrSLqg-3j+#pYmA#@5=AV zAd-J1c|(^N+ClJafp`%&#aKoA092#7O15i9|17{?pF_Te{1neCsVDqVL-ZBZ7%HZ^ z27Lwd0AGih>gxboMj)ou9VV`xT)`Upqdh30`X~jjm5cVm!5On>cKM1cueTmftAtjv z7u#K8p0CR>jq%7ch*;Rwv{MT+sR(vJ1O9(cw~^o6aN@HH7_9zhdhyj?(Gli#-7!+a zc;JC8rh`VwQPcd7%($k+FrS}sM57MHPP@4=sE?2jhzT~q5&!KY=Gor=2_rZ^VG(gMT{g_0^~ryW zI4|goHW{z?nJ(6L#^QA}a7g6pPJcW^R{eg@@2Ri^XNDB(c3OGK3VZ|^U%>7g*d7CI z8@!M3evr^+Zi*iW@e~@DIlfXpMbz%SCsCu#Bpiw^0KuAk>)fuy-m9G?AS?-ji%G2y z)(i0NnGE-ZhwMG16Y1Fxzcdm}n$dp%i0~#gvTS5s98!|*HG?Z95 zG;?z7;ewKdeI12sBiDkQeTYVaq|$j3`|O#l5UY(A(IBgx6z{aOB>#4lHaM-+x6iJ7i&(;+k z?^&-=!#t9igERB8xAxEg|1^Yq7Pe#pX#|9Vh@e?ILK3~v7K2_%x7UQGYD#=~-=a0) z7kQ`FVXptCnmQ3@t81(DD<7Z$N4+$+w-?y4Zp9ko?Hr*;d{KY&iI1?@_I+=1H3-xC zQ-b-UtI|6d3%)~?;rHDb4%WWxMGir`x2dym10Vobxm=mQg?3M`QrteIK%-O5P$|p3 z%ylD;OzH_G;QMH-@9qamT>>Jz`ySMwm{jH(a|6&oF2FBYUr{dJlKr=b_=TML2~;1C zBVOY~zXAqVf5U&IyZ~01ayGvTNv0UcNV38Pm^eZ#Y7DoDVhm;Po?a?iK&+?-Z)I}u z9ic-1=3W3<55hBdtVRT5r9T@EIwMR!B4GpB>ebhyEP<*(Cei-Sye@0*zret#vxshp zmw{IPXW$v1ub2E`|D*Mh*ot?SNGNu(5d|;P*gLd&~!`VRF>2-z>3a2 z*Y!JaouZU^On$p^#g2z5Rocc1~R^J&^X!flC`%o|MwHn?rXe&ME6blD&MY;hG* z#`HVGM>PN~yuwKWKT)GMRu@QHt%n?g#5T1haFBlyX%%NoXSJ7mc_9@scB!22N~mK1 z0;!SxdAKf`Em$fVZJ3i5H(TC`O>Ybv$(C~;JPzMXy9^3 zTYY~Em5!Q<(C-r+dA7;+#8`pA|C3{9*@$qGVbAJJ#2z0@*@GYvaLle&AoS}FTLTfT zikK8!1q;)9mC}E3pxK))n4c)Ojw#x|agq?l{-~`Ipyc7Iw@TW8UKwKN>e{@IsQ4L6 z>{&0aXmcTdhkSA(86HUq7GrIDCNc#^u3di@^Ap)S(-Fuh(>)$ISmQQ@E7c7qv0T9o znYH?}-D1`#Hjx)Y&B}R{dzLr+^!xW(7xOWa{SXJ2szpt|onLh^9k`N}k@di12?VmQ zp?JZN=WaXV2rv2Co7_f}h=56q2n5gT&E9qVK0b*+{mGZx-Vmy5CO^NyAuf=NqRD?s ztCsxtEPv z8mNOJLtcC@^9}`QeYujAvlQ+qW{klKlhn4~^&S-s9&>~U9Frq**6Zz;C}3w%@P=v= zN)RApD-}fgFjlKrUTCuv7tuSGFrraEIJSU_K3T{&`2O#k2b2!V0k86mkhUnQ{kumvIwoY1-<^k zBpQTQSU*nsz+V(zNG=FH`EUGY`yc^z9%at&6gD;?Qr3xBpnZk3^LmPW4RL?qz}7SV z$Sc?#W_tz6Dd5 zWj}DP>TjgCLAw!h?P3MgH{^eiV`2&M2*js)6W$&~5)U)zt&#CAKRn#T>#T)K+(Y_k z)F$gF^fqsG5qJgL>+@aehTtTf&&A6mUSVYlq>yP1fh6p%rT`*+yYzSI|%D1_CD(6ug`DY>qKR%W>cmU#o0}!Gmrc)%6q%nUqP234}AUNfN zJdEz5R7rxm)e@Ef{a9-lHn|@*uX6b^U9>)ruFg01-%f1gR|j#;6;4PC)vpvyTtkKi zfS+@}S%1S!rX&*V?fCAh8ak=_hwrmRI;z%R#8k_g8NP6EG=NG+T%!0|&D=@k_Ryl> zR5?Th9_l}v9#nCfA=w-&&vB-XgDK>}+v;E=!9E&NM zuWA*nU^BCufu(r9W>zBEsrL6IBI2f)Tb2&Np-ecdrPAGC1fr4o>~|Mp3N4b_e}VIM z$zp(TG`P~wfG`l8RrEj)c7gkXmLrpC%cz@^knlx3^JokJFZO>wr0}&2?ux3?lwCx? zx-;t`hvns5s3XdJuWVHr!x9l@%A_BYrAq3D*P~_A|v!G?^MWND<8>19V6t z^ni?#0EXUC+cWmxFk zVD_?~XNoh%o}Yj1JUAjl>h5gx9@cW2HBYt`ZI_eRjisOC>kf*C_jwnd4pPLOAWh{*wG*VC zYiS=|+`cH7kU;-)J6oB(^zu}_@2}`M%I2`ZImrKGk5+%DX8I2LZW%$NRgUg*_)oeb zH(YRj@JfNvNk9O7Hd5Ls?vz|#HsVPIPNDqZ_l2{a=9~z+zwy4z{>}M3M zc1ndGV`P7pbg&ISle9qC2(yBWf@vTE94&i6%OIS#K{SYLFhAG;P4OT7QDPOmBd-66 zh4)rpi%quA0!7@{qC8|AHDOBysRg*}fm`#ml=%qYuGeMlqPhU9evW6BQ1382secf( zU@FY7H$kBkZ*sNHXi#)CU#vmzey}}rr!|(~ckO@ngn|$65Zk7-QQ8i);_!IP|F&FhyDNXL7{*wiG#!#Fc-d@^A2;jzz3BsF0(bJg zi`_GM2(8d6+eL9|8MF5{(7FH;;l>J8yY(sG(1;buS@3T<^O?pHzXM}`{?fQHk~=@E z8b}0YzJ$`@1CMSTKRhaEj5f_f@+f*tVW`L;GP6KP#9g+|BtWl%Ds_ZeOw51y z^8JlGQ&ILK>)&=9&IjN2ClfKcr|<@at}F`sA>a)EKaY6dL=R~`LUG%x@bQ%ICaC|z zGsu)Gm5aa;9LNDr;}W{?t6ec0>7k&f0CDU}geYZ?h*`^Sl@ZVBHf|Uj?=!o)O08RM zzeIGZdf6Qd}e-QLTSUW)RLP#1cL zqe~Tb-8piAYQ#%qt)&Bb^#qG|&`t1t?}IXhLRqNa_H}aL7R}4jd!2K{sLOx9#1ltL zoMtTbM`Ub`6;T11GIi4EY^&gb`FrbRnAEbnu~uDZ+MksB&zdHXFe-824BJNR&PRlg zVyycz+R$J#Y#_Jm7Gy*RUJRbL5So-V#@G4S2!oNF#$GDpIp>Bw-;uLrYf!}9>bgimu zjLT%5^8Sq+P6J!jUf7}G2>(-QX0{yTpdrIvg{#-T1^~VDPMMACJJf$+=hV>+9UM{0 z8{GwOF~Q!BT~*YGf2L&-)X?bEu*3>JZbxpTRq~LLNn{4YLG%MQ>;V9AKLv)TLDZVc zFF8H4Dc~TT8`6GN(Jit<=FyTQ)YhVyW7vQOZ?{1%$IX6oRAiG?P+)mYLdM_AL(!13 z9wcrIgCf8|0a=eL)5?E>29A~@L*Wqo#pE6*|0+8%S6{rf&s-KSA|BCF_NM;FOQaef zV%DhQtS}d(BIt*GYfQSmD*~e@{9ec3wX_Iv)21Gne>Cx5p_7*NK8kOb61s0=#IM!A`Rqp`mKKb@HwIT(u&>*#cf5R%(eyN^ zy3=bI9KTa;n5GtI`csq-T5^hgy@frS|6t!kv%4q#smKL#j9V4Vn}{($T(;Q1|1l1o zbh07_=w4_Ai$5)Wg#dw&X6}C&8RdKPYq7?kYksjfEsrD!VApBquHbjzd zLam5%RmFdVE^`n==N~_%0ar7E0eX=t(}Z7m^!~#WvHEddpC?SH_l(yAU5Soj22)8# z>_BJ{?SkE>R(L4BeWPJI_ZkB&?iI#QuD>gG!<;=^f++<8pSOZ~lmk2qkt6ln$9{?% zgb>!UsP3$p`d+Oj7G$zIq!w+=F_tU<3*!QnnV5eef22@E9W(DvkV+Ps`e&Rp-BK=m zD02#c3H=l4&oAoLnrDBbMkolndluWQSiFLAo%1-NX~vC;{l)J;M&;H-*|VkE4hfVX`oD>n@~DT3*r=jU1d zOyYy)!rLXCcxnk=D*NYeVX@a8S*0=@c>;f{W9{RIz8y;%vRMT5KW$$;R!HiH)wMJAfGBu61{oFoEAwwI4oJCJR3 zOd(#$rv8JeAk&~cfLG868{?zmPZGNMjM!|j`LPib4{X;aHgjGn{&Y3La=qBK#G-#I zfd7Rci(yqLa~SO`1-EW-fE$>a@}VB%>fCi3n(DaO;SfD+oez&@`oE^`s_U6~vjXF3 zJQ2{0_T~E=E@?!tU9P4ta|8g7S^B3VPky67)BT-E-E;&TT+SJ-FW$O)F6t7MM;0Lb zElmkMPB@BSD#df+#d1zzWr**jx~zYtBKb9?bALf9zad56x%S-wQ&cA&r00wG~&q zRQYLMMdr?0FRoKN*Is|8PxKZjvrNBLqyW1GC=c9wgJ86fPV^Eo!~nM-moQh{ z!vLRBDJw@rxtLfKOcJ4U19wxi*;`D%YwO2o^F%#pV0?caK;RTk)@ilYVOJy>^ zp6Cl*6}QqEA}Ppg06BxfXBlVaq<-z-P7y)&;ubVO{GY1J3NC!(_Q6cuL)^2>HAzkV z_Y+tX9MweoKKF=@geI^sBsYY@T?YnV! zHyEEF;hZ4lx=8>@`9$#bL3~Bevj#=(+K%w=5F(r_qL^J$SIe&Ur8?A`N|(s|1<0&e z3MaLcWxsjp9LxjGZ#I-VjlAyy2hka~XYBO^7wrCgS4A(cQFVV~D_tZq2h>jTuu*hq zl&{Fdb1(B;sC89eR8^!E4u$xbs0RfrH{VL>pS8l1NBHg$_j(%Jzs|qBv70!=+u%qn zebx9X>Z9TzdVEp=6b`&btP`t61nj7<&_0kPgQ7ckBL;`D?g7we~JY`7$mfjml-uU$!KIGOjLNXDzWccKQpRdD<^O@<~$sRK>Ue5 z`#^{m1y^Jp^!+XUgGHSq*@OW2ky<#O5l1z$fQxmDFqePW=#4?aS=c{@aw69QELR{f`pWPMag;S+TY ze>M#lB&okt)}S41m8%Ef&}+_m2z}o>VzgUO0%em_eWT6)?wEvcnzPY9C?1D&Bi|`i zgPv(s3l-)CW4@^56{>u7F;lzAg%<35%8W7{M~8m|^|u^dYf%AG%xFS;<1axTb>*A% zPDutuXQQm1AQL?8giMQDx@wVv2r|>VCZwZRz!IWD^Ckq-SH|sF^TIErLVC zkHVa7rf7v!5uodXAKkqm6FI0UiB@gGmw3j@{1mU+lp*dE4$Y8{!9;usg8=*g^zbk8 zt>VG8!SjE$AtqxRyd0)Ay|y3#@I%4Yho)oO{a zMDDaex?_P$Kih7^LVT#k(}4ot>C@n$G5UY@(6X!0J03pvx+5|8d%^gG3HRj?#E7>V zYmux(%9@l{vCh*))gI0OEL?v`L^a(S2c($7)z2+GyQ;t6Q2uBBfCGG&U>Bk23O6Ml zFH#6D#BCd6Vqu^iT>T4TJp@L%`NFMSmrtmgHd)h9r6RtcHVJj~d>0gA#$DVWKg@q8 z61Yw@J(<4+#bs35^NO0et^VhQbd2WI9}2NBGhbfAsG?i7<~9bGTg=c0vLILLI6atb zv)ff?Z&y(kbI{q~Ygm$P2ao^4X!meh!OAi0fQwWSW&x!4=#vfa2Wptl6?rAlU)Vvm z&A2dJb%*_~V3pDpK221=;mLTZBKv@f^-k5<6}snV$R+cV`6SZypa7}=>@=cp z6KnND>LWo^{#`#RBnyR%xx)WSbF;{H_<(Ge(pg_=* z+O*OoI;JXo0C}J98ygq{!c%0IOXSvu(kA`;ec2JVN4tFpXXeo zlu#Y+tW(|(lS%+>3kr^7)4hL)*J>FK?j(Vmnw{6$ovux9F*d0(97KcQGAOReTFlq6 z*G3uOT`~h$>EkEZ4W&vQ056-S^*_DiLf`=y&wmro23J(L)t$_6kynvEZ8!%}Hbxd4 zQyu=3+z~k9`Tdow0zGY$dBL7kzq;4u#pp=${xED!d5t9UuoiYkNa264N_a734$^gR zKn-l?TEA=5zF6@s{C3Y~B# z8HwBkmiqhz=B0rZ%Uoa|7>hLczl^H9ovj=8h)g~m1vr3fWF(Ot(lFHFy%Lwy$5}4io$-k3Ie;eX0RwG)5E)E(>?2eUQB^^Z*ZDbm=c;yFjvX$o6avVO-nQq? z<+w*?&-8z$Ti$!6^?(HM)4AF}ASlZBa|yN%Maz*xmZ$On&!K}fW-25@3U&T zTH#$aCVs!Eif_%_hUX&@JS+L~ylEf?6Dd-gW`PO?o_E?m&Eco!<*%^c2(o@oRmfWd z7@dMPQlkQ)u}*JRUK&46BT87jUhpfc`1o@vw2~M*Hb09G0S=%HxfkROj>Ob+&Y4KR zDXD+E{4pjVcLZBEx$4x~VJz$-v*Fq_O7E;Vbv9v*HYARwE+95Zytb&n-^m+$*@8Z1 zjn5G-$ALuTLdqNw2FFO@Qg-v~c#Cq_@wMu|Bx?5$dXOB zYaz9=zI0`0eE*VWvO)b8ohs}=gP>=4>9-qq+^wy{fCx@Y!=vn6v*=xCt2H7yN8PFWFk0gUG0VlPZ|1}!m-4-Uv5RbSl*S8k4 z8G*lZC6lRhKM`??IX0YEy>%Ka`n5Rj1;uG)6_m*H7da}8D`djcrk_~5;P^_k@_v8z z=k&_?!XSU)3P7T)zwf02ekw-XeSiVE0e@rq8?YczYa(^uZ<5`yc>eLp_WlNERDX9n0ko`cR+p;DBbm$pn z+DR4KPiAl41U^Do&oApEP|5G!5zY`ufXW5fq&Q==2mz7+3XS1H(Y-Tcm~Bra!PO>C6nj16_T~Fih_;mg@7w_c^#OLXu>j7BIfWfwTAA!u=vTYqNziW! z_6bx%S>XBoGc=&|aM_%3h6sOrwWx2&+Y&*kBf$GSHCuu~X~_0*OrKm_)8F?O2YkUT zvYA!ZNa&Vwdtw1ME1O4O!}`xrYC!`n7WCoYv2MA8>;t}cU5G&K2Y2_MTPmkHz66ui zDl|_96M8=iSKCEt65HS2b$(R|mJ9g!`x!6*+9;n@KKKX`aw-JQhM<4-1T*KA0jZ?h z=KK2sjXWByeZEeSRNMl*x*_C}O^?UdA}$l`w+g%;K~65ezH3vUpc%jwG*O%y(P_R^ zzKpr?Gu;T8Og2M>z$fO(Ew)rgyhrD?mQ#a=5G-EZ{6Zo3rK4P;5p}+-(dNVP5qI~q zaH!4IADlomfPvFMZoz+|_oo-vtP1Pw8zZ_@c#3gB>mQ1X)>S-?7V1dhM!aRuR^4yN zFQ{r5IcMZ$%`P7(oD_z>;5&*d|*udLUnTrk?;7 zNq2Hrxb25rRJ2>Y!2_XMEP*@vcNoI{b$l3!Uu+eZ-{>Cx+mL@U7f}yL4KX0Sg%<{j=SqCt54dEr zy8leyP;4dh>QfhY}aQfMWF z03|D*u2fV5J|vE6;_93HWIi0|Z1^x$7yKlGzl{^lKqn5GIb#EChzCYX;i9y4k>U`< z*Q3By0aOi1)Krn|9yZWT_Fi+qP9ZhH{F8*BZi1uAp^F!Cl0DD^-W7hA9|EdrBmZs# zENc>9=Ky~t#Vrx#*toU+3^sZ)dU?}Gi`eK6mS>%@{d<Qq73Ou{KnvG=M>$7>q(pHzXDzw< zJJyadpcbTGC7#KTR3i;YoN-+bR5hBygrNEuiQoLpax;8NquIQO1a1Xl$P$&+dl{rs zOOVn)%(N+ip8JD0JT4VKu%li;1C-pQm)(k~r)KkmB{!FgtkA%;^F@uKc%}Nh%!ZBU z@{)fVq6ihJRA73ouBt8MwT~JObB}w=n$hGH*hZ$wUqs0u7EO0{tg2R#81$g=6gOh2m=EL_<*>7M^Xe!=a4MA0&iqJwdGrRaKkk{}z(GpVAa}}khhu-n z5N#HM>ds5hf$U&BUSNjEsc-uQCZD3292s8_<}-LaRd}1=sN1>UW9yt^C$1h+g+tT+ zGCY60gx3stRPPxpYRaZvkSF|rU-t9hlWG09xo4vC-U0L^P}0PPZXoXc`Vt8(Soxk| zXRkzYn#w!=$Ak0~^3np+rQW$a0eyds)Hs#w3?PGdNmtg<#hHFup1NsY#PPT_VWE0F zoe1KS&CUt?AP7KoQD#iAY!0P?@?l*fPix2oFqp#@w=dck1OW?zMjtpUgu=tx;@zpd zoOf$40V*{=raK(4{(`P6dHjE3J0Vt~aXU8QDnNlnRGUb5$?TpiM5a)n-|T;O^LGQx ztBR68-fsWftsMcf(}Gq>wDx@zUB|tVB55oMlq5ibqnlm}5@^5z&Y;DseVx@;qWv)B zo_fH$p%%rB%>DpdK%~EFN^Gri>shs#Pl76s&vqGM-vf<}(g(lE3Rk_!?Ra{7c%)s` zSNz+2FtTDKfJjUhMW0mgYK|I|DA0>D zBRxf{Vzdt}J{oXRO{f`SKB`m_<7v=Crwv+?u)7mJa7UZ<sS4Pu*r)RX#r0GYzA=aSV|^@RH;*a`1x0OKIE1XBui z0F+f}(}hNuD)wfIt`=E|y?b<>{P%Qcu(PWb#P;*$W|Zdsq(Y2bp_ArMWnGAZGO6R7 ztpWvn`6zeKlZYbx^10I$;ZSImkd0!^e0`sk|Ab%DJO1zm8vC4whv8L!Jk%MrM=o9` z@krE7RyQ5p9Tz99F|K*J0Qgi+3WIDazJfXS*t%x(fur?SC;GIl)agKhb?FoU2eFQc z3E0-=7jAG;)LCCgsMifeH{)Esuy#~PbOyD@0C=}d#QVVacE9L9rwB84y(GOc-EDHa zeIyERsV{?x5qP9&`M?B!ew<%9=Qu@IcoTB|2p%AldZIE7aOitsN}Gz4+YunCa!nM4 z1@C}SW_q8d8lb)(!l~tT@HndE)9`XI3=4=qfLDfOB)_@$ht}cs{(u;Nq6KWOO!=Lk zNJCc`zQ;u+eO~_aTkckY1KK}2Xn$99#pS{ATSR<Gkbx56Wi{FUXkv3l&MVM zBi)+<1>YyV4CF{hDPR1IHE-Cw^lkNQ+$+@kE8oEWwfo{(>BKC-mCK_t z%O*6MR{E^X`*bC9ilmU~W)(hNzO7E5zigq+yEO8!9>s1)FPK%mK{ediZ92ghhwH;* zI;lshl0{dpgKQ9g{1piBg*(60#2_$LI{=P9WHu_p@es@Ni1&YPl`}(&zlsBE_ex1f`JCnX>(CUx&?BYyeY&iPHsiXswl_x)3&+iuzsb zIHyL4ShMn}?Wfo@ljbf{6#~1_`>qL2g_f1a3-E~YBuaFsmrf-ZuZvn(r)*E1_fS^deDfpJWwW;M8!tpW0X#B z_m)lRZ_^t2J-$cGJ-QrCK!Gw;c;Bf?V$eX40LNglVPRfRCiSe_#?oBM^e7z?YMAP8 z9dIeaGIlCB7=$_OP5*r!3ybpYWncow@Ur+R8v9_Q1tI-2~qkGUrHQ`EER$&?{)^H)H9kQ{jJN~5|EH$XL` zb7p};6?a>vb^S=iNE~0a1-|v|Mr@3@#NB|hdkcb9a`}D9v%d6>!*i3qghF+Dp2XZ1 z4bB55#j+&qMfdkH`)Fh+hcM}0Nb}HBI**Nix)FcSs>8C)`|0gp!AiYm%>w0I%Jxd< zrS!o%x-HE52aC8wdo`FFi2G#POKwF|V{=q}8IR%|oPWKSYhrFQ`%cEPF{la^pXn8z zG;R@!4*3-k?|`_&-S&HB%aVOX8O-gIE8#e7a&@gG{3davDSs~8ONgF->W1AgdvE}M zy^0tAo;VnyL-YEkLo9q_`)fgE=~x=R%qZ~#YdxemS}>_9hl{^o8v^#A|>8iKJN z<^dwwIdL~37p8Qj8!mQx%FX|p7Z>B&gLr9Qf%&h7_W_v`%*wAvPozSOsqTJnX8HJ| zPf6|>HC|4!4@A9-BfG33wQl04q>E&K!tv?yHq&=wmIP0}j#~~#LP5C)o}}iXhx{l6 zSS_PBS>);lkkum12$`uCrrc#`z&7Ysbt?)lAleUVOzj;x}15V)Ql zYZ!~uBj71Zzk6N96;La^Wz@qp0vpMOY%zO(*yyYG=(&*x{MzrmC;`QV=AH=_sfKOx zFM4E31B0fZA7qy7p;AG9k1JMxUgr?L%WRCV@_jw<#hqXk=m z$f5A1z^v`#q?;?``O;(%P-nvqzZf2M3td_QNwWU*9AAC`rW3!0-9nLmJj+kqBGWCW zYHjR&y(!P$BX!iC0Sro^-H`*G`_&$5D`=y<3u>jp$Oug#o-g%hZBG$!w6d+#%@NI< zhsdT};fa&F&({!+1x2-g4K!8FH5{&P#JDt-_yoCr?PPy0(_bAkaxrrZBz0L^~e z=VWN6)~%$++pco%YUBhvzEzVL>X3Z`Elp72GfM_TzGE{5Bkza=-BIa?c74bo*w56t z-{*7@t$kbT5rkB7_80)Tn*L%Eoq%_gSRHP1U_>9M*rTaNm0Lo8|J>_hw8`d0I4Jr| zM?epFR#i{P&P^<|HKMK3QCf+~I5!m?c=Ec&6yp2_X1$c~6Y?~rTuqxoMSWjQw-bo~ z3`RO##K4HWxS3FYJtLdddojhi{MdX_i=QqVN87?829aOJ?MvB3X?H1K{YSO?ZYUI> zik!oOZM;$0^h1GvHQTD62m1a92Iq5ZgEWpy_0V*J1_)?!(EjuBTDBzZKsMj>c#PNC z1XGieix^XB+~?<+UZY~<{j24e{{s!B`l;2Pe<1zv`A^6D;ZVrcM!r==qtH9p3Lktd zvm`*Th!YB}x92$39?VPjjX}`q3N#4#AYd?Pj|w1X0ABHbf&d@z5)Oe~Fw%7iAnOvn zZCQJYlEnF|oP!)a4ui@dk%*msMQaZ(EPvzJk4?u*Z6BUb=kX=_v=(zE<#(oX97F>e z2~ia|*h_$vU`MeCZ$Mf1t6HrP?S9|}JHes=Zg$|NioVh#VC_!yG^7(?ivqE>gFx8& zM#CR=z3^#&n(oQ>d7|~t)fA3g%gv4z!(9VE&ku1|XA&fE|(0zJMMsqbO?)+`iuGAGL>F-L?2od&r5_9w#;zGXH)YO9mIec|%?k1z=+ z+Wo$#e2QuF6dH_P*OKi3jn_Es_h2lY@R85Xob(ERO(wTDln|wb>i<@Kkyl53zhNku zjdv^Y&-w*SB0&>B@c6nHsEdO^aj33F_vt-887yL>d8hwR$!?|jr3U<{;!P*$f@_*g z4l<*jPjCm1XtKNotVHSFcj1}ss~U`L(ZU|o(h}wx8r-T3Rj0@;O`A} zeu{yA_+^9Hp=S{TiGO-Z4cb;EG;^zYIr~8#2P(jZFYwzB^MC7Ruo>Q}{T(YhD=zcZ z9a%clJL?qyrCaeCFBd&4r%ef&IoS4^It^6&|2Dt#QCVMK|8q*HIWz0@k8&)eTTEFq z(TpWMQbriOS%RO-c+m6A&mswe>Mc+OR+8O+RKs>+%Et{1Knlv$JBhGBC<0JR3rz)? z2uJdDum+9^&k6Vglq9qVU6_e!|*|GSQ}>a_KiFY_#kQRQsAUH@YYWo z#0Ecq5XuD_0%z@xgczwuZEE5o20%M+$t3TxWI)5})ho}|t%Als+KoQ_~0#4Sp_vjpVS0@r9e0oBfVXmm52MgqLQu|%#z zX#}Qb8W-7kf9tIP1e}08bof3Bkc*$KTI5(mGczrmagg4{j>fg&0Miv{6bXNSq(RF3 z@N%T8kD>o<|Hg&~6}#Mu7jm^tv9uW;tz{fDzRskQV%_zy-DVQXvZ>wM#8^pl0VL); z$G>AWc#@g3(dH?GNunwr29bF zVuT4G<*u5dfA}xZQJ>?dCxNE*oKP3Z=new*1HEOcA6Ny603qYZ-4X;&g4tyZyD&lh zo}R*kLOtu#l|BZ!^ay9lngg2Gd@ck`5HzTU8Q**mGPs{g-k?+TiYGdMiYoq%!=4g9 zU*PFEoSuSQ#Tjrnw4Myl^YXX29L;{bqNrE(%N^d3fIgdv~!}$5}gXYJo zWf+ihWPp0!832mP#~spUD=NN&&meO|R=(EAf=x&_#;5>I`^G(eevWl>RIMkDpTj}@ z)a#U!BKNAQY}9bDCl_)fRww&uy81@{)qYost;)!?Xuj+t<-Ep!d54S|x9pgwbv)z4 z6aN=9m8}4U+Y^_CBW+A_=l&ITpz3}5$|-8S$fRsprd{D}zgHvdv-S`Pn zv}pu??3R?S9+b?@HdRhstDuz~MC2D7GopgwP+heOtflq&GsQ57dPSDcAV6DP$NI=d|z)6 zTNR%7-p=QLzSr#bi?z^I^>fD(P6eAPgZhf*+V9_e-2DIoP@l?sAIRnaw18T90nEhC z;n&EP{meFgkL7BTk1b_lI;E-Z>!Ri&^CX#G8ooIcjzcQD-8n zjER;vDkXp2mFLPL3m(}h+|ZS70AAL(HaYNaK%BCFg6CnxMSd6M(2wHHK}++C{sI1(=YP1k|%N~!<6>H1@}DKRlkLVuq2HVIdk+7(*k zV^nrMI%XErswq`qm{N-n`P4hp;KpCU8dYQg#Zj#k^cJs%Di6s7#Q$KkEka5m-T5(E zIDx!>NbaEP0-BS#Rf!oX{|Y1kXr{eq$FD|8dFJ;O?=?28Z?s>i1t`r=C~s{+B*jw< zzg9QF{PU&{?B~qI10o{K>{DCD5ni>ExwodP8@e~%Dht)ThVlVWrl9wp%?F@#L^tz( zvAaL`C^`GTLwppCXQweWezXGxEUxdDHAb|5Vk10HbPy}DADAxRg7dZES4CwA zud&rlC>ie;6OwG<%mp-CK}nZ0WNs{&n^m)Y{FT`ka1bxu?Gs~?oF>g@NMoVLx=#4lZ1&RRI({ySXVQc2an-Dwacg0r;A<5a06 zkmqtD)BQ2B?RoaXTh)QZ<=CL2bdW!_1Hhx_tMbn>Pi1%CsRh21j06N2D!bd_ftl}a zgNY1x*py3o18`b5+njohvatfU<(-CqlQ*xaIRzJ5QP1c$U206+*od7UV&`2Mh3?B| z0@<%HIx!a5GKn}h-=nb?-fhJffhN~>=eKY`h*`=wqw;EN5R+?)+JnBM{L^CMa?}IO zu>S2)519*8o6BIw&7xBMEziuN-MoQB6=V}{$^^f&*c!zmUnJk6G4ERk>G`*R@i#Cw zvHl+X^Eqd$R07J7P-i<*R{hlhWICpf1chXV`6pHjPeeukLg)CXYz=+<&>RDS4SD!_ z5H+P|cq+omPQX~JpVX}igFEj%SU)f(Mm$Ii+j!r6AVTx0IR$ee$mBv8te6I^SDqbD zs8Pj^>kZA<4!Hh=a904=8HEjhQ#OG!J?)r@!sU**rYJLawQxC`2P?n$PLTAoYK#=0 zHostG8JD39!eNi+HP?aObCJ@^j||~g!G0Y8+iT8%7gANb;VUMrRd(Qj15;@v7-jiB zMD)*16GkfNKHFD;ss1t%lUc`l8Ke??7aAeH9L04Eej{}J?A$s%^5`0W9w<`zlV+uh zzo5OPjsxeoNF&$MZ=QQtAPxmU1dEN3(G?3g1mIM>+B?p&b@zk$6 z@0g&OKYp+9(Iu2N!Ybp!Qg!1)X^@FB=~=R6Kh3I8=~^l8?U>Rz{H~{#1G>3}T=EO* zqk5F8_}ii*(w=Up_TycD@B)2TX6PZ#FV-Xm@6tKYxisHpJ{kW=cj6gg2ODusRmZ+~ zEEXbKLO_B@^oCL}twM3kEPt7roccabNNf+n@8J|Eok87RbbUiP2|i(}_d&@k(=Vb=p@qZ{Z(&3F3CgC z{|ihFmA3qX;cCJ*8g0!{-Jo|JDLE8m!pjD@itwb=Tuq-^SML#U)f!Sx$4UZkz1)`C zF*^6pJx#cO_A3l2j}J?nhi7z$H!kfe0^QLGJe=}LuFJ^OIsX5kGy~k|AOOM;cCxtr zl*IRPg}Qz5to}cT2Ja5$m zjori0kyLYiqvZSzz5JFP4$y=EN=@%k6!v=$)t78GOv@(zbKKN8t_O<-&!? zRc1?`?b=jNhKx+;5%buFHQmH`wWYAK zstGenn%26NzwvPd6i{b|P^DLF50hFlLdYb9$Y5ZXmZTBnZdtq_kXe%tOe!>eI=ikg ztJ@Etu#$TuLc3y!L6q4DER4=Vt`>C%%tQ)6W+|bJ&i!;t6ePt;Z{cqPRu*2|>S$hn zjV4ssruw0&r$t|iFRXu^@s;ct6Bhm3pYXi{r=g3qnw(C&w;hadO!O{Kkw`a>gp#l z1uyKsarG~))C^T=v*2&gGsuCwD^$6T4*iUQLhvCaQN4vX+LkB<=+ta7{LnztK5Z*p zr$p<325+6CkANR=D?7Ucf>qY!3bR1x1rPu&JBDKN$08{2=RKaFtDzr{|7JIT^6R!( z%O*E1U_=TzCWkU&em-NTzWCx9! z(p)j$pYF@^Lyh61ETRXcQ=U(pQw+`4d1kYiKn12>Uwwu6sF>8!@HLYC)$B2pDq%s1 z7Ttn0`~8!F!ga5$v!-~6r+)5#3LUv*DVQ%n^6}`6WO?ESNG3rd{z*6>Q+zNq+3v2L9 zZ=b=MFmNd!fJ-d@NH|_MPs`EUz(^Q_NBK_GbV41;@HXySHdKnG3psc?oZC5O)u(Eq z5tM)w9`Oy|-d8=B>ny;3y+I#;ga&n8+R(ujDj2a}viLWR{f78^6JQtN&sl!GamdSo z?B4}mxBdClz#GoN;xTx#RlfZ#&w`{u*ria=XkV7Akp(?k?4O}RwF8Gb=87=lQfNr{x2o!uT zsCMFymyYOtswBqd6pmToZx6Py5zkR#0bn-n=}o}ImR$OO4p|1PJB#uC!2gpynO4`m zO=)+>#2QOAj>ph*7ea})J3CfQ{N!Va+dWHr6tw+>l>dn~&{Xl4{R9dR!cB!AsYUzX zO#FLyQ9e$d_F+l^EqDn`p$zZf0OW66FD*!j0@|c@bVeY#?xqpIK(YFxlURnzL)p3p$emn(14sZC*%rhQH>b=Z)c?Qli{r&o zrPX_Zj<Q9;=)|$)4K2H}PPvUhfl0bxzP?mK zj~646P-bM@@Dz69GJ4rlz5+~yE5&5&&jhRN(OrAsRJ1}Cnz8eB54Sy7x%yjx>jNy) z&G6lS=g*Jj{=)-{jgWWAt29opwG*I&0jlw0(Ah&kKO7C$&{I3Us<==E!vk$k8r8RI{XdaEHVi`RBjmkaoIb!T>P@z zyZ+t4Rw$oHM|PiP>-)>Y(kfkVPmlonwjQEmA`v)M^B;~zKPB6SNJDG>e2pgK)IIfo zLOZn$PZnkIY19d=FvTJVCUXPU7imH-(%DFW4AC)A4;UxLHv)+6#ZK&z5{q}K0+}z& z&?&(;h^FFqUNTaA!hzA%c=zfzr~;A2N>7>c@XsB<)}2^fowpnx6m&{TC2^l*ITno*dUtUvx%A2 zEIBDyse7#@%Yr*w z@zemn%}2;p?=dZ(^Mle}@&f4hbo_>r!11ACLl^n;+nv67{&>Y+eQIq+fl2d!^R6(r z(@iWWxBnGG?8skbw;)n&{u`Sv%@8m8bX_{NdWUQjx=H@ttP(=a@=iO)>>^)wFvaY! z87)UV5Gn;0gWPlQ=YYEQs=@ax^(L3qKd;%7^#K2)S#E!c>@R069oCZj^*oXa>OzaRtHK&jVCX3Z|z%fwEy zfq}ZvB5DMF59Gde{Z^1lh*=&4stL~1(?jYwily?sp%X#6CAlmw2xPtIGHi2uKO1OP zJPxE|?gR=aPyeiZ`}_iAZ2Fr^{2C0mj;ro~JK#MIanr1HB2BL(cqO2JylXC*?G5H- zg#4elMZ$(7Lp0*5PysW&Z*Pkbrse82Ywf&H<_E$d`^5n~?&xll5=Kj^h6dk3#ZR!# z*lFw?^O`$V-9990gdXsjEcS+vL9yH^!k(gcQqOA!$~kkjM)7>}4@7E{t@{G)q^+hY zWW=hD`-E4~E!z^Pu2Eip-?^B>hej76FRDU7%f1K?%80YGQpV(VlVoD z2OJB~UM+-v_p&~HG6?R01jGz6%AInT=ZEy~&a6R%C+*q%-l!iepCu9Mo+$Yjq$x1+ zJT*u4Iz#=(10+X(9<_s4{D5wRS|w|upchfae+1YQfzt27UIA~g96+YbYnp#JRR2kz zDFD9texyNiqAY*vTnr5h(%E;EU5EBN0%r?#MGFusC-R7yO0s$#_C!8G8UJD;zn4rF z6l^&R%GZHSLZaHrzdmH-WoU7jOJj%26&-I!z*m zMy85?@Y2M8S@;WGn2H)f50|Se+(c*tc0dhrZJv}uZ-9p8+*l~@`B1jXbx2ykrAVhF zPn89P3H3=kU?#;8fV3f2_DUzdCc{Z8O<)iyg=7SkW1$cLb3QMM!lG8Z@K&rM_omfN zAe?1FFyjKXfwtMMR=N!rJ>GOT>X*NH+XjnzuQx@1<0?P+R5JY1nF|Kf>oh{l^)mP$ z&&Bn~$&LwFb2)qeReuAk5Ile?V!c76#l%dGq4|fC4t;M2{O@BtN{L+Oqb}FXplj%f z@JN1vGL8*~v-;+~*tjns165TbBX{FE6O_~ZQ**P;o#ZfCu(oQzjQ&ag{HyU;p6z>R z7lmzq7{7zHLD;2U_EB+?7@-%@yeaK@KW@Q}5HHfh``G7t;;-TK0k;#`Z}`5pKt;ae zJvd4J3A2;>b*8K5U8%Fd9579wYHQtu-qJCqhpUtdac%o;7ti75o&McP1^HJ1Rc^MK z(L@D#MZEYa-7DUkTo{4Jsuj)wUETo3s|Uh=gib=5WfLcm!ZAn~4LnkRyHKub3Vt}@ zVD%+CQWg9cY-77WtbusHFH; zH*Zlpwz=*pULmvtuz5OZZZ`dr!{l{;FbnKodnMF1#Lt?5TSX5@3AgB!zqe0WT4;c0 zq~0QF4c$gj(~$iEK@okOzf#|ckL*(E&)Do!k{@0~qCm}G2@TpN$JX$Mi%DqM6Oc&V zeiboFg|p|+P_^AMr44m`6qD4&O7Q?6#mopldMl#nA15BG{%-&>&kw(S4(BI*0tmlvX zT{c%09`zSUO)IK~2t~Bwd+nNkm(W4uY9160k5^OEl6F2wqkvBE4g*sG7ro-XL=R~M zzT5x+9+a8`)aHuM3cHsnbLLy6IJ%EGW9=wSR3@=EGTd ziy#OK97HhiwaMMjybd$e+Zb#D2`o31)tsdIUfs{Ypa8hxN+-)jX+!BR9MF;QZK@vA-!lLCBX+=L!tQ>^Ux_*;P5uXW9qw&m;==` z>IRloOWPoNZPd){Zt$Id#OC^nG$A}J-kZRqGDT$Z?0&Tru}C6Gxe2%0E#f|#KtPUX zrBu~ch);aKbW6`)VF1QtVPC-eejTTv0Q3ckVJ*we_kpn!V_=7gyZ4X-0^-yijZT-a zJjxAI#`~R19+YZz>#g1>6#aG2+(dBsi|)Ot3YLEOcVU@O3*M}MeMj6fXoTDBBVUI9 z5m7*C*~J!_`_|0}X-S2&rJ_4fLgwJ>2F3+W$%~VY*N<(4qOtyNamH{3hv|iBGgLs$ z3~;>XzIhV|=?Gs1>l*PEL+C(V!Wd`h$xG_hzsz%O7henkvkiepl(xQ=JBCAn1&`~AZg1V8^2>Y3c zfs5qZUtV_GPO*X2j)7F2a0**be{bd_0@I%r0I6s+7DlFj75dcOTlTA3Xfk|x1$P2N z`4nf0tj3X-^4ZnWJ>NW4(Wpc36P&%4^gIYyJC4j#D);ta!KpU_jo>~ zti{7M>7cpG&n{(^XCJZD!g>)JM1Ao`MZ5xgl>EPcdWHb1WTS0VP8=>(+QIz7N8&eI z66+_v^E=@&og$sXWdHz}Y|kh6!}GuBIGv`DIjE+XTIQRHDw&#NaTkA&wCVk-E$lOZ zDPvFxIj4K@YBKBTk_RK_7i;-B#xXnDv?jnKNjKpk9x@wP`gz@Dt;RXteMCQVkO>L3 zlK$&|`utt9PuttK$6Q4U`R=lXsZi^ZZNOu^SJ&a8w{NLM9-fxC0z@Oh1RRkqdNP^< z`U-!Y1e26t2O3XhHw{x^C$PM>I@Ubh{JggvEM z?=|aVVufO%KQuPHIOqh>C>v!1Lh6esrc3Vo_J1Aw8?J+0^}M<>e-=^4{$_xIger!A zm}FZ^&R+$$9Sq~(If|?;-syrAc?UkzqzyDitceynK$9>7fG$M^L zSzNr5clye0+O)_3#d=H*|MB*?9u*eDMlf&9lfKn#`is6}xADMkQG#chlU(YVG|OR!Lvh+=@~-n+cbH$f{t^ z(3_L~Rtp{C+oqd3p9`4h?xvMSyzLb(-n4KDvsg?r#El&ZNl%d^!PMu@SOyHMl zh(=LjY1%C4(s4k+&#phvWB~)jAGNP1C)wabq;c*2wHsE`bHY({9~RU9ye z!XYgNI+cz@eH(T~QNY>;dyZW!02u{jZI%=2&>h<0Y=`?h=Z}PckJbntbxBd2ob(P| z#8kZ8n{#57vr?6X^-ncy2qz9;1w5-j6u6d;rs7WDG_UmwsKdw256i$<ulBY`_G*HHhY4f*7V0O}%~_OIM)jW+MC z*rK#@%lRoztO}RH?+sV1b(9_TD}wc>mGAg+-$|K1ZQ-WgeTKu&ovJgfbfBP2`Gn2^ zv5y$edpR$Cqv9^TP2FeU1u9hBCiC@VBn>Z?_z23opMa@^c2Gj=(ezSgM@Cc2{iJl3nHqHv0fo5gO( z>yWxYXWp(KJG_d}{Qpy(pWIs!;JRTH1q8(JwzQ8?SN2Yvw2&z63o z-0zq!bQ!gOTlWxZOo^j?^N)d?%e$a1j~Vn`VaXr)MoW3;Q}m?$V*^kK=JtqYXMN-X zmt~s5h*ZbXqZWGT)ml=2R{C#3`G6=Dp#Y7N5Xkk#3bbb?Qvx?HqJ>k&ldWoo8X4kz z9HPLL@CJpkP(7}m;4#oKDdqj{80d9dv>+nDK(JhYt5kj_Tz-BCakjTX=%5;L`;i0G zJAJM1QiiT;|BYZEUw|J+Q54os;E3!kz%Ewbt^o$#09z`0;PATT6Ls8O9>vp#eAw{* z6h^`H_(PMm!xmLva{a6F3FM*6KMq_EQv|5s@e=s29woT{0U;iRKal3tm)pza5{n{*f9>wQ&Ss-xmXHwfanI!rjqP!2MHXs1%vg9dgoGI@b3am`1) zz(Yo6YR!J$d`Knn_L~m2)$WQN@2Lg(Eu8>=(s@2K@;&AZx@;D49>XZEola*DBTkkt ziUF>Vst@(FIJ94MNPX#lVgMLWf@$U2Uh9-hmq9z==lJzS0MWv?@WL;HdZU?){yE%u z=K2N*Rq3J|(EE)t1tt(hb;Bcx`_d1}WNm&6j#{#Du7O`RzWf%Hpxtkx64Ifz zXVtL^IdTvR{OB#}4UbfJsg*d8q0IBE{vbNd-!#K))f?4Xz1;sSn?T0Y_cw3V>e*r( z0#fDwz~l4P&idsjT92&wIQoQA)2cRqhB+|)gin)eKPH~{0a7f%Roc1oRDONG!_epi zd@7AOLA#if?o_Ip&Kf3YE!c-}Xg`;7ARB`l18^WysC(v63+3#1%(|Y^$FsaNs;@ir zEU=2QA0xp*DDv&0=0ME?21uLq`t64tKfpOYZ&No^E9atU=zH$E0psj>8<6*Z_s&v% zuRv#S*pvUs&tJnK)b^cO;h*=slzq@I&8)uyo46?h{PzFw3UhcAX#o4r@KD~|AXMuL zuk8fQ^N=<=wMNyd%mt=B(>`n&l@w$?tQH{qB!oly4YG+Kt{;s9QRc)0CL;+i+zs%t zQ*XH60b?t+0E5W`y@cEOi;uj2bimy^Nk-p1bEst(uCWXec%VosrV;2YVe8iI7)NoC zYPk%GH>vjSH>#H@mJBo=K3~qvvX_i)s$HA}m%&x2siRAf`3?N&fUEz~<6I&Asg^#^ zv;z-6$@&>qH;OZCO8AZ_QV!HU+*eHY1DAkqD1j<1JBh%@YIsb4%e9<;-?o3TVX<<> zb{Og`UOw2ZUZ4}}KfY`NUWoAl0lsaz<<6aD?h3pU!?_)(VPJm7J2yR)Y=jL!;_K&5 z8xz|3+fg$J{%J+g<~z48um^Ebt;++S=_BOG!WQo!iLcg;BVCJv>Gnp9XB7TFQ8nlf zGs^H4>P~)r$yeJ5vhALK9}}|4)pT?EI=yihK6yI>)90ZeZhNMCLK_{Hw|^M)>gi-} z7a9Lh!*xi4-)>ZY#;J-$FLRL%Ux;+JUcs_ZDG+9xgjQ1_0S}V3cixj7mdF6ksv9pC z%&Gq-@V8Itus-k(or10?9Rm>#x*%p!I-qS%xO{sj1#Z`q8Px56Kqj=lcKFOKBDgaSaVwz=xI|8~zqd%Nv-0Ibx?a9ybvrB~#dIyLGAytZMczu%78V>Nq& ze?dhz9Bm_1KsO*NStz@Y+Ffnz-f6p>BuU2x+GP-5mIn%dk6cB0c7o!e=AI2|&~V^< zGbzZ6$)+2C#G=pbImst%_-R+ILG-I8lJ!~n3AAwfksbsw@y88a_;0pL+>OWrBgGbo73hUNjw6bumt{oh&ux)Pp;`p$#h_pU0|&f;rk752U^AF zXliPms`uo7<|O%G7Aj0+16&C_ThD3xV4c~?rGeBGY5!NU?0SNeTg4Z85}QSk3bS@@ z-bjK*s06$aja2E_J@tPQ|2nEf+hmvXZ zh`(B^MXzW!lF$dC-VH2XN{dm@o1JWv?I(ekhKOr_rhH9!tDyG+$-SOIDM)}u8okU@ zOkiqs87dEbxzh=71+OjA@G>L-dmJ+tyS(T5#E@HjzB(%9w>`QOp(46hsD#owq-IKDAu!h0_6G6utd0 zH3BscPL5H(4Z(f=OMqf}qOR-Vb!Al3cY=3+rVSE@llHXsZ)ncfe;3};9jTOy<{JWw zlB!;mqM8EGZ0Z=oZPva;ozzucXkL7(3$~bOB?Jyh?V^`20ip{SR%-z$^5V zeecR#i1W+8&lH(WGuyO%-Ua0P_mXu}%m7|=uULQj_t+#*GaRnp6m48yc5X;TvTjO$ z>Fj1auoBEyy_=7DYTcTDcm{}Zo(NA+S&V{4|AY>K4b=NRAOUsYS58oJfINZ}4q${tnn4)vEeE!kuLRoSl+ z<5o!{+6XAk+cHCx2i=7I#2PL&=2(4!76Sbu%5hYJzoH{t=%Ug?r`<^=dDqvBQND7_#+v;=2sGYix|KPhUnjLHVBQPLYI4L1MN z#w^qIM17T4{-F5cTRf@$8Uz!6`#)n;Fm@b}a~qsp`O#-tKYs079+>MX?(&nSs8Il>S6Jj)1h zD7-@5gt)L8A83+F4ZAwF$jm?WhG1KX?MDcQgrMMI`sU{Pm^CPzq{eVcPQ7IqL%$l6RIzmy`h=D*Y^wWi z{1kh@f>B8uPacvk7+*5fSVYJ^=o^A!R|_x^{y~f!%eP8vT>zBYY!OeD5U+Wsc;RK{ z7OFikxw`lj>s&q)C(1;Bfn2!$*u|xl5f^p8Rk52WX!bd4N$#jaQf;er^fO~WG3H5j z&!j~QfVsGHsX3WWn%dsa=f zr%yH+BALWW1;6FEAT{tp?)Jilh}o!ft*6WEl3tvvm_4$DEp7StLqq`pRqRnlG}Vq2 zej9)VOX~a9KOl{+C0+q-wM!WP83!Rjl3B!H*afN9am z9s3UM^a_5yZorU2oa9^Xp11-UIp)8YF-DKD_iPexmflVWW+5gJ2+6sumR)B^A5mhp z77yR2amLlRUKB=r(%Nwm1@%$$q+p=g!qH7}P}7)crGm@mSG^Nk5oQW;!;nR4-AwQ@7$Kak95okvf%k&~w z5sj`SlW{f!|8J3sFW*1fA?c;~JBC`B<#fOap{!&mRQ)!vjq1gJdmC&{?lTynQ^otc92`iTu>vx% zqTm_9oc@myu-4{k1a(+!6&-<_oY5bs=y~37(kC-*f81&`-1!j@pK1Wn8dF{YAID8a z9~T!96N{bRbL=oD0x!%6AG#y{axTCvFOfO(F_|z2?ZtObBvG=H4!lOxX1i*KSXgIe zbtS5QoIHTy440kf{Kknur1V5FH=2ihsBpV;TMzrofLF<#Lmu$YQ7N|dv=P7>bRm695%YE$6fsPT@Ln1QbiQskL5Z z)R+dF+`4Ir=mUwO!T@OjS}+@`Tyhjnony1*BYb_}xE^kgrjC%~a>sqAdpc=c!hm>N zvbsmQf6qI`i>MlK2Zr@rj+xR?Cju}2I!Ae*z_;j-OO^OR$!Lkj-KSxstq_hPR5u?t z7ppOA-=#Nn24knFc1m%=Hm?%ze`w|q_Q@cL@Er6}+Q5>{Z zDRcX86BvPwWI73XX%xzG^KOL{{XYFcBqSVRQ|vHkKoUC9+j#sDCbd_*JOIfXAdSC1 ze=#~@xEsA8(;eDc8C5nNWLKd?Eas!9c-z-yaay;}jF3WjtC?mN$uSzNg_=!EivK;k zKeoQfZO70^CsN7oM$|5rVHaU1yK8?v;jRgRv ziZW3{^h9m_0YXTDW(7XEAAv#Dl31}Ke|@@&(r$;{-hEy)uJ7#yeKk|=QG6UsoU`u~ zX-+29?Fq=17i&JDwZ0mUMpxYMM@Iy#W+5(7el7gJ3OyaP3vL4ETPA=C=~;*F~C z#&>^Fdk2z$7araQK?cdJRb)Ig13%tYwA-Wdf3=QZb*hY)oBA}B8+wPCh^vb9f9pU< z7~bEd7q&o}OUJ@GkJ!>1599dWhFn7j3BV!$0vPMs1gHScfD$hPDJi}3jk8jUfC+`O zc^|7mn9Dnx-H**0msJ4X(KTDa0J+SR9eo$lx$phpM||`SaR%kI>^$1m=*~lT=ugc+ zZV^btiBX*(I%RCgG3kES-X765e`T^ia-rHYQT(ZezoB)}nfC420*Au9UXn)F?BcZ-eC`W+`>3|==e*?{Pyo3P` zpAe4z3I=si^-y2u15-0a6s^~^0g`K2=tuPR13-2X;PHD zmY`IiZ8L{~Ro)g93Ctj3f7DJAI84V!gW>=R^l*`aYQTS$@xO>Y?#etq+23<{mJM zFSm;uZ}lLT3m!_w67Ar8YNeOppB(j4R@rxiwwu+PR)kz`uv$o|f7mnswo-R)s(uMP zI7E!Y=fJrT*OqKL0d4#GNC`=vOvM9SutW*J$`>~o-Lk-_>xW%qQtkKdPqv6`dz;u+ zMH!A*P|sURF8(8*!FDn}N6-yYYaiL>%eE?dXR-W;89*mSV;+Z7_ognQT{nmPBHn!6 zVtQha_-iXuokP{(e`xB^YWtN7fQyd=5B{3bue;s?qaW8ktv4RiWyX}(Ao#l_Ml(Y}#ZQ9# zqVV?m%#A6~e+JT+sOxRk)K{dfjI?x|gaXdQiY_osP(2Ne+Xj1E#1*YG2QBMFBl4kI zI~Q_6BXn^NcxysVQP!E}a32(}K%V(Hztr!B@I|OXx~gJwFnOZ$MK>SsAk|~FXpPd4 zX=zYCqWGyV6)h%5bzeF}>_F>|GQi62-6TWHN2J{5e-+-5I=%+CAm_9S+zzlHSy3DC zU#h44py7In_j)`Bwi5fhUNO4>ovJM-m1u#h{fhyg9x3=iP|8550K2ZZY)m){*V$|) z6%$8|4f3ObhM8!TtCw^Ab>0{b4|mf|aYyt!aIovk-S3Kf_nO^{jv)2}=Rh~`L@Cw^ zs9|v?e}74;+I>Wp2VGNvrXYVf6J~+qsP6C_Kgl#s?Btb>xK}Nc)oJ&i@4ji^2=jp$ z-q26_ElO&r(q%WPFV2{hLlM6OlrPqz&os~YLq}~?aXU(%DVr*|F`nn71%_;L&*}%< zSNI7mQEL8bt_n20bi#2MicKcUfs9akOOHPkIiyhdO^+2PD^(+m5`~o+vi`faa^@UewU*n&#ERr9-nq zZV&*i4lh}n_N&2ho7fL~q(yz1PCv_9>WDYjSYuHe(j%F^>cjdNQ*IlK9L}9j@$M4< z0Lb9nR++a6LAylhkP4!!jd;y|6NE!fe^H5(b0Vx2SsNmNPA}ynHS37A2=^Z!;5x)TTC^6$ z+kN;IqX8y`l)Exq%b!(f7I~?^Xa3Zus+@Fd-{n%()KW31-O= zq}%yqXoEm0N7jF`tb=&xN8ZhPJVZL)g@e}RToTSkLeiOE20xipILb7S)ClB9BwQ>E5VX8cLl zrwiOU!p-@>0$-l%ayoE8CATaP;z*jR@J$2*`}QL~-U*VTS`%6T@+PsQ&sq5z`1ZgM zI``?m+i8nB2Fp?|qV>v!u?FLkevv0#s;^!JTT(xD&?P6B_+@(UM#y)ie`fIpog642 zUT6T>3cN1Lz^Tlz2#l2?)F?#Tc4;OK+3jU49U|qNE=pYyNGWG%a zL0OrWkN~pPrcxArpYs1ZL65Zm-?CVdD!R(YHynKcEHryI{hIPj-x)dsI$z$#*JY0c z4J-C058P$MvoD}8J7!v^f6xN`=z*wDgT{NqNmOdl{XxITU5USi)fHgyUOM3CB=?Sx zQ#HCrEu*AD*oiPf-W5EVgmXSdEa6#ycds~ z$OOL@cl`|88RXq`lU$OFU2bMfvW!Nl`6@IcT&VPm#`99U~A_L8raML&{>(lZ9WPft+*ZhcyfyF^>80#`8q}e&x{UpU);N&b; z0>AlW=)WL~fA8m{o(>r7YfrfDJ6s0T5I%Of1DvW>611ot$P~o_YqWF6Efnb#5C*(? zlpsL#zsML5xV-797;HX2jD5?D*`M_4q@^cO#&S9WPXq`UI#HXY`bXW$Yjmnta5DUL z<_4eFuFF5#bU3IizqUkJWjqr)M`Moc{lbNTG`%_De_T5K_oMA%2Mf8LL=)@>u#SLG zI|W9;5?rT>vqsnuL*Fn?TPfyoA@xsUR^46wq-L8n1>V8RQ_bVy5UJ0&>&XmM==n`y za+vt!;(urnYOtkiyTm*S5As8Sz7c=mK(y2`c}fQa0mCSNGF3-Hg7Q97fMz&|tYo@2 zp))m~f6}9eu>!QxKe5} z8T&TJ@d3lh)NHXHzM6X{{|TO4?ijnNVOGi(uk2U*G9agvpdMz8-gnl1slRJxhiYDC z-0-KEs>DrIHjRrm+2%Y8?>VO%u4#*{R&KwIe@|!yJ8dzco_o0#aLle`B>W+irqUaNcaYt>jt%NA8XRR2w>g zf22F|L|=EDxmX|XhvzJ9z*3;YLm`zUla8ZY5gW2Upp`i4r62;(lmpQq0o56a|Bm$F zbw`b888^RyYLiWlg?5LUQ)$t_=U|ny?#h~mxA@RXX%#qd;gFWQ@lk9*2H^#{mJeFB z>r<@97?s}^2<$ZUin-72dKTQCE{afme_7w1Ig$@a1`y5AHRzVJDM{?7hcNLuO*NI9dMv)A0FyvIp+Ji( zE@pcXP<7x3=6-4yDk@fyOyF2#BXi{-m{)B{i8L*=9|LIh8?je57?dB4%=!NWfArtk z4IlRkr_nvJZ?ok8z@p5JW|a5;&1NbkR*Ok_;4N$DsA#L>k@Xdv0J<-<4Hps1;`Xe_ z1;ee9OY8!e%lTJxgM`wSkIK?8-9!91AlST|j>uANx^7f((vpv7^79pGSb>_0_fHNa z47kk8X5&6cWL+;nPPH4#d2SWWf6U05V-Y9PZN+ci$N^LVZh?9L3nvt(X^Qq)Ek!`Y zXvv@*ONawLK%XSou;nRQ5AgdP8jBsWDl!!7pH=(`btF0A0vGNlpAT=KqC^f4X1yys8v_ zd)uJXq>v;3)z|QgS|msysKZC0Jl$Wf0EduBSDwR-W-#j5;-+M~XXIc!`0O|!0ke?Z zAjjt~AJ+-43j##{GNd@B<{nJBA9v!UJ{}?Tmk!dYIZzEQQvd2WU08v(uwtpLQ&mt4 zNF`}gC9kQ9UgQ)xkgXa8e^3r1jgr-~l@|V{onQic=s(4z`7V?@FsUHPQ?5XY}df`gTM8RAy89=2*oUxwawm zxE^k}RJ&`8Xp1k_qBc3V&AW_FTSvY3Jw&JfVGdF&W%dsO9N{+V6C2oz;wTczhAlp1^ zCbBoxaMHD;-ot)r7YU24x~aK61PpZ_9|Z7C z9{Ws0XH{U{CYZj^>~?b zVWB zDw?}w^c80!Jjt$fzjVALo_MJ5Kp`~L{Xa9f1b0|iROfygp~Vq_HbkB)w)iP8nS7U8hz}}V?@)a{s1B9fr+*gJ_rLGYVqTkSE_#$ zNQMTrf09snRhafqypogL*KhtlE;de%DodYt&sU5dnj@axns^hL)=v?HGt^va1Ca1| zs*Zc$IZp;4i+lfI=qlI!GiBvfOOUJ9#@;!9z*auL^!_L`qoX4N+hH^9;V7^gEdzy| zywXV}1wkz&y(#tyowh4RGgeCU&ffh~W`qJff51QsU_B-vkQnP3Ivxby;?YL}9Sn-l zzWt`yl0-gAA5*$L|L1q;|v^acNhnKg(P()g&Cm}_k zf9$3{qaSC=Wr>w304Z36Or5abBUyE#Hf>{Ezt+2e1h-h?U=fx57aqD>omihqYSk#2 zvPPoRJA#&MF10TPS^})k0#Xv^Q*NjUD~E2OZI9fU+T4z{{!;z_a+eBsz2u9e-0J1 zbG81HgW3Kp93SA=l5bk!hNEkP-szmIMc2}*+;N$K$sG!#zGe#mj;i!Okc8$ZK{-30 z^MLY)S>m)tADRFFp9yN^JotqT%%QyFa!G=DV&4|$E)RI%&#>ewM{1jC`a};W)O;wC zBF+jc#L7Ga)~3+v!Tx_EivG;@xGWdU&%V7wCjiOaTu=aepRK<+U9-=WS%)}9fAA(b$g>l^ z9=@=4MPZUJPZa^4+0s>Bq%gkT3&X8|pEwKA-X?rQ-1iPPCL*gKpwIhnxF<^mH0l=K zR7K+3nmg|J$CKd}K1cIPk6mJ4vh+4L>+v#{fx7{^{Y0%>7C5!+Uj-T_FjlGGDcbMi z25xSs(1;};49R%63C_jJe~1Nt&;fT$pPwsI0b(7kq5<*ZCUHIe-MfQ?5dz4BvP)s2 zbB|kT<*uU2{%5bPr{2Gi*<{Lm368m-?+j2QKJfN>eZROKXd1nGqtaU0GUgdz8Lriw z=U$m50Q|Got+7)P>42Sa3(lQ1BSPcF=I6_{vz(&Md4nx?rfmU}e>gU7-)TX%*KoqD zuW^ZJvr$kFOPH4fcwO~79Ll-QWXFMK8!Pf=9Nu3J7o2~W3tXYRGJk&-uZce&%$-!8 zK8;Sz-se~1f=*)}nh`Gdj|=XU(7WW?@)i4!$P$m^$evH)is|jrr7tR`UU!HU?-*Xi zSSRYPM2;_cKOshXe^boFzfxl+pByVS5Ei~&sprECZOTeosMr02CIHm>&^^fRfiMV- z>hD*dbyWuA`2sYE`dS`f3cv38}}q41{-@UHiyMT z&_{80u=e3e>U^Mq%_De~x^|QhGd@sKv6()KCQiDl_ZcBr{q=PxqI!ulnF2G=d3HSZ zpC}W`;=VF-DYbo!duzH3jYv_|;eF0fxsE^vuLthUwMGD|2)R)J?_^|Om`eQsjZ+6) zh)7|2@pXd{f0R^kQfX4D<285+F}n~AN{*Y)Z2E59f0y2#We(A+%b?j4%7tIEpxax0 z==*U%zW5)fF6PF)+qaxYOjlp}N(Wk;GhtHG?cR?lYWhR6DOukBqZx}p54Q_v<(eoE z75xDNM2O}|Qd4~=^9LwO3Y*g_n!X06jbgvrA}>N3e{iq*w!Zn=1PuZUrvKZj=a2bw z1G4Ro^U5R>|HmttMejp4pD*;ayQaTqskm2Vo>Nw>I|o?>+R40yojWxMM8W#>(YwY~ z%-)uz;AqjVa|}5D5EwfcS^z-X0!j67#ZNZ+m=j<}hzSqNtY_36y(3Acm7hC*lv#MT z*~he8e=?I_0Txwcqg=J9go~3aPF;$06G`|JO4&zf0FQVBK^cgjDjq~r7q@Ap3)+65 zK!B^N6luqPyNuaw&bWjL{}YRE8X^{X;0rg~BE1Ve$05T~qmAek_*)9oMz7>^p;-EU zW641biUF6xD1jt3o)Ox$F`)B_60jpFd(6} zqf74+S40qIQ%?@hV1P}UT&41Li15YJKpGz-$3llU5jv(wP^X9;Q*R0f^*M$9gWNPS z=o&#s+!CBKBg6!p?{lb)2SdwF6@sayS8aiYR8ZIFKNQW;f5yGr8{V8}&<#CO_65JX zfBn;8a{U4z3sCh~RB2qTu3Pk_@ya-(CHTWJ&bj&up40B)gLvd=GgOabMVW_^9dnID zM1%wg-~ey#-(T|CsnXlYpejWdfOROI)d>KMu5`2E`$B~%tCs!u_n!WT%n_wCMXb>y ze-M%wU`iWUdpGJnrnU-9SZJwe;^!^AGqd4cALf1%_5soYwp%f@1Y`_;$f@R zDNlJ)t1`@5xoFX~3P(LWnov<(v@`RWm0?Yo2|81*Kk!q_1X!LJA3%XqKQFZu-f_iT z!a^98SMc%#G$B-HDz3e2<@%W7>hu)0A_cm5E$^GX=KwNUsdoIV$bCg*n<5;xfB&Ny z`haw%g&o-I6irO*1+0?zHV^W{f=8JtumC?%GQ4z=9dtshJ50SbMay~xEg`7N4m`7I zJNgK^CfOy>jNY;+SmSU5T{dm{|*m-~`4fqftPh z`ckvcP7PvDr9KM}IpZrVxo_!XI)&C*?;@J8vg-8>o)NhmfotVn6n}n4e~q4en)QOX zC>8xzMjpHJD2esnJg^VA<)E-ljqm1ydVFt=tU&&d4?eTi$>}r3$xxw4`n$%nDnJKk z*gK8;z#N6G&+AK^im=}0u~j3BB>6|3i^$~G;A!kw*K22xBx%#%EKDO|t-zsau%-l( z#JJOg^mmvBvB9*GMtu&be<@~Ic{_bx?l45|;L5HR+FcZWG)vaaMBPy~^-6>eJl=(& z0Jj}o&HVPixstlOo2j(bED$5g;ZZrnmWpGb>~|D5JE4=FS!2(!c>;x$hXS>XL2)hD z2#V67Lg}+vn?ZaPF{%bC%dcBK2nnc3#Gb=(-y%Bb;s4iv;yY#xe;fSAIVoP$8h|}G zqa;8BMw+YQQ&+F(HKOtjv-rk7$s0lmP$qr~dwy1B4G=wqq*8C^M@K9mDNX+B|A z2S8P+3O|a8kj@~yu6k;q8P6o^bQyLCc`%{I@6l_K7mkgj+wKD*qUkag{0u>>suKt* zFh3htmAH_@suPb$e*j9Ml&hec)DBeA4bo}?47h7x8V>k{^T6mbG*vl!pBW=!Nd^jb z4${0YtPV#&3+s-#03;v;u)6pSe+D0iK(|EQDm&G0$M6F4o^i60-|X=RWNr>)nokeL zOy>m)sB7p1BOxg_Ac4NNM{BAsa8tI;fm)V&jhR3Q*|%p2e^3CKBD!K+8(1H0UJmUm z{w*xZ?O%-<1i>!m4To}zWocOVm0F&u2C6ESSY_pFx+H|Ik&S1q@zFH)t6mqjmt&#d zlG^cAdAC7EYZsD$#MX$hypK%)1*j9ki;vx8#hc>L0XuySxe!IhVrRu(To*mUtJ`r< zDHVCcp~%R!f3(PVft<)n5C@ zwrNFM{h2phUR!r3#YcYnN{+-;{?vH8u@`kvZ=H#n=?_|2-w^Sly?G~>6R?)xTQt93 z03U5vUi%vTf6-AKJSCm)Dp7LO4{u=AgtvS2|Qz2j?+?3*eN@O)ay zPy%KAe{)Zr)g5iNh~|CkUe7aC8pKmoo024F>x z-rcR9CW2)_zF9(hGK~Hz`QyMO8d(^Rra~XUe~@UKT_2Q$#lL!$V`)~gij^yMdpw$d z7?KLb4C_+P+bp;!?RzO;yUCF?oo2y$g8{ke2?jl7cb`P>D2Y8F0n53Z|>R}0$OyTI^IN@Z|c}xZ(Bmr z#idlskmn*kP+5G@M?FHc1+&JS+~^hr3a@iB|GTC)*+kbJ$+2^KyXlN> zkgSThU<1AKr*CaTy}#&F_p5mi@acXfe@fqZ?rHy7SL6S}rWsFj4c+Q`Q!m}IMBC@D zJz+zrHavC9c6LRQYUDW>gD+Gyd5B!J$U8V2aYwE~yOU=8 zMN3)!pi{EC;(=NM@9rCq>z{w$3b$Wu0jTlHKQoSTO?*agkKkZr@s7h}03Ni4e@&RA)~vJof)G+cd^;@!tfkHxgtLO!1@ZmdclXP@&78F z1fufq&~$(MK%X|u1+t$}tRvo26C{9_Ot=7BPITT&ROLr26)N?fzJk&?(!N|zgKK3W zdvOPlu)$3Ptu%5AZWzycftJ0!e{Hkl^$jxX9HMj`nm+Hp1BZ5S9^GDb(Ii$KENZGRz6r}$=(1VZ~~x+NK^0asJeVfqb!lHJVFgdYCYOvmjTXR z3I$Jn5VAk&8Q20n{GEQy`3evaqf3m$G2e<-s z)n7t@R3&1sCXVJ~(KSiPrxo~2MGS{_LhPsDkIL3Ka=qaqO#lNTO@}}4JhR-<&**QU z*wAP}i~)DQh<&?kryQKds_h4+?Cc%3my1kTAXI%gh+vRTh=p&lgTCng$aM;=^Z=pG zJfrSwqR9y_fb?RZNlg$1e}fNe^l?>P!!dwU190R!+k^Q6xeaF72Z1etI=CXUj{`a3 zedvx9wqLg6&)b4HxmlN5HsKWat@^;+<%Vfg((YMy+^B8Y%;W{f*t&RY_URR_Vraad zi4ZVH%g6DJzKRZ#kVGKush?~Ef&x$Md+n<=_61Ht@s211Ea<8;f3v)^f8nA)O2;I2 zs)XfHw}3Xowr5P^bX{)w zm{gt`T0&==6`NUZ&4xbNR1$gBZT?+S3OJcB8}C7*h@3k6>_>c)!oS=Z*lb6|m; z`+9J~ecm|3_RbyghhtNo)x5D&tOeVv>ghVXhR>R+$~V+|w=y?gZv5uJu6h6UPY7$X zn9&QIfA;J_f7V^O#nrpo;vNM@pz97^5B^J~yJA`(9~Z$`RcL<(D}^_A=mnFlYBPP; zCt~=wF;hG-7Gp&w))4@ZSO1S({O++0|5y7Fdc523m7ec@%l`S3K-?9JS?!y?**MU9 zdXGwXr$l{Y_EpAVi;p6)NB<`<6 zn~qxQ3MU^6>{3LQPdE9EZ2Z6@( zdXkxfsm11#H37zo0WYR}%%M>d{VrwUj!=Td~&x zcov^gZS?4|=oQRAm)V*?x3?MDnGW{Icxul;T8XD|a+d01XggXT}C07x=n= z$sSue;9d)tIvk2UtjwtCsXdjn`Z8c{HfhQ_&DJ7Jxy33{e!uSC8yV9 z9@_V-{wb~cYagvd8kJ~M<0!eAx>Y@b-i?h*&AI95HCg2sb}^?TnKtS`y2NU z2|%``dmiKjS<@VtU=&Y;j@&}<3Q@3_v8<%tOUk8xmU_seOuw`m@sL-tqCtnff7e6f ze$Tc$1?g}WK9thA*SW^8Y&)Gh&xHewKfBX`B9{DC! zadL=t#UA{+v8ohgVOsNj?#!J_KR>@lu6bBVS%d`{T0+rK88}E|au@EVu$nfrduH&V zYdp+L%iq7CNihJIU_k^UKu9OqEJwabP68T~@s4N8Sk>UD)iWTrzl=k=sp>`6gflWt z%dpgyTF>?({%LP7{{?@4e@v7~%5_Zo0#M?`{YLo#f&gDGQxlT|-YpA1NU3)5{qK9BC{pz>Vc*DoYtl$O%cfxpk{)P zfAZ785c-6=dCl3whtCG}u;>T|68Gjn4XpDy`C1|e-gq7xpeA0-vhU}EQ?UMv<)2^N z@v~KtpgJq?Jd!{H^O)wi@9WAne?BlsD0fICuSfEQgrNDsf5u|=`TYcXl$^lmD``9=Ju_;80R>IjM6*i+exvD>Y0{Do-d1<6QI>XCEdIA-` zvZDY7)7-j#9+y2b>aY9ba{2&)iOt+@^9XJuTh25ybF1p9hlVvUmAH){si6r@;ovEu zzT8Z@jCO$m7SZE&%}qE(`pTwTYtIP`@%BD{FN8TKe_A1w=Z4o4r=fs9@FTITL)pI7 z$Lhs<;e^U1@fE)R#4d?dp4u0hOQISrS#oCEL`IkM8+JH!0ea_)1X6qZ715#(*>(tu zazPK!5mH}svvK58en9+(T-&AW@n--x&2jpoAMDWrJ)|;xn3k4Xn84z0 zdR=|r=G?_vCW3E&&lWzCt4l$DaHE#N1IX{926Mr+1HS4JInaBc-RL3{!a?&gNE(%% zgbaJ_V?&E7bqRX5$GN+0EOJbC1{pH`6(DSLSuTj?9 zDcVSBbRRvdcPa7M+?TDE+m@Xa6Go6pZp3{D@gJy4!}#P1G56}+kxCGWUIS75CVCLF zaWgVQd95I^3lXcjXMsEMqK=AdIG9Mhy~+n|#cR|Iy-#-r%T{yHbr(|W5Wm*K`%R-g ze*{pV(85d5KA*-VRAh<6*6UGReD6v5aRFR5yaQCa3Yj#a?=DmPjVrQCa?~u4R&tXr z_yA9Su9mU6Zu5U&Uk(5F(3En4>By-_FBhYR^r{!~4A;Y|B{FV?vZg?|+<)6H_<4mk zzv5dspAuR$J#+iv`_N`|PkaVM75KJ)fBF=ZM|+A8Scd97*780Jecb`B^jnKW&v4&l ziuz8R8`>!yQGFMvC-ZiOb$fI&(2G}atbn|bW&Iy|k~(0wFtyb6(G1vi&Z&Gyhks0s z?0(2r!w2(k5uf8F(@OURdGsAGJy$zlrfv_y;ojk{8YEc`!v zZu_{Dd%gQgq~l6r1**Y#AFcB(EmrE|?>1lpXorHMU9zkk@BK%|TijV4B)2bgwPr<} zGD&WM23s_XU4}2$mcyG4yYG7ef4|s*y^Gu9yif#~Idx5+a{_25kk0CW3;lp^)r zlWyJangAJvN7+=T`YDI&_tY|$8|^~T_sM+S?PU4vb&6Qgs|lwOU|LI`e+8QtDrGOn zT(%Vk(e{Wm`(<_q;Vk#ARaoGw+C{XLZJ{cV8!J#%%dhYztO4_%79YD-f|zJlyi(~d zSTx(Q{$w^wA}_O$K7>~RmsDY=*@nceKr?mc&%EM;6ZmK?kt*Fj33sB+0)S6!X!=Bv zt;yvn&$R0q*JM!pLUJnCf3>d%SF#O?Dwm3>hNXP7S#U3776SP%sfoJmaU`#l#8D@j z+}QXE;M_DOcdHL{P(L%SeW-QJ<~#8ELvy#j)6URtBzKri2cVQn6qX|vw62saA0ghL8Fe-Ahyb`%3C*x!4x zW57_bhcd48?!p?@Rtj|Ruq&s8C;vH|liyGp0KGVZeimx4Or*nDlfCh!gs`|{Jh)i1 zD&&@hg{S_(_uPAdgjfAFN9X|W08P9i7UYsQC%slBRs8ZF`^Mhxk3(5E_PUFIg3m5L zF?-W1D&Q0DTIdNBf1c?e@k)?i?I+k02VDa!%yW&Pkb6sI!d5eMG1|6 zYC?AE#*1Li!dd{z=Lt#pk4QAdNY!}zozxC@{`@O0tTSLBf8DET?7*;l;lBFf6hJUl z6FrvoDl@RsOe@x57k(6gaW}093&9mPr{fCRflb-gL2hCm50dz*HP9(tuiP`)3_yXu z)co!|(i*)M!gK=H!3&A7{4r!fcSaI#-pgXuws;N~SlJeikJ}F%-x*qzDxb=WtRRl| z-REl_jjRpMf0qp^p8UUw#oY?A;0t#y+#%yFyA!a5mND!ZujM{Uh8llfCV4U{TRKL! zbzlWze}Ch`D}9aB0~PD;%VQ?&U7_xJ{;#q_&ogP(K`B{lXp12cVjImS-IUAiMXsm3 z-BoRbhOljA{9V~5_Pay!7w`bSV!&Rs!f(qzijmCDf4i2iO7%F(FDXNI8?*qmZN1|u zyn1zO7x$~|bRA+}1MxeSTvdwbBG=Mj<+pljO!L%J;B_h8Ns6DCAPlZvFfkw?0=>P+ z-GA~NnC$-~9`iSwXC8&fEL-?AvK0v^DkFKC%UKS)kDs&LO8qjH6qYZOVcr?Cw%F_C zPTOLTe_z-fl}LqHZqGQr)Lg38fVQ+1ibzYRENP(RPG<)WJ3+wAhYJr;0Y*QBwB(X}(tF{sILy zjcXqzi(D`>Y7PqwelEw{gG!(nKt|CYI_fRS0ljb$K5;|hy+ECU6u!u`A8`%$OMeZ) ze47OnJE zwD?7(s0Ca7+XWhTTirS(3)pVtu;VnO=PQ1xw5A|&P;VCtE)QmUS0V5Bp!0=r#?-q~ zlp5s359~$SYEH6J@e|PRaJaElol~&me?RdDF%i{fJ|GvxPu3e#v@;3*e1vqJ<~2~s z>wMP;nZk%6&z4~#6q{&-t7aCePD`G8Y80f-%rF%=q)8%!V1cRi4RQ%Gmg1s}BWLkH zGrT{Rgx`kqLp>nVd3I45{EW(oXd<25amh#kb~VHj4ol$0O&KSm(?wiqRR|#Ne`ge3 z@c3ld7;QE(Wo?mzA^pt2OElNf&O6$+rA*mqTHjIc{HQp0>?*{|Kq9Y21cqPe1QSw0 z2G>PQBTVR?RN9$B#)Dd(Ot3y(RZz%T?k7-T|H<3Q}gKuIc|7CFrw|Dlc|!4CI=+gAWi&<$y9%-=yblpZ**sKlM7FhCZt}d zsUrF|l%&6kkga>6s!hh`%g~79z= z^mP`kNxo4(uG?TP%8;&AayWGD7B8N^g-XoKq?N^A?oid9<7u&&?j7IJa5cQp2FQmC0>vZ{^1NiP=y zc3E1@rE3NfIxKw^VpkAvxqA68_z7n3qmUt_JfD~4RC6=rL&@Pof3=B}DhdSs0EE7x zDu3{c_GrZ(pH^8_H^(6bpkHok0Xh8)3DvMR z`D>h?y+Hc?9dt%*f4MxRq$v0PVjy7kL3`9=@$m~sDp_1m%>Fu)S!io6Sm^S8!!P#a zB9_XxySn_;UI*ORe;uV;;;nh8xj3D&oT%SF%>m7E$b{QeS>Vt703cO5CTln-S!(0) z<5&3Xz$16g7g&CeS2C6;y7?Dx-^ z7zlXqC(0)H5UXt9?oQE6f$<`r6W5d4z{-e|ViJnwYv9a3&*ZSPa5Fp?7FlbD>afCY zK@NzP$Y6{Xf3GQ>@nNhoxfhrFB18%>c2655gslF5ZQ{^qH(&SNCbJHbD@LQ=wiWRg zJpb8IK(l*>dQa)@|`YEnIoBWEgDoRra&fi-n@2~-)UTBLw<2UYhiMG|Y7>(s2 z(9KURI4t#aR`qDF-;nA=*k zSJ}m%HH5fH=KQ(j1ScG57I8<`)aJMoWFOe%k{=1*P6k}IqBqalTSUqG<6$rRVn?Ko zT(!DLU$k4jzKLhi`(M4;eeTkO{_=asQ8})v3AL-~03Yv=|Mk}Vdq$#R==8S-Oi{(~ zafmO_e|kifr;-%m_0CCrv&3gRJ5WHUx4~OhirzUGMrZqt`S) zP=$=&+5k-j>bM9RA5X^eIld%CH5QYnXuCkjRIq#ApsTen2QnqtKqJoI)UQ+?3ErAz zL?2bbRjrF`l6naY3tq}$Ms2;d1t+n!>>!JXe<^io|6ix%%qS5|y?Vt!3ITf?45l)1 zG=BWf%tJMK-Dfa)s=t)Xh&Y*nxV_QN7z^uvH=f(+fIu3WY>Zv{1Q2RJ<+ev3vHi4) z)YrAtDt=XtyA7CJ)`v1g5S?^n=A~1}Nnj}9rjv+(e*220S})oTO6)4ze(_1=HkUB8 zf3C_ez1Ed8mvf4{| zZ?y~cpXsRv!$=WtvSV?l#A-Dw7I;UCf3{boBLAp1iuOhUO2*!(a*9WYr_|X0Bh(dK zmt76msC`=c@_=PDU0*J#<#zxqFlfk!ya*m{+q0G^H@RguT{u*ZHZG>PEV%F3DPO01 zj(}V*hx91+sxU41Y#6CN=Q90LuMT-#%G_XDfdX(U&-eY_R1sWXLpO2+q=5aUe?uw_ zS2aAOR0Rxq~CV&l{*_Mxs$M zB4$-|R?gqZrt-(AOlWR;Io~9wf7vPhX!$A}tsC9j=Oe(M;dRt90Xg3165LmHKmhUy z0B$}Xb>g9gwGZd8zL%6!#8R?Tyx%n~DR1)-jCZf?`uC1kIz3(H{7A{-^)XWj-TEWj zhDUw#QK~9-O)bz8exWFd8M#!D%n=!QyFK+!{E*L_0;Al>Yt$R>hwPxZe}BW43g_Xk zX&;*&Vwhdxc+;=GbEhB|8^*pv)bg<+{qpOFTpjHGtwJmHG>-e8T2S}ZFB$!5_>Ky{ zSUa){WrUO8Y$bXW^+$qwK)-z3$XmVRdR(=Iss^)&7);=+q0?B*0FhGc6K3^&!#C%ZlfE`c(xzDcpOhuPeSMdUt<4eawk5minYx&l^#&6>$`4d{4p3Bh5P)BNhX2L*2daO4c*~xSPbL7Oq4V4g^-%fCgXdi=TaS;gx_GALh zbm*stTHRn;__VS;FXxwvt1+@1D06k35Essw+7~#g)~o@me?Tak`~7Zv3}!ChGT$Jw zEjQ^&P+|Za6I|3?*!-U)P6`R$6n}wol{1|RHOM-|5%6ufTZzJe>Mm~^>>0ED=`(bsnyc|DIc27ualYdJ zykrjtx*}48Bq;FGIwwXi=Fvwr}%AK)`vw9?xz1~Ynx zv#zXD_Xea7OXuAPGUDb*^$H96kM5cv8^qVR*-$UranABeZ-&Hz@P;FwRB+#|k`aUP6ZwC!=Bt&dz_w$?Tq-w+7`E z0%)bC#kN`rmxIT*eI`do4lg?UoG!K}AHb<_I_0L&B7exM&-h8=1YgvqzQ+SI{QwuL zQ=hs=j_F_|Vir*D^z4kD7{ym_r3YKoMIvD`tm5gK6nVXkxXp+2KIHK@h#Ygvk-x+_ z_diWYf%z&Efdt!oU+M=SfS-~J@Y*YwiFa z_LC2q1AmzTebUwd9`dVe!JPl{M||&khlRew00(&YOhPNr(tmlGPY+xL4j6MsuBczZ z12y(3zrlO~uMuHn)OYKri^iI7LdpW~M|&d!K%cq$sxS@cslgP*hRT6dH<^v$Xn;(~ zF&2Jo`j~@HCx$bd!|SZX01J83paKUY>kQ_|1b@GxJ=#ROj5Ts)3DA-m{1QF^84idk z@v9aOLQp0O$(+d|1qTtsS>_GET-i-wFM!p7(NR5}Fk|R3Dep6{T=((l0fQdA=R|_j zPwl?Zx<^ZmL$+R2J$xJ&`g&)t==bfPz;5-56x_Si|1CEDNsF|IUZ7BCvr$~vR2YH* zmVXe07`>NY(0Bv@36~(G%+*;y^b}8tix@8|1?`L zzHHD8Ui>y-0YKT3A2jD75xa$ItADZJwllA%nC#CHv_$!YCe@B!eV3a@Qb6#hh<_2t z!}nGcp?0BZQS3_lK&Q7{?+Ubfe{oOD@+rfya_w@F>f!fqesJq`-KreL4P@AG}S{@@59OvEPA~&Zzn|3fEjZKK#XctTu)zh z_600J~5>ww;qbpn(kdDE~4p`@vrx<4X9$Cvd25x2lE|2b_4hhYFW*+Bw<-OB0- zwS$Xc?Tn`O_$$OpD6jXy<-F&qUgr9L9IQu+CYb_N zQZ#AfSxqMKi#I>HUu*hAb}VpeL(x>A9nH--DF+N9@HQZUYy=3BZJnftc3|eL^X(uD z#KaS_^`tVH2_6L!?w;Bsgc3}w8KfM?9T&5!*JzsV$%rx^ud*TSS*~yj&9a>OVM|0K z*idc-Xwi{DkkEu%XY+tR%zsEAM_;JJjyC0V3ied8J`j18ZLo#Yvji8Zcsrm&MfpoR zrvu1PXo04pNIpKpwuXZTy1qW&RRqp-B3vAu6HC|?exB{cHALv*<>fm8THxO77Q*-H zm))=n;8{tIB?1yZsAD^BA55_*`z^rYYCa55gM;~?PVa>j$C|n(Ie$^=z(A#R6?ETO z{tBC8SLdSOxu1@@Ti&yvQlvrZRHN(?Wq`qg1SV%>H?Vppn7NQtU~pyy5=+>>MeXa+ z4X1=TC@n32K!O9WK$`#s{#CC;xmuZx-*psGh7(|_{$6+#iucRvEEe?_`2lv%#;DN8 zkbR$rbLI`oB;&o8+JENxKX!veU6{pI>B(0N6fi*jEfPP`4fS~e`cWV8fzo;~&mo;8 z7;*qTa5#HG%;5P?=MRR6Pa5WsdZ9Zo4=_^NF5Ul5sPoeEDWreu;2qn+IEHsp)v9Uc zt@NyC(NVNw_i_m0>$+b<%c_*uPFoH-LKkod09O8-bFb=PRDWG^4z4YQK_XWIN|U>A zAZKQ{6;GUObZ2y>#rDpC01hl;ia32DK)9+eFus%G^DP*};cy3OfFWsAW)v>y zZK3%3kRzX2&-cI>HvtbdK<)rbZQPGM2T%LnUIHyAv7z}yUOO#2)h@0VC~wS^zAiC} z6n=5)>l0X7DgOvo{y<|H?KwllqCO;fcir696&qJ{`+uO@!2+I@LG*CGC5XB3?z)u^ zK4Xrp`%}y6-t-fVI2Cj9=d#rRwd!LKSuX#(3Jd~#0Lt&Bs7l|=JaS{-O3w8FCiW(J zN%E9m4e_M@vQGwbc!=eYKpf+c;|y;Z0Rr@*ZyL4!D?W~<&n>sL%ljCu=h*su%8Fdl zLo<2`M9Lm!hDcXECuR*%3?+u}J2bjYHP7!|3ydZN^TSp%WdoQ@cYfrYbOJ| zWQ&3;FbQ_kCKP1_w=2E2Spb!oL;}Wue1E`!R^lG~l9shrHMj)Bpyg~nZ_NDPb^;no z)B>h@p!YUdf+Qf#RS*eRVdsV9`wsho_&-nohWD!p7e;d!X7c);u zuWq`_B$$9sX$5-Jxts(g^q>+fkcCD6xip5Et4e9~aun%UaOtiU4MGdkq?`P-PiRmlW#h)qP5)u?WwmaD3VN$QFL!lTnpr`WS#Jgl zdJVez3wibJwO0*z`|@D)MICS|8xOHBRNh*kXL}``m4%%YnB71EYmQU1+_l&iW1%!T z&d(;!PV=xSe#alipDZ3>izIX{cz;{fOXw#(mh!9Saz9xq_-;%Z5UHp3mAUqFsh7+f zunBpi2Sb{ezLeT$*&3d2<;#7^`pYhXbn`o&XPW~{v4isqS09(<3)Za{rYv4?An!9C z)Kh$8gTEJhxTC<%owVv|K8*|E$f5`2eDd0?NCBl3bwkH>5~^oJKS2P&zsdxVVU?3G zrOz{=?Xp0U4)TU9FtqI!7Sihl5g?p_7G(*6rmLR;K+wZmg4%wCSVgPpZ~!jv#f)Dr|^pit1tbLAL9iDN9y34P4DO9bpw2=dJ1~I9geSOXYPgD zbf+NnE}jRh6$?&hqJMAz{q$jJq|Py2S6i_SaaX42#McO0Pw} zIERvwWGy}}yviM%K#>U2-aav^DmNe2)InMymkB-)5!``~C4qte0)I*W6I)aO;Qc~? zSA)kqf&pB(-qmHL3OV3aoe}w;Mrt5aN8or*OV>L{IG0X4M*_ zH}-Y(p>LG+0D_Bo_O;upx~`D`JFPH21?N@GA77GHfS6#a_FAZTJl}fVC=@O_Tb9z8 zPLzJEeSy%ziP7oDtVT+v$EzZw7$YIgdh*z(N%pC-&VQ0mysePni0de*g6&+$={_T; zk@7@}0?+=%O2n#d-RX4jkkN_ne{}ha>7?fI_6$# zv3aXObU=agbrc=wOB_nRsHj}bzMVT2zhC-4bNUR0*7M$-#WhCjQ^-&c-nd+#t?Fsz zRo(Wm?0;^sKmSv%P*W>l! z*o6n{nWawzl`Od0^M*v&RXXQ+W}*SDRdb4dcz@=D1Q%zX2t7+wu2#jGEwBiC>#+z0 zSa9K*Vem&{9r|?+#5O*f4l~7f;KdpW=tT(!e_031yg2_7eC^l!*MKRo=*o7LgL_1GAd` zLw}ew21EOglKqt3MV-vR195QF(z>P>I3iMd611`S%3d#7Rv$edTenehp`8I~#QhWs z;kbc8p#!2P9GVd&HA1J9)<_SM{Sx+6b%nu0cWO&r@dUG1L(ZmVTT#aT&>5jlvDlDlHC1a_eiMWT3=eQJg$SaOu)aunTayD(~W41c8i z+CO_NGlH(>gE;^tIEk&;b~Y!&RN_?rTu^9dqKA0%;9$fJx@$p4jw=610p-E{!|ALj zhD~L^=;_r@Ku)@djJC_Galdi3O7qlXZVjxJ2#%9n^fL*6^4^R=wS*DnSZ`vcADkVbMf$cHx{u0r%2PJ1)GNOET~X7=r-q`^s$s_f4J`vE ztmrgtE0tLDdg)}Jep`*5Np4O&`)X~cUhUo>77CpSnhTku@Rc-*1rG*pQ5|}|;2>hX zWgV33Ha+0Yt~*r&J*db)0P)UWVv?~6x7H%}g?(Gz1Va0&34e-TrxxFLTQa5Lw_nvD zw12Xm8ZEX*-p+2~IK5QEQ%O{xRI=q$wI#0+%J?9Atf)R&FG|xi>>!-zBKz8h8@IPj z{wU(F30Z&eg6;V*)P|yI{MX4o=0oR%S0kKPzEVr>MDn#S!wo=b?)V$XM#7W)2J5II z*gue|dTY)v{eMQeoNP6imH1(e&rQ*J06Qt`nQmuEkL9O&m&*cadVyXFtv@}+EKiedkCHIgHESd)YT3ZXCgh1+uNXt(LkFOE>vlcBlO>Dc9 z5+Hg@2d{d$YXzesGw$24&XGv+l6DgvNqdM_ZMv}u23su=5>Z|fUjOX_ zck+M-+IP^ZQ6EtNFLC+CYSLo_N|i?M_bBqaQ36_;0>B}f7b|@{Ulrfb+HRh3LW@B? zsSttAf<6Qja$@c=YkaJ*6+z`^OFQf!5Py=O5(YeBe;GOK(l_gwtw7N%KWq0o1(aFoPqj6j5Ks8j<{lEnFydfNtgQJZ4eJ0H3<_Hy=l^hYC zfe2!9JcBv3V$gDYa#xxZ{f+Uu4Mv*_dQf!e4hQ$Drfk#PDfW3~{>o!5UZ4X+%zx0R z>Zee|3Nxz7>Vv7cQ)gviwJ5MAlQSfU>N<2ZQ)O`jDU7x_II{+Mo5 zz4Y2x+@vpxjcC=N2xDZf-vik*WnfUUr` z@{lxWfs>Y&K^CFNx$kdWsU0N|*a1EzsE?pwAf-l60zV_^(o4)JV1Xx{kbiL^4QjmCG$^l$ z=UPsBDS*a^OGHliOXt&i99V;?0;6*f3iPfgs6a3lI&(LWl8G6ElW;seKiK|^QA;A= zi1PUpqO=T?(dWC@SFb?sSMfDe_PzyO(I$G#b2Kmq7bXq+DUquA%rY28-) z;1d^& zqMc;N>ogDu&7aqh1P)zG{4)ZP?6om8#NLeJux03Pb?WPjdVe=9*$==HX@S}XLF7(_ zJisLEai@d`9{PO}wH`V0SwUthgr}X?BPRRUpVvp|JxdrYS*%3;1^@17p|Ihb*$r&{ ziQ)s-#on-W+|0|F{8b_ut!fP#*(CDpFBd}5C=>dAH1c^|_d_jFZ?vaCP~oOmlYV}3 zp)$7>y0~9)`+r}m!+Z`lER6J7w<1MP_$M(iva8^uCWqF06mr}G(sV`8K+71jpk@MM zrB=*o3m<4YDlE9cLox=CcKRAH`D;ZGEclEO+EnjH5osGb%6e9tDfGhv3V9vzG5j3< zd@WC}E}>UAzFaB9Z}~;8VtV2DsIV!<7Og(FWT4q+seeJn_x{Kh&n6EjMWWyYS>$R> z(vfA)8_U`Ao*j?5pT-IqIK1Eww(}4;RY$G^vt1xb00QnmZzNHdV@IVzIK|eGX0=<1 zlr=vO{Gv=QHh_=QoG1P2lfkBXogkx4zWtDiCzJ2~?=oyv9#u4^|E{O&v3J8918%$N z{cU}jdw(L~JZp4UM72=w0xp}DNo&1&fmiy%L$_|mo*}CM3cs@^Jz}M-F1nSQ-#geg z?9YCL0Op=#cl5DbZt8I~_}}Tx&9;EljJ6wLAe8&;Y*w2ppsWFa`hhN!9{4vV)~>n5M-jVgNa`B(hysU!ru`C#uC5&wktx zQGYAI@|Q;?s;zwj0_!D*uC|}XpwyuB0Zsb8BF1gMP9P*0*CI()>&;!y3K9$glQN&YBN$7wvc7IMO*j&i8hgi62t4%Lc@ z&_l!9o{bY_JhzlKRM@EWvQYg>-(XbvH@xzZtC)2kKEx}xilA^Emz)Bl9{^@%xVAu- zfCmbTY$+BW{G1<~>NnYkC2^8*=d$wPdgW~9cJTh{>!A|r*= zTX@7WC=`X3V*IRtxagR-y|;pwE%)|{V(&Zr|DqS*s2YOjufIp>3I!;z z+r(ddKt7AlQMBHG&JFXY{cnDYhfq`emi_v9l6(OSeD_T=_`CLec&p{XC&f=Rr4PS1uL1=N z8guu-?$+lhfko^%{PunDws}FA^fn+TOJ{KBO^kZ^7s;S#mH$-}4hwVX1Dl*WP{ zkoTi!B3HT6$q)Z~0W`nV?6&wW>2Vrf7yA7Aub%2CA1LeoEbB7(8GqpKIHiBgZByEu z3u+7NKI3)}{IT21epk}3;3{Z8*+IB+x)bU@&DU-m?h2_6A}Q^*D}tlGJL&$d-r3wl z33>Ag;NS=sfi>RF{{aKgn*oc9hZ5p^vLnH%C&++Tij2Eq`NQ7J?j(3W0AR#OSoQ7O zULnpzXn;EO)}l2e`+p|z)sgW?Q3huB6JI7Ih`q<+9M?ddy*d2w+;WLN!Dw35tq6#9 zcbv;VU)Llv*RUBtNHZywO@FTf%FPhZ=MR=zCi*!)8f=kZ6GiI%Af_qJd*pJh!~KSD zu@45N*uhDEdz+`5qs8?FUnx}o6&Tc-J=<;D@U!2Z&BjIR}gS2Fc2uGQWl*C#)xl#0}sLwX<86gZqQ)cuVAJ(x$X-=em_363o^e2 z6%%7E@9^MTC%Y5Cwrn*!L{_zyfcglGe8(>c?Y9Nr zfk?BSnOBpERrOw((e!-$5sA}md4ezWs^pw@%;_@1>$CC??goPpSg`k9#Sp)da`9U- zX30Rrl!N-o73tI{_iXAM(V=VtL+~CVqnim=J-*aW8mf;udDr0=_f>Sj4L^}k)=@v2 z=IlqNcYicBoIS!Cy$}Jv5peSzn`y18Xm@hN5^O9rZwR14J#lO2*aU=&pY~xtWkVLt zYykzywG~cv)k2{``FHC~--j;|piT8{99p+gX- zdZ=Tt!3Fj+Q%&4cxuKtm0*=^4-e#PImTfhZ_J5}5%4ZcCIH|`7+c3<;B*Gr-cn8Bz zp$^*~3UGTEjMZPLH>3{X;f_rT%g@FDvR6xF?+O6JIX!o^sCA=P5<*?M-dd{UgdF8d zFURPfnPWZ-`-JUsvEL~WC^@+Jz-_ye(N71sqLRy;4>8QCbdg0o$xmGgHfqM%6{|rLRPt z%KvhiH4Dmu=wv@dLVH03e2#0xGuWe**?(=@;FFVzG)9pNzEE zqDavTbdFvs^J|@3QlmoW8*~1HKhok=P8qJ!f(55McZ!7nia*TXf*Zg7zhH#Ut+u{i z5n6=vmh;_GgQT+UlRu9HDPQ)|Dgj5b3ZJV6QUlDsY60ll(_ynh(* z115870p%1q;ZQ(%QcT(>&R;4(6~bv=66>Bo`3fB4>ELHQm%m=L9%<|>zWV!9wO0%Sdc$3JlMXzx?rR$J) zevI=-Ys>&ISs)+5P90y~L8a=^N`LM*wYWtg49{@-Ezrg8t-X+ftJ*jsgs!x+A4Ss2 zO)o!5fI)D!E*uNNl#q@jPy4i`hzinxM^fkrOgvr2Yv^v+%uR6r>v5vgKz*h)pafMgm6>Z&>trj$phq4$3xl-&%xGTFj0L9_$%}`>VE|*vxaE3 zsakD-z|Vkq0>M|&1aVIY4gMuT{H|l zhX$kcRKlt}iOk);%dqu(vwG2dDK^T(vkoGtz4gbLZ=w<_8Dq6)>&woOT8k; ziG?>F035s82?IqDO3Bs=3`Uu%6nKZWBGmAIuk3k6PgA0qmVcD^fnV;tC{nmeG`SDh zh{#SY!Xt=KG&4P|Tz?MRL@22IwSe>g64lKn^gheH9ttV15cGo;E&zaUK-FnG-23=C zobX=`uQ?is%+G@&kU&`YG(y}0KX~}>G%yNAd%@OKWk0^w%@oVbXd4q(O+QIvGWWji z+V^)&3{niOL)b_(u4w6ReSJuen6hQ#x=U@@*S26m>IN7b5 z)r1gQAtlv8UMu+v*H?D+ZZkh!*M?Dit00p#=@NYBxf{2+>>Kg z_}1>&p?}ek707$#)KSH!c0{P$67q-y#2nT}eT( zz|PmEYOS<3?ur$9uma*#+M2Xk{rTeuT--6Pf zpt1D9UCe%|FM7%poksKKNq@QhnzP2#3OH_VNYc@(d|*O_>2Gi_ zv31+fgD8qz_t+9w5Qz8s)Gy8yXeSozip&HFFUp^>OvMyhwMDWt?*BHstDx!+w%c*l z0NQj55%Rjo>YX7e!X*e3DGp$*cMY3 zhJQ^(%&Paj5Bn?lx<@ppN_^!t0Ee3_5N;dXzMzDPqd0kRb7(Z~)(eqQkmu_5`gxYa zp~Sr8gA`|r?y@DJp{ID$?Gryw9qe~TC6 zf!=9=10%&kLtKAlr!#FO#JlZuA^zDXbbtI;R>7<~0FqUe@Li5D6#!wyvD&@7FzB0o z`S*GHp1iAMOT;v@=UI*sMb~GljP}pcph!Vm{?Bi`V+8-@E%V=;I&{kh50*y|s@Q7Z zz$CB$6IcGh1G{CtqNcb3u7oYh{KlS1#q9{YI^i}OckKmB=fJ4)FwJVhHM-PvGJjcI z-Yp--tVC1W1E)g?CJ)WS>KpO1T)h@J4tDLIsHAI!XLV8)EXGnCSAa+uq-YDEP}JM&CKeWPjqf57}Ms zY;GQe_$ol1Kz$u^EC9s(nNUyyXr|gA@0Isk;fX;!3cg0%E3?R zTZAG4yggYzA%R6EswT%nlTY_rsJb9Osl4#BcU;B}dC7H;8Woe|5SF?BR<}c@O*I^i z<}}vQ`T=YOCN#4f)k`C+Zhs#(Xw!7Wc9FV|(;s}YDXL1pFF2Q2qEoC=;Rb6BNY*C@T-;UtP}zwtgu_}b6H6Z5}`6S2{;aMq|}PE zBIY8<1v&Q4%|Q0FvV*l|D`DBZ;t-Ikl2k@R(gbJu%Gd3uDb5fm;(zRkwCYXCuw^lO z2&9WoT?uB7_i#FN8?DT1N-gd}qOLT_O>>2zEJm4IdFWn>j1n_SJnj;sOe-`3=sp?) z!M=NZNj{Mi>E*3w1mE?j-1Qrd|w(!RFYP z#YbLPDa(ZlXsNCnN%w0HmMG&+a5DQBcBQhi{C6Y|$yszBrA0Qq5(qgRT>_e{wRFOE8ssNf&*McYY3K2P zBve(w!Hh&;_wnCv`-s{NmGsY9CyrnTXIFWHR^FeRR{TeggiTDqt${b*FoyyKHdvTMG z@2~KO*%(GJBxy8C$*jo2Y5qb9$uaH(D|`WtcIMwly%ey^t}M<~>h6@bi8aB9Zq#p$ zP~8Bs?0>~+-CK|P(4*+O?B;h1RC{a`{%+i|{C`+q@0v4D3S98^jFExdA-FyMX8Zg) z&~h1B22fo@KqQA>VHs^X|2g4JvH@PD@(LHMMJ$*4LAr8pVbZife+JWfgl+zgZiZAMSIS%xI~3`Ytkv2w z{(p!O0Ju!lX`K#Xca`@13#@L|AJm2)fJ{~Xt%IfoZu{H7Bl1sa7cgIQ@DD)-%48{B!> z_ZhDVjTl4m9OEalsCb96RPwdUReuva8;fLB?@(I>MC4iXss?Qk!~YNgbU9-C_Lshd zzt#-(mf8LjGvBso94>>1IHZ6E7b22wmp-x3+uzOQ|F5o5G>lh8J`y)y)7v~wAl_Af zwaQe=O*7Nt0AHvDuj(g1PyYCHiW%-?@|88taY^|%1Pd+@1%#PO0o-G{VSf)q`+P5C zVT3;`#xFK=@e!f?Y_aMt(x2&Cx8`-1!`{6bo=&dgYjAubBbnOXmUrPvTqhZb1$5CL zwL}Zl`)~NwzunJLL65Ko>lf|^E8%xX+#^xH*cAeaO`(E4CpHS{eqL$s<7hj|{jDmT z2)KX#=t417pMRg748+?#yMLz?=*&ogzORUIvPr#I{*qG@DV#5LoXjyj!^m?no3#eD zR_V9cnQ14GCaSN2{?DF!qbYw@a|09Z(Rfn%5i_%hygFTxQ;VHDTMSfE-9f3A&^%!R z4BAKFEjZ->oX5B)%Ly8n&)M1od=im0^6+3*Y8Q_}d_n;=ran%iVSleGGNXF9-u`v) zB)c0pspoOplDvO>@ouM15uDhgwxivQKl>M1QQXctg(X-KGb2LKQh$*~+r6)RimuZ; z2GbnL>vJUtlR%8?sv1w+e)Y@+=>l_?OCgm|bembZ@hS9QeAn_F4_dwWYsXtt6PVm- z9V>4oF!S>4+2%kX(SJP6M`f$sr*oe?e2rVfS^303W%nq)XOEiOv10SqKq^uEUdG=& z=iFLp-yadjx`KsG#TJ*S5>TS z$vxXhe^#g95p|-E-2}R9<|hh;md^Tq@kaeYJx41uRB2bs13&;R<{;2aB{|3~=bTa? z5x-wl#Y?SD@ zkC<{(j`r>ry&|XS>E7a{Z%jVMvqP-uS+ilo*Hh^7EWACsrBM^wDaJ{!Xg^wZS`eSV zW4k12fqx)QyI(`2AV>}_V-joZNUyiaOtvzW#M7d^)Xk%l>SXPxj`w;tbVgNt`g4G! z>Wm@Q6*~a&5g+n~7o{x&HI!*j{mY^A`c1dxr4`xT3c*fVAI9H>O2hzV*8M?JsB;fg z+C^KpTsGeCGYj*bu@<g75hEo_kJ(EL4rNK*03 z$VG-d5@Q1E_*@L0%~8AeVPEPPAKgb8CTMg7ZN?=v1>mKVTC94P6W5t)FZzhC=f~Dj zC_;}+ETE67{HR|zBR=o5a6qzHXvsNk{Ttz?=Joc?ZUrBrVVpRt1JUSkE<`lPYi|pM z`+ryf6Kd_pfZuNMr=#T6GC+aLFWqoJ)?CNL=<$O+XHW}e?D|m^BFr{ai>hmV9AO8G z+>O0_ziCtT9_UJ8hR>O6l-eUwaF^|)~rmO zJbOkGRz21bIIfcpx_pw1tHZapnTEU2B$Bw2LLNtxL`bq=tRZ#Cg@YLtZ#W{#`G4B; z;~D}9bG3R9RbfR{bo7zP>D0{=;$`f27{U&o1INnD!T>(IM^IYomRw;PIMx^LjyHr|6)* zB~M81$fP6yj;--oEDD4`0e`B-(C@PEFl9k8IUNDd7#VpGD^vTlJsmrMz*MIK zC2*w`P7mrDTPmxstLX-SUG(`UMgVkL!Xr2ob}l64NC=s3P;-sA3%jSr|KwJ83hAVv z-!Vv^N+qt^D#QTq@!JR9v#Oavf`>TX!jCrR7jh*`Rk43ZiWvD#yH1wmQh%bUM*jK9 zwn2SbC)ujXoPhVecKInpG31oy>vHU1SKRNI~K`zQIl6f1ePcl)?usT}SvPffT@ewMSs zJOx5tE0d+Z17e1{f~*OKPk)Z80X`A!!EH_Ab{6|F%=t8_vZZEQS!~TN^q?xWOxrr~ z&FOoWQjcrOB)Gz- z1yTKuNezG?V^DocBY%NtRAc)!GAE660u@m6LtGy~si2{)@DQd7wNfQ?o=K1K1g*

F-`1EQ6Wlde2r$`r%^?pY5;9}EqmiTO_@-t9vmUDU#B zM?X31X<)W_1BEZo=S^Va6RNC*YrBH})5O1`DpbE_y;GjvPk*8pU!cPuM99L&2^G^} zwNtAOUSFGoe&`kd52T|0vx6+^ zq%eoc>nJ*!2RJ!Xs0h$_G3*+?YyOHLUFJPs{k@O5&PHZzyIcu5r4MWte3aWqDL`MH0zhne6L2XwhscQ1_y=%( zltQO5;XsKj`X~g0yGeAIoY)Jb1a4C!$q94H?ET;YYJcc{occMWvrKOAwVzkF)2j}c z@NKTqY39U5`D3P>w@r#NAZ2pmc`eRIfL*%M?Y7%ai0R|=3XPH42)b{I@PhJyAEiQh z0R|Boq*wh<9>KvL=Ff#f)iNS3hE#NLF1;i!eVmjnFtX!Mo}*79pAs19?^r8UWydX6=t~9$m@!h zxc1D2l-bxnS9g=L8ICRj8#47TMQXJ*$$M98zJJH;uH7>Mm>5Q$%12qh)pG-UIXnZmUQ^Jx;6=B9$r#U-{3e|2SYqb><>=+<&$|Y ziibX(U8r!_raJMYiIL@lKp zd?>ND)9y83fl%Kle{e-<)InC?Vlo@u^pM6|{ck`E;Q(s?4o~pu&OeCY=zs#tzut!H zuz^y%-Tek0tG)Mbf-XlP&B2jSZhzAckcr(WH2motKq_Y3x-y)Z+H=o@^Jl7$jQYqJ zT@O&F2(*l0xKu0XW#FU|2$`ZYzkdW_5&^_5S<7a;gP;kVc?y zJV|-a5A`rgP0%hDp$Dx5$d4}2I9YJaqBpI_OC zU_m{=72{3BY`PGiWIV>z@k{1My{oT@lt$OHk+ANx02h@etszrq@M*MIyptQ+S|Kiy zlO-lC4Bid=0;Sy2)uKT~ z%4BI+E%ZRi=Ku3_*dZ<6MnXk;4@0?yh}0Qa9s;G83$@hioW(|@|3*hQri>na1yQZn z$y#<%b=vE^3gpkN)&vb`Bj0~n_zPji*rn?J- zph$&RXHO9bmi+#$DkfW2aVh$(4_3XE zqL-=vkfzv8!d)n>l?8vfQo~=WC{&OQ$yg{w#JA;%AS3T##YkJ{#zq^8ghKUqv0LG) zsDdhAyIOenzl5?Ju7Q<>1Y~?+SDW!C4HdHug3+_o_QW-(7JW3YD$3hRcn7=aiS6uP zphCo*4^pY0nW_|Hi0p)q9{^J`g3GO9u0lt$G)2H$9aC}gL(PAz_73}@oBnvC8?xQ$ zv7tf|*{2GXi*CI^LhE+|{&~oSPO5ya4#g226v&=QZSy(61@K0Yd2-qO0&(7G&`Hc{ z5wQdhb1esCdy&L41{;OoZ4pXug5Nu5o;00WfO>@k7w=ILh;0N|x?dk4HU}E>urhy4 zFc^db6L0@GvkiZhF1-i@?La<(7Ua=?B}YgA)s30+YAX}y&;D{kuVERJYsPg(MEC?Y zGNeCQetYo4=X(LMxa=;v-Xkkt^aNZMKf3B9#WGLJQSRwT7A!!i7PDFH{~VbCT--np z_BkxW{_zXXq*Us6jF$b*V=z9T(~3GV7ueI16TVa-VZwjmvc1cNVq+i9re*l39&`M{ z6}ssQiFJM5M3*iu5Ae5o+g35pr2^logyr*;$=bTi=5f$FNf;NBs-&$4(Dr_@2xMjd zz#x2l5?LyzR+39jQDyf}^Wm5g)et^4L(yo0t3d<~pGnM?%QZN`d1ppWp+}6iPunol z0ZD*Xv^0MJzMBo>aoIy=Dmxr}p`ZYf&zu|&$7BcuK3XFu`%iX*yodnv1p%%?Mb{{j zOr5P?mCisqs)f`v6)~_)VQfGkbwIY_(!Pnk28v1hnn7`QQB(Z&U%x8wwQlt@7vT4G z0s-u54xyBM5?ISosF@yjbRZGn4+Nq=JM9`>R;Yi>VY@;}bwK%lEmJH3XP=F!to|6- zYZO~Oe8OU>&lwTfwUhh=J7q4Ts?gdmnio-~yX7>Q7#|7aL=MQQXY9E0EP78!k*8?| zycBD`0?VyBfBN&|(|C=-1a@k~Yuj&{9m*UrbPKMU$|B(|d)*wZ4G>O zTkd~4`BU{b-W~8SfR4W4rt6iGpL23xkFo3kyKooLnWCA4k?=sKaf48)KX|k^een}q zbqBposCTJmzSxR23qD~2m_6U6pirXzc83w#-uj!g2z{REdPzJxAz!%pK?Jwe5-v-` zx&1;ub(bC8-p`d?vH>Ptk*A~iXcE8q@uXKJui z3JzegIY1ZVjs(`u_C#Oisf7`A1nVpX(yZToEdT(U>7aZX2`}rRz|3mH;_r`Fs~vxo zWxQpeRmpRCa1dpm^(n68=$~$*8s5_=I4*<3sTwdA;j{#MmMqqa@bM_dT@%#c6>F%e z4>D+N+b#H;IMql0D8EBzKzThjDw9pa?t==K?CT-T=$7Pr^~=Ga?*#<+eWNknzy9d2 z=|s60PsSymZSK}F8|m_^71CF@_KJUqAXk+M(NTbKe{Zgf#M3Aqmlp!cOd7A*6P+zD zQ0nMZUu==&jB(D%IL!>(oN?~+UbGI#Fk+a33q%l8r4Xi58RMkyAeCj~J*m9Tc_tf1 zFIdSH69Kuf^`c?HFKITbgty<;Pq&k}A?b!Oy!fAHyAX*+Ob~wwQps)e zZ*4>c;3WCtbAnYiNW81T88*nmCo(%c<nFXa+T|e{>bf$m#1H59fwaJO35ZC29ZOZp#|998uHS`mV0$0RYQ1p-N zRrTp!7E2zWciY)wq(?J-7_-+nyqvSr&TJ|FpnT_?QxJx!A814;{yFd6E4?(vK8{@v-KAKNr5T5b7h1Ns-kWv_`Db0 zQ;`}wnK!_y9Gh$+lIedT$u8ycrNgDMH^oZ3%s^^WmxO zWH*2h=AavX!UHCoi-EO`)D@qdrD?fiwg?wl#!kuih#5^Gt4e?MW487uCtiyAWHA}{ zj&>8-{jiW7L3k_;H;5F-CKkbZCX44axT*0b}Rh1kbueBBL zSSyDb4@bNn&WNgainb&4RCZWG`cl6uAB(-ehGX_XY(BjBDI(%=x)Rj^0I`n^M5p#H za4X(1^IwF6e0)&EbMI1OFQZ!Es_Jl`y_~2beO<5w6c$erlFmRXYjRd`#5KX;1 z!&GN=P(bFC?lP-DzXcceJHA*tW`opBpY@Z`ld9%7b=4%GEssoehfg=cr%|n0aw3JI zeKP7EnYE%JDYfrR&tWC4RL+O7JYd=o7L4g+6z&>mZ#O!uJ z53kLIh-r(850IInV3dAzYkBOws&0yF`}mjuJjYu^_$_Ho{)CF#BrV3#sm5xRNR>{LrFF0ARdElxv|6R7?zVH%f zFbYA~I{|-QRV#EXub(N^(mbipWiWcbTMVk(8+s3&?r%E2qEYd_wY1E%}>2AuS-8inN-%@A(^so~;$X?Ag{^=OmJ-kPX5Uq=|JJp~GF+{pf#!YzF~AF#Xp? zt(ibK{FAcF^?cDsbTZ?p6$aTe(DRn!YRrvn zwzpb+K7mg1@+{WtHAqFQk}r-W@Y|((NDG(GLWHb3A^{~-Y9?n)qM8nlgG+B)NIRp)+*U0|=vw$|*p-ne1sq6rAV){lW>oF(f5)cQw`* zoR5A61lco5y{lX?qmsViyMgm4-ZmyfVN-vdcGP#z&E3ssSD11yQP*J%c6LXXh+GI! zi7GnQ*^)r&aZKn0wrygb{!R z`!-SNplT$iqjIzIS1OOLe}o|8AMp7?4rWbHVjZ~E$lg;Vz*m3Ql){>3rIUX<0~UX| zG~}U`R)d8RYAi_r)p;nyF2(X{s|g;@tUtVvWV{e+0D+A*H-pg;Jr9V^5&0@u>m0I- zfE~S9BV`bI-#ltSGUJ8*SUoEy4ETGm?v>+zKtGr&I=huD;>r;u?@>aSPeck;fls;- zbHi}ERGbtIS^+>0JyNsSJ`_ptwNQUUSIY80xPndo;kSI<+k{ewL9HN@0h@Ys8q4f9 zaMVxwzT!`T^YnzS8!+AFEY>RuDHH`KV1ZZelS~F)o#6(g)Se58`h2$p|C;P0ro zv!3i`yAsA`gk146L=C_e-Gs~q{BH0Z>W_v96vMkQ@VSKogYS8mUaNmLRV|fr-NbI3 z8J9TpHaia*-5aO6UH^%SRik?yt@Ze=Gqzo4li-K+o?lI zEhq8rLb`}sc|aTg@&$(b^zwfy{i8;nbmaH+Xs1sdxWsd=Mc|&AOSvmkwuyb?7QqYm zorD+KJehv1`yYU#kWR>IH=;?g#){h=1{jhIT_(mo8-!McXV#*LX+_eXtiwsESl%?I zRs6-=&r^-!Q~?0PxN%ahgaQSWE5~<5HLa9!6Rrf28qxxZJLg?K?UR2+yIt6|m;~Rp zJ{aW6 zw8D^s?=u?cJSvq;)ZLp2J48E*U-l&cuF$O;8xQwrt$zo}?^F$)niWh|l~KeVXX^)VJ=vVfYN_@w_=N(AY5uWWV8(mhaRP^^ z{OG(u!Hf*MvqPAQZiAos8N~;bn_qLFep;^e(o=0?@}B~uuu?_pbLf^I!rAj#V;TiiriXuPnyCJ&j^v+}|1D78 z?D$ry7y4wy->SR%ce+re^#k9KW5efxdq(yWXJq=Gx`WP_$_iAIS9_n4`Uy!J!_&N?}iM(f5h*2I0OD=^yDN z#cyX(hM-n^e+y6`Qe@utnYF0p4K9#C*q@VoWPsW_#XHm z9VgTdazKo3KH~zH=+7^IVB(PR-f8HWc^nm9yQ&Rc86mk_RgVYIcKEHYg2p^KXGjhP@T^hSDE+VF3f|RBJg2YnK6a zK}$WD6}NwS2;#t7LM!*t^@;cuUj5z@xE;Hv+##wT{b!tXsMvErnmz`D+5OddXste# zrSyc@M%JF;OEa0N1XuT}D!PzYrWuexrF*`tco?C`X#RmltK(4hFzpr}5AWwkO<|+G zmXs4%V4~{0b36n<;P1LZkKy+Vt#GBk$`kZQCDebbmmwG7*9YE+>weYxH=U@cq9k!g z!S(AkkGJ6poX$yo!E9^&rw zGWh3g)@u#do8I+qxGcs`{FftK@0zOI$Pj-)U4rRKR*HVr^`JW_VM2m=pGk*;i(Xr^ zRbYZTl5T#dG9LPi?m|XjWvo&YNemR~wdn?*s0#hC!DXtrD9s{eqweEC38^McrzXYUbS`~N8l`_x zEqhxSeH$nGhp$ZmYKC^#Y>&{k#d-&r0JJF^T@A2-@y;maj*GyGOuE}?ZZJikUMBUN zBRYHYxe6cVY{}xI-!rG6e!++uYtg^pqRahh1DuKWcTLkhTjYn zo5?RgKgzi;7ao3toCVHadh`I@&7x9J=NUV?i{i?6qFn~IHA1_UwL}Xc^z{pMpEE@C z<;aGwiMn;gnpi~f_rG5tJ3fKj)7&mw=#DT;;$RZRS? zh9e0=9*U#(|2NN<1R(jq0c40yQS!%5b_3m$QX-pHvfVFs3{9)u{9=6nvoaITgHsiH zI1sW?a=M@sS2+mvzXeaFRK9gV0|A!GW(bQxPxyIzGU)o92fo92Y=iIk1X+RTbPbW{ zP6GxC`^URrn*~e-*cE?Wr)dC`hL{A`7OSC7+)t}tP$R8+nZhZKTM+~6Yt%e{VE`)7 zCK}zn(l01iSg7m^E;z4iu9DhNI(qHfjtK1Non%5HH{M!o8!zP~oczOLTqe?H`8Lp( zXM>X^v$#!mUg9HJ6g$~;9Ov`p-H1f_>=^r+J4AJ%L6E^sCqff%2cHU{ECDSPz?en0}4P=HU> z*U))eoZOV2i`Y-TP}Y(jlLu&{lYXswYWhtJCu`Z|$ll-P+9sp>lKsgQa%q-1V{eyd zoB1gDsFFcd6`Oyf>@@6yoa%r9^dYXUh*OYorSMgi1Z5A)AW2E9_;^a23xJF6(vSY= zf(M9vf|UJeX|u{Lgx15I!aygtzSwa-6#%Fo4F5Ck$RTPjg)bi>2XPGyyD;wzV~dspFJd?|bY~ zXL0!XXMyaDuFfOyeh43J;UG3!=8#)$*Uus6P}&4uDY8O*OyfS9|eAWYq9Y zYS6N{rs01_U)$OqkfK1P`sCjiKb1)6 zj5NRw(Gie5oFzyvTQHY?Wd2oZ-LJNqb-dpAdscs}MhY2m7ONj;!`jy@m+;!5?H@LU z86Iwj)6j~t^7txft2!*fq3&|RY$D9iU!OPTl%Er81aNSqC;(&~Zbb)w5vo<(>)%?( z!sAD1yDUESY>|DK5&ISwug=eDbd$JOzM16?&e-@>_n zFl&F9!MK^MZwR3~z53sD5>2bqrB(EKU_j|PAxEz0k9!fi#8;ke65t`lU=&RXgYAl& zzfo`OY30Q2;Xuscl$i#*;5_s{4%`K($Eii|7;0+rv(N(jmB&y=uan%iCLbCpW?;`UCvQEPk;bCjkn8c4xv;Y-;)A{fccjb+V<{U@ZgpThzX3wyrWwS z?joq?|0o4dvZ%|sRp@`pTy(!m)d9qSrwqiJNY`5Y=~3WioPom>FSY-WMX#Oo$f|!4 z0=XYz$ybZc&}VEvb)410iAtB|BYy^t=?@I6Dm&0qCQB7~HJa8&S)&dLQh)0yy@6&m zO0Pc41ji_#aQuJkd}&=7rdFYh1b(fL^?`y!_T)@D{HR zF@USZyrIUW#tcC00J70ash8viH!**q5UTEn>)nO+*LVa92&+H7%(G#Hf$#0AB;VZ? zdH#M+s5C$ilhPd1`kq|%cQ|+vHu&4k;LO$xJVQ zho(db6^^k;*6XA|-Hzvu{hK0V<{_KdbmZVFcw+A?RXsnfs9NYpkQB8{DS;5eWqr|8 zd(xL67zhFrp+?Mf>9$W(8ECV%P+FuF3m8(qi`VL9+Q&%o4V(*wq&T7vd=J@CzDe-1 z`L!`Xr7AMgh@dP3sg4IqOFVx%yT&QK*LBfJgeJir!x$JR*gdPBh(+vLy}2X}4KFfL z=&=T`Z366Wn(w9jr$+ah7Nsq=qJF(zIGBe_b0 zVwc+GKZbHEm72d|qvGQdw5b09%hgE$ylL=CqrX5j*@(8jK@cz5!)1=MDK_IOkb0&js0CT^ZxKR?o z03LQ(8=g3`c|;Vm+7N#Nk^~SX?9YT3$3BqA8WKS~x885H6a?QDSNU|3V4H|Za~U6{ zPkgAR=2AN;Ma-3G$X&qJZ#IqRw{co#?>I!jIA-{z7v>K!Z_lZ-ImdA8)BXZ9d^%u9 zCPFo8hArxE{n&ej07AeVh7gpOlu*wAU2-K|Yyej3yp4t52Z?`~Mb`vz|3}?o$oM_B zoRS>P{^0|y$y#@m(5=Tbj!rs66xl|*Ov9~y%~FcId^_m9i-*v98`{S>!HBS=y( zouD}%<_UGZVGMtVWA%uAaqsaEUD4KRV2(>s%@r?QUUP!PD`mBva`E`X?UwOnk^Hah z`w??ayVOcM-pDFaY}!v1sK}8_)-;55_Oyp46UY1s7a-&FX(}|;JEZwZ_E$RwJ9d>g z?{V|>Wb)D7@%RG0`(2`N>#|5E&d3pOuRxeEV!;RGM0)}+YHSjOM@M=**Kh#zod6a# zkO&n6DN48W&BC-+m%O5xUOZQrZG~O6illg67gK-F@`-&;af1cj_D|wr`#3NM`J!-n z(GRxLfL*(2Ga}Cl_&qI^N!vxNf*Vh0BJ74>J*5V%cXQz=c|xxAINP0?4Z50-F^8%E zy0bMl^{Qv?g8t_M8i4Ehf4Cp0i-_#_**~JZ0Q}qnVGq>C8KLe z2{HN-jzqg-Qk%pr9`?qUu>mz-A_=kX!j11z0UNBAgnX0OfGvL&@?iOJw?#h17o#eG z@o{R8MqC2*Cx?Tf`2bA;p%e*j>xt$;_vn|r-z@fyS$G61A_i~)xSyU75={Pb!!>`L zQV<3is_tw7%m4sa?CffXAp1F`E*?D$40e&cH+j>QY%wt#x5ubLZ&gCALUemrSV`^f zUZ1!8>dxziFTe5aN5P&=KHZzn3T?7nPzZWaw0y_DDB&ssrSz1fc`yXNO+j3Msn%87 znqu5l44}wBNnj&u?BdVbfz%1ujoa#%@U#r?I}A!GJ7+5YA^T;qAmi+ zqU^uC zH|49R#$qyk4o=20+vEg(W&gmYfdjL(PoV|goX}43NU}lP(1)ZIQAZA6wVJOELxhTM zs`PIJb6=g0ZrKtA(-*EKpp-qq?CpQ(DTj+OhSn&V9Inn>NN72w5*yj%@(j*{*hz-p zAr2d+>K5EMaFR_Rm1r9GpE-X6#&+sLfxYS(y{Z6iz)bJMhyZ@(PkyRRsl%|xfW9y% zfZ8YeEtYsF)m#y}0aWfODq!!tsf`Oj8UmNgZ{wdlJLZn}8$SA$M?X~0`!M1nDt_7k zkm0%yt2({^VX5;%%hoGz(S-oZ%rq}vx&BjSYWROw)Pj2N)lxt6C^Ub#kBVRE7beWi zruFM09joP1>M5W2Qi)={icWIcb*Xun-S`Ba6e*hh@%G484KGvwiO3^od^Eh^1y3C3 zN|H(O!zDuwJuv@14*xP+P97%AQdQeMNtWu$YIn6tAUOC5h7Wr~7%E25iKHwvTPamQ zwT<6ht~Db#qG$ATI{qHGpPvHrOop04wvOF+LllD8 zHGJhX-#@&QMn!*wQLp_Sp+kJ%i>eD~QH)d~8G`k%YczfKypVCFj$RRA>)RBIG#!2% z)|G$NVg@~WEvtZEmG;R z@1s@}Y?In(i)qn}-(FRKC0IyUT`i|+VYh>UTb#@Pi&TF&%c^6W;+jjwtolkOA!<@k zp-Of#`$zX@hYJ4m&hii1Q)iXQuaZB&kX}z#_CNy8J8)59tU!^cXjJ0@1dzBv2NgW! zC>p5#zF2(zwf=_L%N1I6qxdrs<(eRT1o^ZCh6U@IDs_cfe8kK{CV9&it(QLp>oW>%1IRbRuFYp3ca!1ul8Kxc@KaILGu(PrfuY*Yjj!z# zYd>$j_JR2TT@{0|sdmCRJ`f;x?>nik)6|SgarrCI6?A3#r4u!uofx5kduMd|3Jb$O zm<67J>W`9aIW*6FkbUtds&41M+GpJ5GC}3fL^*%Jcflehcn>z4_d!GcoVE}6uNxnB z8n)V;p;hzC1?x*OMz?+;lXmk!h{m^YQc`?ge)+axb#6AL$q4u#uMs}ePZ-X(g)LP@J$5fuV83&~mH-o{d z;S+z<6l1ldz^5`>kxdEsHUi=kyo8!m{^5cQunUN&_!4fgkm-O>AY|wH-AWDF)`Nnw8(FbN}CNGeDGVQ=zb0&uKYjBcvBMQPHN zKEGvFr$E<)LYa_L1O^IAbC^JFVUreslmoT|2JaNDz;}O? zDGfSsIL*BIX5VApoHld#F?pO>Wa1=-kGnL<&s=7wJuHpxm2`Yf3*DJVVbK&1_y`bj z?XrX2nq?2M6!cAouD*NM@6M+nN4(8Ye>fJ&=)+J{a6o}WXIbosw(196Jg8qibG|kD z+9EO2;AIj3a^Jlv0Q{l75#F(YjuwA5NdclnTajC-??xO>!%1$Aeoap|5g7Ub0%ap# zZUWzWTK9sOX)k6mfh&c+mV{Ee5n(k0;)6*b%D#Fto?2+QkeVWy5`Ki?HA{2gzTeliH zve3~!se>r^ADw5b^zbH`)7Wpur?Z7izaWzECA(-l{ldYvkkByehlkdbsFTwtNC3{0 z^8>M{{5Q^CjYq01IXQEhDB*vOlLrB-W;}y-tM~w8z1+OLmy6UWb>Cm7mH#*>P2JTe z{-kvYJ1Ks=df;c9!}#L{p4Dpnnp2c&)PHK(uvm=FdUwMpwZnU#=Y4SsKV)4CRK9qw zALIW0gW^DD61bY+i>6Qy=H`WrQz8f$WvT!%&>C28dTId>k}5jzg&KdQ{#|lc?i;)t z7m1VSX&2I=X%lA7y^kOQ*x8*Xlp*XJ#W3E@56gAd!l}a)H*cr~p=NX-B?qzYHo&S& z=?njtLoK&ca-%@p3&jtBNNl!>6pnljclRnbiJlTU?6E_it2^oJwhNEtNrL_gw@#R* zCjpim>H}N^m-RzlrhtD{h4UhEsZe@|q|F-`V$cGkuN8sOz&&t4p48gG4k8M8p5NEb z%O@{8GuZ2Ft8bq5MQ2ce_9o5A=nH_0rl^*~K?`*XVJ~_O_p+83yTz!q z1FEzBr9qe>a3K(1N#CPUe1{kO8z>-Degx1AI{DqPJ1O#IBg=pIMyIH8C?WQu7MI&D z8pnp$yd=|RycaqKfHqQ(#$3HHsL=;iN6g)0uT_MGjiT=ii5%yszf4$asTOC!)s*ho zd(u9A7o+RzHIYuFydRNAi5d^EAbTKzQIVb}*L3WRhznrh4G}UGJQe^cnt_+i2BA>z z*W8hlud~O{m&$)S+9U1dPU5?S{4`M(nZj-P9pUp~X|dE~C>O(dl$_$HMgrAv((r%)!&;h0VEWqupbr_;{*IuR7U8T+I?!I{3rYC3OdInLiGP$MNQXK zXejq^{|RYDe$LE&vb=(!m8N=eU+_Wx%(+{;Z(22&09J8qvdB}p5hm6XiQc$hvzPvR zybxuRO*?<7?rkWhjC(yCE!ryjATF|;Y1p8YvX{PA*Ts!}0E>^oRiS1$MdH0`kJqcG z^JIs3R2&tqhu#@^PF@G&#q1Ru6vLvBHLob7z*D{gbV39U3$UeeICypf$3N=I9j=o{ z1*dx;EnePP1kw81`*{Rdelpl1-1nV6$Qv@teuIBv_ppUr2q1Jt7>-;3GLZ}Th1w=+ zAHn68#Z$H@?rBj_)&Q`xKYn9us=;8r19hhHEm?w}@KBG{s8j$|nb#E`JSsVo4*YgS z8-|bL)$tIjX{wK@^wjW+7V{78Cbu0k`r1mk>l6- zsPKOcdTGBxsa^b4=j$q+5F({BdksIJ7F+F}2vwnv|40cp*qiw~a{)feo6%t?+T-z` z-5XV#Mb@F>BC_AAQTQA+E|YlkC>a0}f8$%ZfAwcbK)jp5OkT`W+!1#KcO3n0g%RiJ zZ@P*vHCL#u`|xU$padqF^3vDbKG1^xE=GSw5pDGoo*egr14O-s?x}5P?=3|Y>KO15oYx{?S|W}1|?7@^0}c$6m|Rkf@n|!Q%~|J zJ6>9_^k`@fOqxo`pU+W1A>kckPtg#SorZiBk*l#OosTkHFZPz(DIilcHFo~1;mCh7 z;R+2>)gH?ZU6E^yp4r__1+2RrEtq`5X zDHj{8Ml(Mi>ew@mPWbu=^#nEv<>Khc`yTPv2`znaYM@^@)yeCsluF$4Kd900J0@}eD4 zc{&$GSv5vw2+1$3+x5r4GVV10YY27Hb-yYQ)Y!P{(M3*)C#u~GEs+$6Myh{($_C%P z(FKl(eO3sUDbGM_aTOT-`9UzH1~33t!ng2A(-B3l_+7O&|1mc5w7?l_zH5RL znd~PT&)^U)tyTwt!6d&ESJ*aCBixksc$mgwH5eyIinGdzXze(;k%7TpnxN1e>+ZK>$Ri zc5jt5slq0xc0I?`Na262zL&AK;Sx+IctRF=oh};#D#&`oB0^E>|N&FyQq|q3- z{!!qIRF@bCt;GZo--ImV&??sn8}_%yED}{mS%DRv_Obf`!_A;22W?mw>TS-AAi~I& z+PUksXb#W+(J(e%%a4C3DAj5{#1P7Y6^EnT(_bdP8}B!ZD(4Q2RHL#0x`hLt4ckrC z)f)NF4;xCP`p}|9J%Kl$L~l3*SSV<5+;PpQzI28~P==Q_s$_qyz>7Pm7Do{i_Q2fe zWBot;-~7;4)8S3tZ=WWB06V=g1+j{`yPOK0JlUvlV=bkjz*T?T5_G*UFja?e02=PG4IZ<1o362*{tcI{Q{F8QLVX0}S>AVqL)fNZPY9!q z?x+TFQQTxH5o3ScgF#PXfV{i43zR$3#!PSp*V%Oq@0&ZH6wxX^4YCutR44bx{(<4B zyM>H=?>9&|1si?HE>l~qo(P#+XYs`uWL6P61D6g|8k-2}Rq(J#&D19mOC6GU74jTk-m~tAuo8{iK#_bM#T)E`a4K9l z5ZtFA5^8^n<564gn~pS!*wO4x>4{lGbT|VMIElKAy+&kdTYjPA)pL+K2-?(Usk8s& z07=zmfin3a0?B9&RC>#qi`_8Toov0mTuia^%Xx8tS>EwQ|8>41fPMgh3B1mlfb}_> znXw^QF*d7aTbM}9z3X_Z^#o)VKU(9^41|6)t;>JiiyW=g1(LqKBhe!&J;qKf9RjHs z&g^w!4|+eF``Z8L<>QzEp!JeUBIh_hxC`%W{gX*0%>ti~l7#?{fVB5)vhps^N!}RW z-vV1gj%hw``qze82W)h9wL4e64-!k12%XZ2fanB==?}#I(E~a9$Gf@PT8(7xyJ4OK z-6Vg{l!th6H0pvQ9JY<~T2th%@MH%3J;_OpiKsr-I00Y?!hhk3xeHuF zmjaZp?-M`)Z?N?o>Z52(^&`4^lwZp75$%5nquxeEDbD3$&%8l|i@WK4wxvU37O+VA zz!S67v50!71_pvjQT25l^qEhNisN%9eJTAQMZ8gtAnb z{f9>)zh;u0VnEq{+y#M3ik#xM)Z<6fOLonJS0fN=22%pnZO#w%twH|Gk_VIr)K`B% z`eWF|3PPl-UKXvlNmc%Esyh#%Jbl%yjM^Yx_B6~XTG&NYds=SzBS0h7)lUx>c;rTQ zG^~}PQZjOERSICMS_BIzw*+&t-|`SlAJfs8O#~lRBCgjdvfvgy`3ioMqZp20GNVF) z7QhO2Yj&$5UI^cC0JUSn?SBS|dUbzvbO~9z39V?=2r<&kg?vDam-fY6eylCzqP^E* zW7QrRtjt`v*1Ehq$MSy&GI<8Tfw0FD2)5ZEhPr+9Vxp${b^ga})`0@#ASvx`>DYLk zSfeK-uQc7Ee~&+c3%VyBdAf{8RA@~wKtBOnjDC-Sl!`I->x~pHa|@J@eJX!kTtX{Y z*Pe0jraT;KOFZv-W!aAnlvnM5SV024q&*LS0h0GRZ+!+a?Fyf9e};1(7=I{%pbZAo zVt`}qnvWEB_Yf`BsV^oofPfoKq+ND?xw-9;or8~;r6x)zyx?m$gFmm zb8pRQEzy!Ufu4mlu38~z;L$`}uIT?!ACviy8?y~4tsp`a>7NA>VQ&DA=KTNyk2e(~ z%i+SFkuOFV6&JXO#d&{VbK4%R!ot2DD7wC#-iAvb;&4TvguYJPh5<$Q^8vpA2C#Yt z-Dn}CDiqyNHxt0un)pIoL}t7~guug985CgnZIR9xy_7Fw(@0s(y0&9WGAzUN_#N-LMCI>krR((&h7~WWRYDqdwa;# z1ZwyDsS?7f!u>kE0yFMNV5%_|ovlY_e(y5(#)Ki=ts^>ntj4nz#!77r&Z3zay?I(F zy-4RsKrR6h*A#y`&7$4)MhOVmEmULWRC>f&%K$_u(1A*UwU}g8T+hw`5>*l(y#BWo zXmCX-y4&67?SG*F-+~668eXY5visKvRf?jhz)}A_II^Y#8mwoR3#2eSVk2w->vuc& zi6}83GnH8vtu|sb#5lP6wgx$70cK7 z_L+|}#fvg|k^L8@z5qYx(PQX1(Lki$Kb2apQ{S5lIr4hhBmgEilD?Z%c*)6$djRSh zK_om%R#(k;*zdn}79f*;LF9tKAP53dA%3P1jOn>SE(s!HecQ7P*F}B1TKM&v+T^Jo zb>3S0{}+E&f@g>ywuaO&c4^^#S>g#Op_c&N0Jb$l-#4?ri|R+%%^W~LyNKVqzzD?LDG28PB`3HBL+_9l(itj?)qZqWgYX&{m3bF-gnf%ax!!IET zJpc$s_thRW=ybk5$FwprRkN2_xs$$|iVo^r;Z;D-F(Gjy==*yT zquYNN-8@%*{ewVAcQ=L_NgZ7q$x)IO{7Q5zk05Qr0v7Y{^ ztibY#=5}=6C;WrYDzWMN(Wk`3Mg(|Z=}J5QDk9L~w_^vAInoL?alZ8foI1Y1p& zN5Gn5xW4qkg@ZnUs}wqWHitelya=2zqf_q~m~{ z`GBdSMkQKzqzD=s$Bv4}L}CFy^}BzKjHQU3QbbycM_H#te+~|I->t=1y(d-;Apj%C z;Uv_;s)EjNJ6<#Xg0h>>Na=L&APiCnjYyWwHDHPD>k%8TU`9{hsvhiVwDqfi2l`;{ zYRK5%$}ak6t__qX+=n`XNo^W>g|qMVv#PPaIV*xAeTx*J5WM{!JtVD2Yr210gcc%& z^`f*@9e8=1C2xWr5s?*SZ7MI2UWS1xmqZinxVwE|j~i>D+H6p5rB+Ie{tUG~lmOtV zuuo6Cp?@onJWQ!RcZs zvF?1yUk6I{9Y}?IRq?->XX<->qKro=uoQjtUl@x)K#5W1ioon#&q6WzL%vPUE_GeP zPXGMH1!S2`WCSOOxCXWFld+p1fB*l1rgzVv00NRys8A%TsR2|`LX`-rN>xfE5hY3_ zQjtKFR47tKN+<||s8Fg3pscp7v<+oj4VJC5O|>X0Hfq4NZL3>Sp+%vQNR&tfK@uvd zNlGLr08j-ARE1K3DxgUvD5?O6pix0UprsT7B$Xhl1eBtsB~YbOs4A!eD~bRDijYJ| zkN}7xqNNp3QbLMRArgW>N`i$26rm!LsD)8fLJB0n0Wbg)lM$aB2NGZam;ecYlM$aA z2MI6$OaKJHlM$aAe*qOlOd+96%AcX8lhYO3jpBYIQXrk|>8 z6BK%%qMl5NQ^1)t(={?_qf^14m_{ZOe^bF4X`>Sfgv7*YiIYsK ze!zwkQ_-d-(qd%EiG(y7Pa`8nhJsJgrkZHUsPs=oK&4cOn2i7c(VzeT0000XfF?CC zOax#|1i%2%FsF%x#KAIRU=gMfgwrMj!eE$~5tAmG4Gc!4Aw4+*Gy!D+*30#x#m!Mg zgFg>_HZyQ~f4W0EXB7nNh>gO0!^6ekvS$FqVuv2UW)xtP^EVyI$kevi^d|h}J~Upa zuFj>i)uDXKT4FL+)_IaY^KXXlaAV$Eo&U8hY7I$WUwzYc7@LV2%&VTeX3O;(TV|m7 zNp-Z|T>8w_H0rfhv*N{)C3iiqJGlH3f4t-_hfA5he}<`(Cw!I1rEncNFl(BmYz>o` zCvqE}%KC)Le&2ZCsxdNIIvJ07;?%#}S%IM`s;Xj%yHd&Az*&2gCvzpPNoK^yKg?Te z_itYQ?7)`XPYsR?yRB++Tx-UCnpw}*S7uI}&lF`Y5UYsqLe*1#sdsr9XT->ptEk%F zf~RMoe+y!jaqc3h&tJ`s&KTMJYM2TANM-`FvT2e(zl&1l$$_HKYtBzy#p4gb@+;TlK*_5*; zun++>16|<8q(C9YmnY_L=?o!`82p@){`vu9$ zzKK_mmvEE3Cmm7YgJ~wHOF+HjIwuhLD9_3LVz}xoayQa+%$-M^7PlkWjJ7StOI}j* zf8{=xc*i}CG>%7Vl-jClI5jpDnmghtzI@N8W)nebcN7iIOK|3Cc3$T6f#H(m!*<~6 zTIYrG!2I&9XqMpXr8!<1s>S-MS(R6`PJ)xLdyxC#p?gr(sMkj+EreT;&=-R#+-u(c zm*nXFZHkYx@|3e|8r=BOAiHEb^KQz$2s8ewZJdY=f?sech!-;!ko{>gGs))c{XGu)i|LL*r8Nw7*6cK`!pu z64L2y^%_Vr!qu(;&@}VclJm*xVgmdUeLUlsAnX~fRq_O>qV%+$|Z+uO_9%`ds7 zet+pNxF7JBXdI5Y)d}bW(Jxym*lDuk9_y)~mS`)2hJSu+a!X;)qd^D*}sF+U> zpS|8uYc!he%N6deI+p5AO&8>mq13FxPY0cs59eubl((iSFid^o0M?j-C*!p*+ zRbq+!OrR?s2Wa@>;$zeQzi_5;7`ZQ7IZFzqi>2t3i~}$3@gixZfS#2tYvFWuI!)%S z#_Y;?R`0ZYJGdpaT=lQnL6%f()PKC7wUIYEkHM^5jGeaqo@Oj}N=|2?NA{HS;_?V^ zO75~!aPQ+4@QMB@GbFA=oGS{F(?6bs@*Y1~l*HJmd}%B&^|GI?#`u10EvJFAUsJ|Y zlDklJxqMgTruJ2;MEMmTXpRlS$jw-|oJ6N>FAnAVYu9YH1bchuNb6%XCx1H=OyGZW z>^hk)_)p`|)m*+_rPRCjaNmi#1F3ozNKPzF1ka2A=wB|}sy55z7MFbzw7EGKo0BSB z+XYLF^~ih!?8VuN#BLPxMDrlz(~G3asQ!8_ZCOe#Cdk{em)yU#?CvKmN#kVEa@=PO zHEWZ^lkR?)`>}f<{cra3l7HG?`AcTc_oYtrgW06EPAoC^wA|^B9oa3XifJmZRGA?> zuVY^fvZa*K>H)Sh-Az^Y`lPbe1;ffdm?*td_LK#J?dpsMi_(VOD&epc$Gm_=&UUh6b)Uw<#M$Gl3HyH6u- zZgM&IM#>EsRsmQ8ZtLH~bC{A`iA@QG6`Noags>_1M!$*^ov;(K3kr@BG)r`wJynQB zt#xr=*m4hSoZ5_$OCsWY+|owFNyphOV2`(D2|i#jBY&sxg_}K!ojyIeSgM!(O86qR zc~1nJurVaa@}PeFlz*KYz!l#=+*budu~R$8^$t%wlH}!ugY1)gRME+EwHdaJ@6yH! z(>4;b{+@SR?AGC8d-3#MhQeO%;@Hq}scww9&Afd*-tt5@$eAjZRZ8Jo8^!TzoU45P4$z*NJ<>QjjBKUd zNp3=UlEQzOVt*V%cx?{?Mn2gr5_SmSB!9iA+E|`loW30DRLUu7^;daLIv8#k4}=^7 zmfi5M6TN&CypnTXE0l|MCN!6N+F{xgk$R7jRjJa=e@L7$8CaW6j`ixDU^Du5#wSDk zh4vgMuSr>=miWes+*|^@sy|&zF!YjRZ;*8#UPk{*KYvr0Tfo>v8k>` zO9z~zf2HM#+1Uh~#mQT(yCnXyc@~Yx120Lm{9f3bmf&2S_wFOsUPpG5?Ek{Z<;3VM z882u@fAEz37ja8cNtZ=)wTa8b z)sLbXF*G6iBJ8DVdeSwVx?9?-Dd7p`G=A@DX@7gpDvMZe|6rW5ajRfXIv0wgCnKcU zRLhadZ?c=kE!vYQM_ozXUpL>{RVPPb2X$~=&^N2F$ZnQmmK3Y+KQfo`@I$qS-l<}c z#j@gNLTJd==~nBQ6Qs1uqEuyRUO<`tokl<()0R}{{Un}%oFKL6b3Pv@BkjWe&FLH+ zRey{oSyh=b1mym8S4S(H)iJ=+f7)K8^JDh?kZX4(OYTJFe6m`#52JA{@};$t_n#V>EDHL<{uu8y7Fp9xe zd`{cNWK~^`b;=D#3+sEkv*dq(Hs4o<=an+L_E2CD#$c+x@iv((DOGpDZE(9SbXFk0 z%il~QhvvZ%o$6A3daPwiwo?SDc>?30PQK7ulSzAJ*b7GFV0$3)1%!4+Fl9A+?& zfk~}YVk){U6z(+n8_e=5!GpudD?1j}?zIQOqGi=Ao`WY=QxB#lj}?d?e3_L?F<5*n zeW_|7VY5X{1wAhwmGU`K?IX*-299YVZn_e(%38>qjf(Oqc^92y0@SlqHGk@iV4C&x zsbX|E)A64kh{yIdZfrsfSbC9QWf&@~_ACZ-fLEo0M;wa^9oF}X-R@SG!c!Vv=LjB@ z%5apqrB>wIiH6EPd@g6>?O15EXs}Aixpb~^v?;8Tl1%EDAly_`7A2?VWo^g|5lsMpN4GxStT1h*PlMbTK{)Q5V z`)?{d%*VQEq%uQ~rC@752{4m5U^MIwqXi|-x1Gg?;V@dTnuYsiF^XSL0;^)(M8yic z)nUj|*rTLTj2X36fg64lycH}ThN-Hle0(xLgl_UXcK{nxq#=@*R)0>O4pRMihbt9< zM$ArqOeGv$7!C1(=&)5>djaAqU}Zph*hyA>pA!m>`vrTjVQ@+?G^=SJkgE3>_Unc6 zm4s2Ze)O1E48a-BxGR_@8mB(MS7{~kv-+HV4?k6s(+Pxwj@roRuHbnmlb^cWltu;%9rpX6(gX-Aq`_} zCNWQ}CKeU~=q+-VAkjQ)6svBi!iCzc(+L})Faqcp8g2USMFWBqk3|u*Iz@ z`l)GmwEV!#l*tF(O7voXjBA9Yg?pamOA-q$3kaLW4itNdv`@ZkDf8}TvVV!JF9 ztT4zSik75y*OzN$RyrCjYQ&|JmH}~iSz|DlTEkVd7%FVNlSRV@l#CLsV*-OYtd-^> z{dzeX?j`G3qzu4>M0m!)@>Lfh-+MTJszEDc&)27eWaV`#oZEG8i*8de|Y_g`)o zRIij%hDMI*y35O=`vPW^bQG+gXR88SwoXGe3xg-7S5{9h7rgLT%7%nHXKcuCF3Gv`a+nW`HYz(KCi+*){x17p7??LzT;$vD~0cc|b%2)Owgz?y% zB#y#U3V%zHu(<;Zqb3A!Wj`j=rZQI6zy_qosce+6$hUS6UW)>jfWW4lO_GmU`8cGm zBCf+4r({fG&L0x2DIc>1yRcGq*^3#6CE!qJF1m}*#7S=rFqlDH_5nS12JB1%w!4+4 z6r;Vs`m|wNb{3c>5mti1I0+bB%#12K8Ta$9sc-B5Ewr^y` zH-9`Er7RT5S)gH6WSBJU6psynQHd$9F&J>UwJ@Qz(!iJf;Fpw(0PXOj$W?r85Ay+t zO2|E`mziJfm3wR-q*p9r&%1&DM-Gz`jp_^(e04C2+pxMO7e7hBco4PLJr07Hed=C< zOj~R$6f<8lD;CJ+rPsMz?nO2z?Y+87Y%A9Fiv(UQpN`KlLC!~Mi;n44u5Cf z`(7L_+aVTDD~TiS;cZ){DIS$3{3i2_>?vVvWZK3dT1G1O z$yz#0S0^J0OAH^k0I%19q!XbNc7J#^adjU@sKr-pRt__-EGbr6ERWT+ikCpd@qWueMT~F5_9|q8ZIqc>Er!{7(wPXoQa?0J5l?liA%q@% z|MJe<;*WGD+ezh8#L^{~t8FV~j8z;*-AVW{t`6If#Y?Wj%c;gGi7MI>X@Bz-=T{JyQa{xza$w zQ*#(9KH@FKAJj}@I?D_0!ovSQ_e=fxWlVY(R7)^}3$}}2eTqLTL-r!SuaHZAVgCgf z^qfZP^^$JhZ6*|(%1o|4zJHS`qfwKj$?H4tpH?O)o<3fa&Byg3Wj;EL%8%QVNu~OH zeI`e8QN2`Sr0Vou>Lw_dW%}5d@jDSQWWH@iTiw!br8L@C0sFMWemp zujqNQz_J^^M+Tajew_xdlhf6T4DO|k2BV!r5*nthiVTce=6|IIHZ&SuYuYH~^=6+2 zOB%Hwt?-KlM{9}dhK0}6a01i&ji6SM|FjQiSRr~jE=x68JPK#^Fn&&BWYX5b-{59) zAjs8>`Kqi+=D&W%Q=L;2@qwv!Nj&bCBckoPKY)f_ zC;sQb%4Yu#Du1feHon59m$H)03o3KG7x%~h+O`S%6UC{L{k~TJ#SAhVKIawS)Y6)!`K_j}y$cqCCZnyPvHo4ikJqZ?YWq6Q zM$YfBdhI``ygZssM_=i2{sO1*w%uw^x9ausWmUL#xPKD){X80>c>}|t$Xy~(QAD&< zdHBty`?|HMsVjxk`L7^ed0T!*Ym;03Uc)&ie$Vgv9dO67w0+8_D_7CncIec_jPms@ zeh-jXf2(}_<$@PYy?o;Iz~=axg-B4uNBKMqx`z8EsSW3L0A8-q@HqGYU`hG?Zp9g= zj(_{rh}t{9jTV3wm&AXK4;hZ?cPcLr3ydeTERXC`#OX-iGjcK5S^t%}aoU!juF=ru zwPu=DI67RrB+qi+3@{6|!9(lfg33H^`_5u2oc8K02yfj5Xt_R1-6Gs}eG}MzL}`Bq ziOMSXy{}fL5YsYdYmd>N*B{`c3oMsrrT5b3(u^@5}8}aNPb^-pQTFX!LP8U&|~dHQb3a zyB2e%nf6=e=7hnZqsV4j=8>}5=bPD7wD(KRiv_*^Ef+M@RW;h}#P=)!o7s2(K!2dz zWGHR#u+Z7~+b|bZ`EGym=l19;P+T-m6+^4!AQvSALl=|*vy(fTzsyrufWZ80-t&D) z?p*$D)L17W?)>pvXIbm|x#GY}3%lOfMW;!b4r8qHlu3v*-^c(^#VcAG6cO)#Ts5+TAW z5&ASBrwWc^=3V&UFm|(k*HTI+v)-c1*j_UlC;(qmMH7Q~tHoS#80>H(4}Sy_s6u%V z)l+W#QDeYBs6iSFeHI%ZRWQr|+%0|}5&?bKVb;NCPm+=5-93nOfS*`HDR|;;KzF-Z z;R3&u(O}Vva=nH#kbep==)sCZLhU?pWcbBBZ@H`BChg2)W0LbbEQe{k>4MYlKd9&W z%PK6tQ~UJ)v3)vO3SM4oTz?Oj(NfH7``18Lmxdy-zV{_7Ii~X5{)+`1@5T1CTzVK$ zTb6CTb$(WLo@q2U?=uhT(VV3FIo4GJ1k9vmJvuKGzm z<{u7-^f{J!6hhiW&%OQfQnBHl1ZMxWT%=ez`3Tv#X1B>44|(kRjC`lLk8SLeVE=5i zPB$mS_favm>VJ--dh|7Tp6`X`b)|9U54q<_%lGbEKInN z0y7sWAdKbS{kQab7z9II!}~ylznyDmnTh%#6n*ahse(@rrr7gZ=T+O}J5-$~0G0eR zP}DTNQ&{vnLVQg_u1T@oV{Y7KBT_2oD0;tNbcOqSp?~x)^(dJ-s$RMPM~y;=ZZZFm z^OPfDeQ#H*uE7E^Al`l72B=W6!gkzV=6a^O!{^{YT*h~}<6^-Xm?|`J<7PXgM>|K5 z(;vk{A==*g80t?Q5#UqPZ#1EN+6prMjrV7m#obG?hF1U0%U67?Z|qce|5wuUbQ5R{ zFi_E6bANX!H$KP7i%aC}cU!CWgi0zpFHUs@<3Vj$sA}ZsOBD_8l)hJ?f=_*ov23|= zy>FGl=}P$9H}vXzz2^!}hZjSq6ymdDwzqoxE}+YzHg_#f28%dwlqdnZ%i>1oOZzGu z+_i;{)CIU?@XaPqSM+Z1toMaUi=ycG^%$_>_**JuLV4&jW9^ zKi9$YeA)0e%>s|hr&PR;e$)(X>O4KKO5VzP-|yUOZjqtkC9cYNl(w^Dxo zLotcl>AsFnpa7F; zvwu={S+r31IufRj3&T)?>naF6DB5!Lq0QXu>h8)AQQxQYH?S5}Y%;be`FK4(Ph#`> zd<5rlcN@PG{@(grKFRm6QN8BAKC^<4d7snOceE?2JRT?u@#Tn@%3fXH-OeD`b@y%+pqU$;KJB{! zqZ?JWWRz*RRBRbQ$ue@Uqt1SmUfXFaOBNeG?~z67?OHOmWLaJ7jjG9j%wfCqI6lbd zD|A)$_rLYS=O|B#oLL|&*SE--LVrJFqbqXjHXmkIn5G)NET6CWWo5~g{ux;@@+i8V z9Zpw*N83;KLJ^ehJ393UR6S09E=ZFW`JaOmpqGUNZ@t|Z(lBC`ZDi8$^ay5@cYEJe zXq8R>5UTwdt^Ta9tFm{x?>N5?*D^GJ_C!oH1 zQB)<+f{`jJH8Y|ove~~vKMXitmM}LJWYCs-bQoWv?s`|NjGMO;6S_&?UgzwRKK9OT0?KKUsviE8De8Sek z%G6@XM9S$@U*{!Jw14TUzvG(8pIgSr%R`Y194jn$BUQXM0}_@cjBn#>&3tG%mX*py)G5S)F5I(!re5 zC0EAMmvyF*p3=w3&@0B&(Q1&e$-(|IDw}pjMx(L#=(D_Uynpg>6IF|xlS(aG5|oic0NJS@gVLqNvfPDo2j!UHA5_nt@b!a?Be`BwX$bsf$z2eFEf z4BT}9nvS3nHIX1t37)@iE2lHtMNkP9fBG{93{3`C(frvZ1`H|=pRbAh*b2*-ByOaz zGt30&^PDP+^nbbb7O~$jq`z5A3~{Vgz_8MCI2|n)vP>#VX%kV42~BQQf-lh67)37W z=M5=U$uH={spIQt#cDPWoh5`>b4iNZ3iw0KNyZhAcz8w5VfCb8CoKyCSJ9Dzs_3Gy z_IMC>GGIdCYTwaeM0y>Y3Vfu%v5#?uK<$Y9+FclqXMf*e;rb|Zu!7kziTTuf%B_^J>f9u-KT+OtOU?}tPBM0KNT6v*_KBC7+LXzD?M*@9}<%qF8=aK ziWi`k3V*G9RsuSztSGj`oCuhd=4>y@CJ}E?ut|?rp4;7-`f(_Ft%62?RfgA8uoX7k z5#z8*btKOk^~jbXQ-i>%rExevr621C4)y%YTPHOm;#jPtEG3V~RA{7lBl}qppWK)t z&R7#vDCLy395l|@A2k+mOeUiY$eDxOj!lUs@_)dR>=Lji+$U>6giqzMVKcI@DrY5H zYYI&aSEiSzx>`b-T>d&rjTgb!f0c)tlclAn4iN> zb$EeX+WN}7P0jfw@FPaOC&>d|6_Uhpg3Ai9o0H-2DRYwvh@`lmswNcha1`>$U~Wvg zOd@73fv!wCr{`c%(n!H7<-ov0l%-$^#ea(aD0PZBvU%#at3OiwJ%Q`2sxPTYgj&`J zwql$@OyyG<_-@A$E@>E2?Gms^-y;bug@jh|f~UbSgZVz&&K3ArhI+vhY(;{9^8;95 zY{dLRVM1{=E%m6hhN0PG*dMzV-*UoXNV-v>JAxm?h9af4=CqhZR3ve+ExQBCF-}9y#HU+85vF1MhLtW zJBY(5B_>)k(76FL zacoj7qDAzq)JKz|ya?6YQYR*yOA4O4aap+kfFKL`E8` zadi0%L2d0xE9PN|ZS_|lBM_W9AAVOhPlsd0JS)_L5m=`9!ltTBsw>Y_(9(1dbTtUQ zH@TnR%XpOE(R`1Ce#pG4S&F74SOLl53!_sxs&93VBU;`fx9gtWZMF=JJ$4jL#%&(l zr)b0;M7PFNi?JtjiBkKjKYt!S;rxntkY-BxH<3%sisSu4ndW$2;52Y)W3ln z=gfujWNVImiL&Yc853}SG zL#bkXg69PDHPubH846X(6w9HpNqcax$6nsRayRWogsn=B>{f3R)_!}vkm2iE(La?BAFn`@CRwS&&&q0e52<+^y zSW5Mt(?H)viXqVPbzgZa4I#%913r4A2#0e^QC5wZzeQ*%|2|B@S$6u#h$WVDMhi>&QKYut&0Gio}@mYQcNyen&WPoL|3J$*~!aLoX$)5GSU z+cb+UrTtYiHk~DsH%+&LY$ab8y!{|{dNLdvyX>KV(7CJJC&S(;dcS&$Wk))Ol~rXt zKFj)*St)2;BSHMhUEip)NuEl*ZR3M?5WKQ)^jTzA34bZjGGtz9IrS~xrS!w!=%uN) zD97<{12rR@z8yE}H#Xy&dA`vv^O}qIwS6`J60una^9F9!Zs&=Q#Rv5&zGN?RsTGU9 z$_w<-b(Lae>+{6TXm>|dDV!wm|9qAaIi`3o-Hc^4zQU$lt?`!=P&3_Sm-CtyvHj@Y z$;Ez#Fn?F3v7EDrV; zUelYzO|h~)?5Ru7EhkBfVyR?(qFiK`rAf`hX_EA1KV!GTW|%Mwtp=L(P=QpF)k4YCQvOC!Zrzxi)6g zpMRC8m6Ot5ADf{`Y;{(ND%A!KHM4xRg#+TFhqnWYl`&n>z6tf|FwSQ>*$@%=;X*Z!+rg8qir6y*o{L)=<>BR4? z@fUrs+x)MfRc0RE(F6Hvw?EetorAEsoleHQEUlmwgOF=mSA7fS3A)Z$9sQ_Nm}tpk zGsQ2=OO1;^QLZLu-{!=+Xqt?d*(2#|EoztBbiCWNbo?WuA)`vRdrojWhW(tB(0}N7 zT916$N@lJAr>;%^#FKT(YF+=i7t@|06PW#6OIV+2*YdTB!?0oc= zUQbw^aa&{Zm0x@wdAic+0@~Dm+Fq#8s_`zYZCz>&@1^)lvZ4C1Dz9WO#N>%a%zk8z96 zO^&6{I^Kivsh1GjB-#zInq>!9u(UWo#le%0wAEGl?clEbO`Jx7UV^HJ#<@z*L+D{Jyn{Q`^TIEC~eO%|If&l zYbm&M{h3b6rSM{Qg1KeUDZ|pxLgkddw<#A)=Fz2Sty)gBG7bcqUO|Xd=KfflT8*{8CzsIO#6^+SIzrTth~h%O_71h(xvf+Dit3>{_SK|joOV`r;+1gyFp4+tUDY}Wj z3)a-PN}t#cwmzpvOJZ&PM{ZB)Qu2wg63hu?ev^H|rdRuyhwPO>mzInNH zomG(cw6lL@CY?C?j%m7ZgtyVVRJc~v_KCZL^F#IdB-mP6JQ%H3gMVhE>!P~FSF=m} z@*IQ!Z56wPw(c=$#m?D}T~^{z)xXRo}w#DStoxx#W4< zz0b(i9IBS8`C8WfabWsr%L(X``dLe9h4%C>>cs~B&Z@7OQ#jxbotBo~Y|@^G%Tn3J zchs%><77{<%&B*{JKDSrAWz~K$&q<3m7ciFZ}BCl;wUoQ+NJ1HaHQX0!WT-F!Bn@Y zO*}?g zqw7T2-5EEALQDLHRTc9{-h1CpCqAjQCld$G%erjAiEi>(dA*0AV7PAQVmARzfG?jjW*sW6U zxo~9dC&{uoz9r)NY20zMBvpPpY>~;8hfx#6xrjdIx|bTG*b4c#8{>nm^tPb4O$tw; zD^QE$Bby<*mO!gcZjmuctWz{+80uI|ek0kw7#_~H@P%|zd6KR5mf5majQS$qUN21! zxPQNwj;W z>O=7V)|MMZsl7F-^e%O3`!!Rq>sc#Zq^YT>rV&|yHGS9#k z!AE)Z^q^wbT&b-;la+3&#S_g7_UGs{J+_x-spAt?%bfnNwADItaiVJ$(WHg0s;u`o z8SAv&Zdpq)(22)9odsbE*$JrwZc&?Pj6_-+mVEg>3?ARwFI(Fu&d4?A!SNk9UVmt7 zK07jJPdlu713TJyUy(VN8~pef9wK4?!Rt7W@u}r%o1q>&S`KBl=54B$qmTSJfjX~^ z3n$s;Wjsh&+b^R|hl;#9O{6nTgCXE5YoB6VMh_pKgYds854V!hW>*QuLHxg@R+&=H zhSk=`**tqJKkzBgJlmG3u(ysMY)zP{JnM>t*ng;XR2P+wqh2 zQ|5PG+Lp-AF>I)v-77jFo_*?;oGZKHbVV&v8Q7P3WqBSy`l_{68~mo>6FX)n9k5^i zg~r0u%CU+w3GWjx@?3Z%>Yu{$J#;z3(_WH@-rtyllG7;uHLG z?K!7#BDjfeM9`XsT}tCxLZ)z~wz|C^3=E*3n$oH2s=CKQTWnX5J{KTOJ}j%H`h?)+ zT&`G^nh@t;&VBg5th5NZN{nGM$J&3b13D_@;SgD?|l5EnO{UT)ns$Joupm8*wVsP z=%L-C_W#zxQ&y<%0hzt7f|IVO<7zblKRhiVrqQUsT-A1t!7CfhMQKTXmg=&|c9!T} z%Nd=jdu}PJXXR;>X@4Z@^ulHFbZ}^GA)3B*PKHaP)vEly$yfVvZIt+2ui>d>nnps5 z{7yCxvs2YmdA*JDB|o8_SF1~36P)PxX;+d?W+%CuR@Tu8ex_knqW4V$UpbsCB(j@8_ZwgQ;e&j6O(bd7Lo6hyj5sEpJ|?xAy%mug%=gN z_ZV8z@LW5(sc28WS6L;)^RZrza6_|nV|ypY-+UyjTw8w;leMwAs(K~*nbAM^P8y~D zC1;G~O_ZLQI)7N3S#}h^4&S%9(l@3zy+!R6qf>D{at^*H0gwmSx0xL(wSL^GQIpsXdiG|uI{PS0+?@msaTO(Ri@2O=3*i^g9ZBkftaqdM% zLDbwyPk+I__16d-mE802x1Ub*_PHCDB_EbXsctuYZg;8sC2|#&yX%}wZAPz4qRdTK z+aKmlKRz9@O}LvXTgyX#!oTEKYfI*@>-w}9>id|pmfB2#KOs!3MHfWviE`R+L#gu6 z?Yj@aED2!E89Ur^G_hPuQzghW=^0Hc7E_5O%6|dcL6xO_(tKps96d|dX7a8*>&boM zGe4S@mMUr=;mCU=|D}Jb9gc6^ptXpz1g=k*|6ItLDwof<9qwU=)k^YtUmh1tS=3m06rC9wg-6xmULRRf z=6@8wGr=ZBCd-wV6^)Crel{qc+q89hx~pX&#wBDPSYACH-Am-DW6{sNU^{0R$NThp zvOX?soNpCJuY>)Qyk?DmxRS$m>|B?@q7#j(b)7mrKc%kIIASVa)zq}OGm4Fu{a3#& ze4MclPa#3d%S&$wUH;T9UG1~FtC>^uMSpa3EsRb24tXZQNvoHXjmd8Aext1STS-?e zqwmDkI=<|uL?=~^aQj(YOpG{Ejn(*>L%FQwpp#O_(f?F$Ox~X(7Y(VYt*7jDF5gsF z3ZN=;nMY(vGf@3%=f-4<`uC=VN2e1Kh59@@0CB{>;vY-A%DxVB+Wkh zr|nYHO4#Z<;AJPGj&F*k+R*E4)RuN9RomJ%IXtvYbE4xviSeqOxBPO^axyu!R|OUV z`4nt3PbJgh$CV|^zhMuo%Q-r$si^Bgk#Qq^Wm6gFQQ$urvT}}3WPX?b4l%_lzEUln zO_#Hj-8K8x3Bunzrv64fFMp(6NjEB)c3^Nwwly1!r>;xylJwlnuga%KZ#Q*o{Kaw^ z!97xE*;y-{rb=RN(rDMVgbDY7oC@t@)#A z9Vb{zI#khQzJgxkl&X7AnJakAT#CHpn^z%C3z%?Rr$rA$hYYN8bM(1zZ}RsA+N0Bt z={IE=IKHx%x1e}(dw;Jn+d%B0q7%_2#0PH|NS4)RZ%HQ(lRI1G{Ss?*nvmQ3?%ozU zE$SBXss3FAEZ4*2;N5;YS*WbOQ*?`Ze_nCZqj7L80gR5& zn(U07dFIBe%cao?sDgUT%UvIfm*obt@--rBm z$oi!7io@dRr+;K*-EkJ;sj2o3GAqqw9{XX`UW}GY+oOMdT6>%HFSU6Z{iDiK)gsdf z`r`V;dBl4S8&Y`Gv90Da5_HNu9W0iSm?~pQkJ;+31v_aO%8o~~h3J#YvF#^fE13r{ zw9Rs=_&ZpB3@=^EP;x3=o4=)@DRU1TriYHD@SJ#`W`9+$UL~HU=wGJLh4!z!CtKFE zsIIY7>k9UIE$Nmz9hRpF%{3J*R*M`@HA`|1;TN^Yzn{{{_w=vMhki>{b~!0F1gwyl z=0bQm^WNYf{=ZcmvMk(Y&)`pycPOFY#>p-HEGgWVXIctm(=^-W|z0{MUDq?kBS8SlrH~qD7R|T&D0%8|Hs6yvrT5 zTKoNzUK5o0pyF<3Pwhqcc`J)apDD;%Ib07#sDH`+NsQYRzqXSvNSs<$zdPvIKZ>R_ z9D~DmvRkPx2R?l7FHH1`_gy~DPWNV1%;)6Qs#<$}sbltdyw4M5*;@Temy5tA_D@Pn zBwVF0*R%HNGMua|okqj!C~Imrl%2-d$Su+5e7n9)aE6|Y?N9!6+g8;M2oCEm@Hr(< zmwypmbecWkC2$cpr1$DtQ*&>ycbdOE!Iam9v=5ot^G?isN?kw9^GWj+b%|N3 zT{$>cpR=WL&#X-3o(VB>T8lL%J=>In9$&|`y+(O6J-xm$g6L)3h-M^5o zMoaYkp3u9(e?49r9XnAt>J42QD?_0xz!T?AH|qYFTVujUa5&rUQM1)K%6CNd)=wv_ z(loY$%<7zv!T6ag%aY6c*tJ$Ub9!fVpp#D$@1=AgqOIf!y)?{X1L;{>sk#UrD(mXj$ z7sW-tv~pdftNB#?2w=e$Uh5*dW!Td3mAfR?omEQ(83JifVcOye?|<;`^1Xu;kURtjKCQ~T=i8WOFUi7P6tYSQd=Q8vYGQ3%oOauRB9E6 zgTK=;&TyY>ntufc1ph|4QrIHuTLCp!)W+3YQ8jJFxBfSo`g2&g=d-Luc5%nmU896! z!!A_N6|pXmI{($Id<51X3{C1&_m_B20jQCyKKhKjmU~OH#1nlcXtP3o)a!n)p^&b= zO@9;XD!J#3sm6(w*D#@n0ZP#Sxm@a*3RaRv;eVj8Nq^Q~Mh!kVK3nwEuBc9sx=YKs zkvIz?rx6D>lc-mX)5OX%EcDRueHO+~}uNqe@6 zldn?Lwm2OE_Z=4v7pq4~shnelxiuDUPH|mdfv{pcz3=_LIzAd!y|;IpSuiB)=*`}W zrWT%~lYgVvCv05mr)ks^mH`6}{PAX@)k(l<{Ls9Ige%si@=x8VCg}_HNZ!fJUDdx^ z8Xjkfc9)E!IcC(%TQr=-r&tNs$n(*5sAalJTrY=fS~{Dej{@I34Ov!h7ZH6T@~@;g z1X}m9w)H=m9;21J61}zPZ|xpS)+dZlbe5e_$co_@lCOWaErQzvV}-W~sPXcjy5v|d$76h2t9x=C6BAP75vIL;*wSZ|ccifYDs{aQp3ttRf)k=6 z*eZ3z+a4YGy)D5ecG#QPcQ=Jgo&3;i5j>zZ$L4D#-8K5F?9#up!>M!GxVXOTrWj=E zOEEyrl*)vvXIG~xNK=BmDETxLy8tyOT!Y#V=n2M0@IhKpu}{ix?ZrQj6#Ls?PU ziPBVRABPU^+LKa=zFKt$czRIjDz8C_<2KG#EZy7 z{|l*fVSR6hRsF}@;F^AfPdJ&4OVHRAaE%fy_Kn%)r-TcoUvfr0-d@TtIwtSek+>J+ z3!Q&a>nOilK<9~U{C{Su%N@E_uuM+o&Eny3xV5~>aj|C*xj10r-^?Fli^1VU(G6!o za{y-aTC8j_JK9=pR^mfw(WyOQWrEvdv)GA=`89yMx;l{PKc1%D+!~JU((wYYDl4LK*|72UrXS&3iz zJocbWGG;yHMsF9N`c!8Rnj7DtRB#T4a9^R)bS|k{jUT&5njKO2hqPT?-R+2+SC7UgvIETXNs)iD>QfG&=Y^D z(BQpG8mZswpKzN6OTgK+j})HE5z;ozF)Km?UU>;x+**+h?c#eXUWW)yJ(zRq-G1(D z7}z#|{3&Ur_kBWaZc-P}spUR;4EA4QP6GM>)*)p%AhWf7%fS71$5P#B)^kAgqQm5< zbREPWXjZ#iye&t`t^utZ5;2-5| zcha6rmXO)mOGs4cBDfrxFLx8%)cGH5PBxZ}CZVD|3ke()SMs9Coo_T=QeA&s*X@Xz zvS}PMPWA<6eE6-0EX?%?t|Fzy@o9bGUWhm6<0g&raQH-WYPOM_h4)0%aL<2I*gsiX zj-`8{HWAyW!lP5>@|wN@GMC|IvRd(X zZxSx2G!?*j`qfM0p`gtkN2_o*d!MELl5;ekDA_Kk*6k7dtH8)bS706 zu)djf^tI`3w6c4Po(q%aiS#Ns8eS@<_E|kjp2iRU?7qeMRBI~toSc_uywFk z#L@i{efoMr%&4<&eWFUg6JReSmeNh}$|Cz{ZZx#Zc=G&#Kkok=0=awf>HBf%#Lp?u z70dT@uY88Yjn|%fUCVztW7(-KDy5|}PXV>A+tE%DnXB`YanfkVioxQ>Osf*uUamJr zscFQ(|2;WAr7QW>ZqB6^1uZfw>JQR}vfE#>2k%Vml6-YYLBF>?{SCSVc30$F=t= z^;KBRQda)@YjK0tNaE>!gm+iXOGod-+);MXJ_RoXF&{jy9aYhMO~jTxE9oYhD_myW z;g{mc#y1&t8eu*c;flybu4cT;?8eztz*EWTyQmya@ym4lJ`F&fR#6A-`z;+)i}E7V zX^MAZb-I6is`^C7a5DT_{(w!un4e`9!Y{A&f7ENwP3|_dtrn&GxHXT8@gC2WHq7{) zTa;1W@(}#;JMH?L@YQY$ucY$S)Zz5X^ZqzwMA4$RkMsPQM7V!qQ`BL$QXWEf4ib}v zb)fOLZyaux$%6((<#(E+ih<<0_%oVT8(d2D*JFQ6!j*Xq5s!KO$yXJxaOB$`CQj|i z<4gN1r#_08CD*^`@7OnOn7z4A!kaWxh~)|U{LWTZij#1p*KPIfDC$i=_0RIb4Lkv(sKJyfqZB*B26B%T|Zc%5-K7qGHuGt8|k6qzn{ z^^x`KB&lXJn&(?);(X;F2b})+?Z=hgJ5V z;dHs*TO?~lav8q94lb(eKL_W`s^b!IR=@SpZqyv5OCFZGO$eNkKOot{&dcvj+znkw^eYHl}Go>G6v zwN_bD;mQ13FR8F++?~5HZhpQ!c^?)eJ=IGdURd;={1^h5}6kn zRcRD#t-Ye6@-gDIDC&dYCe6I}F0hg@O0d2kG zIpdw1()9gDh^f&#iniC=CdgIsIla@bXsKL=Ybw)-{W`w2Lu_z-*WhD63aszns(M)Q zS__v;uH_RuCR*$~3EooPx?bB(zSJzQ<_)*={}`X39{;2VbHjYyT2Frl2%di^Sw4#6 zD1JpR5uu{}G~oS#U1zdO`pUj7l<<+T64C0+$Mj;wt$D(KyIa~Vqq|NE)u`xC?L$n7 zrb>G&{RzQ8h&z~`pk~$X(9E&fhRi>n?^; zmy=Pd37Hf2bQHHQ8rkV-qS6uUVdNC!8pfv<1UJMy2z#1C{xP6z5}1GegGMKbFY6b4 zo>$&u)s*fJyY3SG&Vi)EHEvhmhW?9y|O7h9S1NbSl)Z4n^WLehgs@}@{ zO1W3iE0W@xj}X>Va+O~}O*_<4vlE1mkGTyfoKB=QFJpgvc%QFl6YgqId_r0(Uh3QKYA4m}Xf{PpH|nW&G;UI4IFj|C z`=qlcNkzl6>KyF-M9TP$(sIIGRZH+C;L7x#7+Tn_DeyYgesLw+NZvQ0{+UnTdL?)K_x;-P{`b zE`%@6t!@v8>e9%nZX4yI>#22Q-zs&_l^WA@@#R_^t@X2h7bPw2h~2Wn88oLZO-b9##92fJ}WZk1NH@qAXv&b$Rp>>Sn2D%+|!WqrT= z?a6!3^ZknVVRwHJYw})gw8GvkP)(}b@2rh#WmI?KaW>!PQue(SFOhriA9bUz)t?y` zEQU-udwrpx;beT9wNc|z+5+~KO&J|wTs5ab+J(p^*M*nGe&JrZEix9Z3-ZPL{N2e8 z`71b8&XcrpLcU6uMVq>bET!-f#!E|ytUX>frSeK}s$73(iSWsH?v>Ce=nYj(y?nj? zqo7dan~Ok&-dUD>=U{rhlZDSg`_~sGoUfJj3Cr&cM&pvZ-`QB`Wi6}1Qp>t)GfU@E zY}df{di)-`Cf?q~qNM12pA!r_+Hl0Ql&*!EZ3$cQr){eR>1-|xZlpSUt*LWw$f?`; Y5}y;ZD)0`-&p-TK$rRy2L3{(wGk>~!Z0sx0xnD3zi7-Nz7o$oS2O0)XHN|GDYMGKzU z_pj#(R=dA{ltn6S*@3KutO13r0)?ytg{%aHtObRv28FB#wX6u{2ne$@+jMRQgAtRl zn;(Dw|Nq3B{o~KGpaWdYbOEEj=KugZ*Z=@1003@a00!&;0ln@3P&a#k02^Qc0MGyc z1lR|lD|a{mP-egY8FT;!_5c8G_W%HE-tGkgM%&N;QQp7+1A71f8(?}hPRxgD9PM^i zBIj`C?%dmSYT|=Bzz0CzuE)*jdZC|8z&=E1G*&TOG; z-0sCxUfbJx&|3Grd)O^(-sa+=m$tiYYYTffS)`k=)yrnio0dZ9%U&^st<==fJ@>ioYhxbwbslXgc402W^EKORMyrt5ZLFtzk9wM*Ys|$u+X?SyP?djr zP0MjHfU@fxX+u-E>B$y=V_);T@4-P^6!0`%SN>X8IfnU1ixX96HKs=FFn zYPG%X!jv?m<3L86pY zt5mH4+fZGA*4vwFt8>csn@zgc8&$P~d9$^)wha!~7Io$6A%_#Yx`Zce<*tdyW-7?YnkUi zv>6rM$4V*Dl!I7_S8Sw<+Sun|6*Or_cRJCFV@U0;nvlJn%%xH4 zvO;#~I=i~yStSElOa`*H6y!qNG@zi zQgU|zjbK!pusE|B2i=aK*Sjn1$6mTYPMDCcW{LxwN~s&2#YDA;8cffbO5gBb#1l|Zh8%SXzP-JFLvoc zQ{MNwiuIAZ+sna-x&tNgNJ0_MvQ>ccuao?U`$Og07f)SO&V#0X+0)n zG&INnOaN5#XahjXo(6(ufB*m*s4}4d00IVp01<&003oITnKWQcCdAW5Ks3kCV5FikYj005YoPXIIk0009(G}@>lq>vB*0000000A%&fQ=dqm;z~p z$$>D8OePVDfB*mhnqp*Vr-6_#OaKaCG-3>x6$DhG5ikG%0000013&-(000S-Mw)2I zU4fjl!rkdm)OlzZNL-Wmav=QTThV_0B+SCG~dV` z(IK|e!gj-csN|;CJaAW1%G7KVLKBdlE(78UynzY10tD?pPef`BvH-hpa(wj~Ob*2X z9ip1x6%^^l7ga6PKK}yFs;0sB@uh!B@cncC3N;5Z0RJdGl~^pcVy@ts!X}p*o(fS9 zh8<6%g8(eUt2rFa+SBpl~wB7$kl(+y$Wlha3^&f9g}Bm(&JfJEO?usDWGg z9>l&>A2$~aK!H==eB}ez-cNFsT$BRTIvT$Th1xYqm!kph*dV_kqq}RtS+xho4G+Y+cIGO%Kl`&&z4zea%tr zxbMrzd~I^QJD)mhc81 zldE92)EDzc!^7iruRgh%HJXfBU&swc`|+TZdU>WrM_x0=^Z(lXEEe%cc2Q`k=eQD{ zNUH+sqTFegh3ESO3MMmere*v^N;G9NSQ?)MC8{Pb^e}ZIxA>ywh+?{MK#1khIkdP2 zN;71NkP4yzWkG*AKqXcoUNsgjrL5yN5z)4rCfG-?1!K?Yc*;~BO!QSAX%VKiFumDD zyX*JLkCV;n@RWP&7l>+b)zu9?m^*hc2w7V!RHDnci<swpNEh>e=z1YPe( ztpqzGldPgCp^*K+C`ENZN5uok?WIHUQ6rY^3HjW9JSA!#TK1_L2(o^ z`PuxHNkE6C^Kjq*;{;q%gI+|g3N`(lvDrYo?3j?)yCeoL@eXLp)ta=$O*(SW-n>0j zsP@5G`Ky1=?I%C)+ibh_LU|1Sq9da2pO=|fD}v!Yb9ze2J~Af4NB7Q9bBhze#2~o3 zpTGt?DS^QiYtXpQ5ZpsW-q1C--rAa|VJ~h!FXe9Ayn^8T&Gl8<>Bq16P5!@R3meg+b@619lmmVp}(D zps6)8v$)m#2te3+Izm2%!vI)P@GZ^59}jWrtiJrsRK7DYy%g6{}eD*$U~+mHk2 zQFKRwj7W5Z=>lq!`SgMWX!}v=7(X~*s3y`*u5?=~LrVo5p{UPt{l< zyn6I_QGWUcY8R*vI9l2gRRb5R2*m=18Yb)90Yx?_nDbcW=~N&a-#F1cP(lY!@wD5Z zdzc?^5~mUEj3~aG?jmWBxD&?t3PRC9Fwo`wpDSdlw820;p&^bU88~3z9%s>ZrUg;0 zeXvGqFyni{!C zTj4-5G1>U5Tl^3fISu!D2 zaB{;Q>ISpUQ8gh6!EqG&`rfjlMCw!n!=Q_i1tY)Nr4wr*bS4zOK&Kig5=6+uDvIbD zd=PQitzPlWSi$(4<I#6o+o{)JH>3itgg8zgtGh2&HuuUY8E)| z{#Q{QtE$fBvvmdz6)F?>edK>1qJr&K|L)MJY$`a9bN!anlHv*l!GpQO9RuJZ3nz>V znnIRSn2u-?R{&eQKja)}AVfIaMF7=E0pXzOpT$igxPm{TMp}R9c}Wx76kukUNcwPb zQS6xlCi?`#ibKzdnVF#m0=xi6??ef5nV36q2d^XX@pNCd37P$AbD>OZPdtYy1E$!T z4*L#~5r$|0A$KFY!;Z=&FY^(%X|)D!JFzol3$*cL!H~QC*}|p9gaiFQX;1mQQP&`N z04W_uQHGQV6&-)1HPuo0+HcB-4?Gk_r?s{?NdXD;*NfqE2Sham!X zfP_5qI_&O1b10;hOPd0O(>H;1I_UG-y25t8+Y#%q%ZO4$gLSh5dhis-pw>QD7_mF$;9?q1nfN zfu9IoH2$osF$5iM7iq{(nTM|KR71q;ialxP6hpTpw$R}xW<^)l=!X#1+W@hIHTHM@ ztw(Q=x>+wnD(6y=N&i(w?tGrhlG^_z5g4QTf?rwUiC+eKRPE( zIY=60W4h!jA5bItM+kJq9tL@^d8l2b2pJ?oVP%3s54>vXr{mKD$k-m6e4=J8TV@X| zBp8~z1$xL_T~~LfO>UGu-?p7{+;);lvZpWlYPNq1VPM$&mLQN~kXnjOB_wB1+4+&H z&g%%Ju2DX{Mc%5DGJE%~S%-+N3SuBs(4Q|5Uxu|Iu~n_(HxMLb{$AKnh5KxFHu%5n>wRK{u#u zfJ1**LSNwz@17~V))t6y=qxsp9ZI972ow*AQHM1)AepFRpmKh8Cn92Hi_8u-B`04J zK+PRB0|Y_pp{~bJHkvRIhe;kSwqDL>@;GgTD@%05>8LDo3M5|8U1 ztb{&digAa_FYu@@&@^Ic&^GDFo>ZfXpJ9LHMu(C>xuUar>ZvBj8{)CgUnun=24g&h zM*$H0fCGcGDsk{FQ(Nkq7cx3ks*!;C{4cRmaR&86Gy=n(+Hf8rUh55B1;+D9w$rcj zsH*K(Dh8VzbU4)+byN$jA0Ao=7Rj(j7DT3jq8~o?BGE1#I-^44n4~$nXtC;8-Q|Cp zK-l73A)z2xG^1Uqcr=c!)KKX7>J5}nVM~w=H?j!6m>@y_;n!*X`BbERd9=^9G^_Rm zRIf>oyX9^9y*j}s<{)|nB+1O1tJ9PfW2yJ0AukrsoI$B9!Y#@fwik^mnY-~wOdy~` z&j)!5Hu!tfQ>8WOc9yMU?P}^Ff{%YTFl{rMlNkX)L8 zM%IX+%0YMn9J4m&?lJfgQlS*lRo*ny?gS5^B50OHv4Mtx(!l4vV-i$gCXu{RavGFq zOoRZVxy)VCH(ILhNx6Qg2B}wfc%`RN>*|Vx=OyBO6A!rc^$%7E5IrGA ze@D9t0c(M@3XnKb28awlxM|Qe$!EUlGzx;?2#_-vKR4lP59%GiC%;s1zRd$N$VKmV zOv;|mtRh%GpHwLr|381_Iom~5Z5HZWm=9olcLe8cJl5>bHGZEkbSYJr` z0E{#y^$=PO!XMk(lqW!~1DA(0rx2mzPXq! zNvP7LSM=(^I!~e*y9?WOns5P9oop+l%Z`RtWN8FlD5*8Z0tVNFerr42eFJ!*qC5mIq5;NtZ-Dh^5*MH$GR?>>T5 z5*HbPKxX|NV1~&9TO$c0x)9pFC~EWmAhq^HG`Rk<(?0PS?STgNfKOr<0W1iYmah=y zXrTPTFVNf>CE_Nyj5YV=qm+)zf7i6S&PQL(d36>4Vl02=k6(cOX&{#8z4P?iVn3#X$|_Lw>c2*b}hPrjzc6I;B*K&G<~L1BU+g%pa)QwPa1!huz>%>xN_I%RcTQrjk#Q z26g^*I;oye3H%TZ07C`36g`nfantTx?4tK@E`yP#+XLZ1JZefL9RVc}6SHj#al&to zoY#M%jTB87M=E>eB|4YwBOCe*5TjP2fFu_Wqa?Y9b2_PAwVs9HCok%rp4PYR1=^;V zFs{b$FhG9zgKoyb0LW&_r%$Cyoqy*^mVk*D(5mo%PPL%{&S{RJ!2LIhm7J{+i%%1z z5g=>b9X8rD4jN`xa4C5&^l8D+05pYRi9UbL9-w`_r=AP{hj3=9)19>j#zsHe7~#4w1Z$EO;Ezv2EWlShvx$B~_kZt(sjC%S(M zMgLe^2>y4xO+%D}YTGc}ky+OOlee4v(DJnK>Y^Nz?HY|r>5PO^eEVKPtF+^yi|(Sn zxkufxFvV9+UV;DF9w`OO1!o=v41j|Q8U&$(hPH@BI&yVz_gK~sVh9vXLqkGwiUk)e z020?ZAr=R5fbE*I5Ka3^q8VH|H6WD%@9*Pf-1BQ+CkJu1$^2cg&{H9p37&hs?z;W?$IW!j;^41@m zHYjs`H7NmIoQ<*oygt$BCS=~VnvB5M^@6RZR$^Sjf7k(4|YK!qae~KX(F9MF5p={SmJ0sP1Ux zKj?;1%yXDf(`c#Vu>LcPVDEnxQ%ie0)-B#Bv+7gUzOS)#{O+D{;cA>xCv$Ez-fuw5 zT%@&Pr=8@>AZSt@I)F`<7_mvH&)0wc+V5wb46v(Y zp1}njtH_~c#!xp8)2_=E@k#*>7HVgS!F+>WqclPrc0pDY4ga=PD7%LfD0Z>!x5{s` zyUk#Vj8OyZhXVuVgZ>ITR{wkitPyk(&BE`wlsr$Y{zjnk2nH}A#!VtGbrXTqI<45- zRCQ}5+K3#4+VxD=MiqaC;REU-W(dEUNM{wL{y0dgzHUB%9ZXEp68aEa0nirelKnO9 zM51TNX4DAvxcA}4)^lSN&%!ZHS^};-CiocoE)oa55B?zth#B~QI)wuhkSHJ;lrH3Z zzTOm1K^So&hBzxKz|S*cyRukr7x3|;piClY%0kU3Ud@o_ps0*Gq6pNkKO>mS2B=& zj^G+62B{9ey7zxdm0QUkW5A?`cN2~QU}I1DL{15xR;Sohrru5&xllK~K8Xkl=^%8} zQ-=sH06~ECLZmym9|)-jkB(4*twnlhg}_MkzJzEVVz4-=;Kaj_@-_N58299QIQAS{ zMK?Lof-vahBkHOV!rwRjn|0ClO7J#3TD5kXm7XNP%{Lam?0souot?HkM6 zOWFcK#7dU2(wG*Fq1*f2X7O#mUm*Z4g@i{MV>xfA@(2HwPb<`lhKavcf=Pxv+xvM4 zNO*+&rXB}(r<9x(6C`cmv=Z~Sd2{k>PhkV1qMpPI0hE9(09=$FdL{XfJG6L(ORF+o zs2o&w5+{El0M3vh3+ztzI#k%0?z;631^~G=0FTPVzl=A+DXsZ3govxvMf6c;Mnp5L z7ln!E2t@0V7@oF9lp=2N063JIPTfuus-z;T)g1i-(162H7#Q#tKN^ez?STCL%ENIY zSX6`J@IS`lO5DVFMMf+BrBpj8s2eJy6kR7M(I$URiDeZ3C;6^MjG61j1nl_jzyvBJ z4K^Ea!@7z5goI80Cp-WV=18AZg9C_`;NiDAhaTzW?LyV^_*9y=OGQk4?K z)3ASvF4GhGA-ITrX+TxHK?d9-P@y-dl>qDLr4aAqvt#IO(RGM` zzxSIdLON9J{M4d|YmhiRr+gJ=2%l~&LV?L$R7x5-5513F2hJFX9k@gQ!ofFU2)3a1 z{LfOk2fIRf{lyGQ1T6~3`_ZFC^XFA543ymMAkdIC=wlx5`SmZ0a5CAA2uM7_v3%8BK8%!(*#=jD=IgN1TYz`=+-9QWdxC3dvu1#0wxWr$blGa8cJPO~2py%fsVgm0Vpck&UlfJ}LK^27(=V10?i)gc zYY+Y-v`fEmG%*GVT5s_Mx@wd*Qb|driZl2KDjPZ=LoP`ibVPRi=XIK@y~Zj%WHo

M)a4htnI^v}B5{6Ct9|@lVJ$-OKb%a62Mcm58=R-MDg7TK?nl{sKvcc`P9me*TkIk32 zv9xvcVXm@n&rGG0^ION%{gk(oN~7w7_R9MZEGs{@*zpa2YX1jYU|BswF!DXx5ij&-Qjb+KsZy6U4tG5LxcX2n^Ao7xNy46%!; zup8E~+7+E-MRk9OZ$PtUwNm9B%b}ovUES^!3+#3F8(1fVT|Ufc-q2s6J2Qm+>1(u0 z0D(V@k|XAVlCF;1PoFidU9<-Lh+K<8pnU0#p`Cy#Y7-_$%b(hC^fh?rIiD4&-O(l8 zCUEA>l~ne=OMqG}53vLT>GS$}Rhbds=z{CSK0-#yk05_dWCqV_t1o?8Z7}Tu7w}h# zPP(G}YuCFaDz{j+&0-j3&?vt{QVX2v&f}p9-&kJ~f%5>cRoI?Zl%F>sZS@X1(3I4r z!(2oS?JAoHANr~SJcs~$pe#ss$}R87?YJ9F%55<1f_Bnq-L=BB?4#`VZ8UAz>Po$z z#%Nnmt66^nKQRy4B8zQ=VrHrld*%}OMMMZ2yM88R>-iKi@=~V+7n&%;I&KloResK) z)O;1+=V8KrCRnd;CoKbFn*r>~d;cj;<%ogc5W|oa?b8yi9iddXVAZQbknJPqpt{w7 z>vdmXT2%k(so7Hy%sehX5)>apR{3f&hsLx`#hQOKPc6_F5>)t+@;)j~Raz&P$3uZC z0{miV^ssRm7hI@61_$VX6U8JTa{&YX`_v4P4}u5=NRBQRT<)jD-Mc=;BrS00&$^C$F^=xA~Q# zf6^#5T96t=L%E~da$3zmEIXP420|SjzXl&gc}O~b&p_@Y#mimWc9lpLydgtxpEnyr zO(yI^1jA@8zIZ89rFK2QBcpd#6kb9e5+i>({+HM)*cIhyn0{=g&FOOra&>riJY_~& z$Xvcch10bZ3T*_EkOl0gF|!m~+OYS+7)#)(LyH6q=&MgPkmT%XwU;gKQMyN%FmjOJ zC|)ohty@Ry@Njer_&pMdqvvSy=!^@rb>Zf-p;FwB4pQNsqWqKY0SF(UhGk_H`_Lh2|9Xq z;X7b26j6OB9T9b*yDC9I&V(|M-8Y|@sEjb=Gi1weJT~oBc#sBLSc>q29@Q1h+zO9W zVYyttdZ8ObA2cz&g$kc`8DHq89w&d@(eD*%5KuEmvzj~$u6mYU$Rj<15dv=jfdO0> zul;lHRixP&Bf%eh5vz}!zhOi4P}cu4sQ~RCI#7CJi6{_;+a5gGK1vljY!0LK;(t=H z;l8n<66HkOj4qExrzR-Q0EO~DhrrMzEkwFaZ09KCrwuVMG5`$Ln>__UA-8`(#J#ac zzsB_y28@9^es-V+uH=QVkGG=xcwz%wf+2bBz(*{AxnG^LmdVvqRxQ+hJpC5E4Jtj! zi5ah=w~13$xr!Q}PZM1B+-RF4?!9f4<9#AXEt=B&XiPjeUvA#pq3&dLpb!)=-hfHh z<^zB|?u!b9hyJVN2|F(asH-pwq;;k*~Iin z5=E?tIz56Q*pu%NZB$y#gW{vH%mWSH4vox|aM*eu$RRLc9H`EnQJ97khF39B_8|*L zDilLCA8TEs&%`?k(oO#isL(dzI|Q|FG?23EXlFN3p!!{P4R?Z~d_jNrLWh+Q`@$XU zqy=s#LqeSW5JTZ-j|Z56dJvz}4mttK@UZQw6b!IU06^*Q4#i zF+J#7+bzOQ(Ifuf`nn(c}vIPJCX4zqVqc-k$QsQMHt2mb_7 zcnI$7kR98V^-7QIC{TYo(rwQAcePQ1ce(3)3DDQ2ky8QGXfc#YYD{A7n?_&I;xL8#dw`*L&*^O%(7 zm^#GngNC801RYz?Df-W2_2ubTJ_z?Fi&6LY)LQl#(rL6(vFHP+r8Igbp$=_hs_iW% z1A?p6nqv>h(+WJ~%iMG=M^GZbI?wc?TF8I^?FkqZQZFF^^LXeYH)vH?NLDuO%}mvQ zPxW@tuo>0a%DjKhJ4bu4!_K1^H;T0{RIF?(uvfY!2T3(#YpGFDv`s5Fsw|+&K?PaE z>>bis>DS=HaJD17D<|S$afmMqHgEu_>%X2OX24}~K}Rv0_uhbEuhpAhrzs}m z9&23ZDqQIW17*{VOFLP(f-riL7zkza?vWafs$}mJH9r?w0k5cm)*=zR&EP;cL{@^2Y06|il6Bz1!*579JWI2xT3HQ4SQpWg4G|MgD(i_aF_fpRct6r;KCJrU^xYE;s?4 z$P50aAi37^k@GuR5<0vNt_gpJjgDy`yWhutsde}gK70dKKo4^X=KfX?Lw!gSn+2dA z9DUD}qHa+(zc!!7o*_u0$DuXdnGh;nbcXjEBu0KNpGWgAg%s}L<*GeUcN--d)4vrr zqLhC@fsn@el?m2BK*htKfM4;nWKj)BpBxQ5LIKIn-69>_PzTV3;ye5T>ooQS$7H6b zinnP`??}Zq-F7p}c11)kpwnK8={L0OdWZLAu!WD7q%=zizl=Uz3SsRzP(ZM4hZX?JU}(^GNGKhIFNlAV z=P>ijhx9Ni6nX81ToWthut?lPH(k*XoO$Dfqsj`_P#wthj$X^n4ozmkPWugPoQ8M zWI2iWoYywgaTF-}P<^=e41%mq(k_3A#uSkEpx?Ztp?QubTj1Q)9X^NgGciwc5(Yjx zRj2MMDuM4tKn+y|jl#(NAbml3YEibOg_Q;Os`Vu~;1c zJL_P@M;ByL zJQOiA_h(iiIrTERj$o0NP19#`Qd6x0D@72=C>WRc!US(&PIK*ZSS>u zwAiQ`@P4$~|NHMng1TcvIegyODWIsUm$Bb9LbAMbAW8q{34Cc*Q&Hj-|DCA)Sds0+EQ`0s<{RwW> z4j#8tQ6>^9JW@~sm=J$~vyPCU$`gh?`kb6hJJUkjQILmMFyzY2IALgf>Nx6QfJ&4~ z4)jL*9<%OR0jdyAZZGIS_{Q4N>S9~t`^4#pT_7LZ1Ft-(NI_dUL)c(5Yt(BN&fv-6=(20O_=PI#ea(lkr_J1+#MLPGgw z@6}ZRU4RRDqde6Z>jtVPab(f}Mj3PpZ;Rk2vC0li=&=yVkr@RR0r9}L_CDs=P^0Xz zn6?6sSXtNNaMc+1VK}8nfh@9PqZR}Hb8?M{;>e2RV2FQo!66I0-26^2jiXrH;A}8H znIQDsRH7LU1L)X_-%1})3#k-2$(0VCk~&I>X`m~5z*}nRhFo#A)tB%JPMuY@RC=U> zeHmnqEmZ!#rb}t@=5OXu@9((-rIQ%UX(ci&zy!b6&D2k(L&>1sX7V?wD;+=w#(G8g z*z%7a`S*Y9lo$e-X>9gy@!@K=L^LEUt@43& zCJ|PjUjhER{gK`Xu`*n_Lq~{r=%iJCxh7!sRT>fQwV0@h28=BKcNZ&2RSqZA6WtG+8i7*(KIuj`MeC{SbK;8=hL&e zlsbzdDoywu*uG$F?Kyurv7~N0@&QDl)#M84pu}q=rr&7qat68>?PIcpmuB z?c#TPY@t&-sAKhN{4f!GN&y48tB7!XrgAIP z6k~peY%uWVSRtuFS7Jzdyf#$|oiU1zj$|^ZtwyaZ`*}{xijQ7TcoHO+y!dbR9DINL zKms~XZ{+4H_)-eEpL?)8qP6@dUT>7TL&gMo|BJh{bU2KL+f1h&HO@*>Ct|~u4z*&v z+KeCwG|X~olx}W2&kHpDuu``r_`SAlf{6bTIjie5`s||4U6E1SU5yzfXP-vGlx?%X zcB=711-c}YwhtE=GD)zDuf!L-t{i`>Gl{)aKt=`7QHR_iBm+Zl?8>2dplOYeO<9cJ2o@3rfzZAFb0Pd zd-S*g~Y$qzS~ln{G^!P4sOu@pLiR{QRi0m&AcJ5<|7 zHtyz!m+q7R4smy3p{>HrH+mR#Mk)u_4Z6|@(C;vn9sLTyL-!SUP@#W1+G;R*SiLU6 z-QG1D1_pOtH3uUkP9s%H2e7Em>dc@k-Vy$BRHW9u`f1Y!h`{~-x_i*xG(HVRvGgF* z!3Ymgpb7=j0*4Sl`3OE9HB$x^Wr=^Atf3_M0EaD$p~(|ohpiJ};k_!VCPhVot3Wkl zawv9dGb)UDT(dzJQkZ|JA1RO;auC%RAH*D+u~GP;XYWFqwwFvViPh9;Ff>vH!>cK% z$0@o>Y3cz+fx1V5%26&*Hy!UWrPrx&)>uAkYXF05|4Sf21xkv^$UQDOeXAJlJrzUS zEFC+vJXW>-{&q7yp>~-(=E3p6h*6gFeN4gmZtMb$x?N8FjHiDN0Xj|h^=|qz8sVZ3 z2lygBxzYep*fW3YA*t1q{*t^L#yHz5N0dgLzO7KBPXTX3XC8l||XQT`4UeNJlZz&`+S+ zJjxXfg$QuSo*wb8UvagKk+(zAhW}<1vEBK~4Ibsb_ACKwQ&FEcXbM@CKz1%|duk-|i^ zBhFTM108>OBJc3iqqTZMF6&cGzqO`*x7>!gEje{sI~+ZujJ5k}S~?3Y;yHiAXaPM+ z`qL3dHw^+v&b3vX)EvAWzn2|)pzNl{LXN{W(VAf&Ai7E~wKELNO|DM>&!5z+J&_5` z?jO-mtKKB|lpUUeA&?022b`4FVuQ%dvYWL}P{4oL9X^PG(~$asN&HVn5Bo6PT2V8* zmPGc-{}C1<1%IBolRe7;?FyJ`eLfuu;bV0Wqi3~JkO-htBecumT5DD@T1by>Wr51eg_#JXk zckQZ}^O7kg`Y5k;*px&Ku||KOj_c?uGzx#Q3MbQv8{X$&P&oO>PUnc!?%IEKWF2%& zq2NM?YHz2}s>ZVHiaWI-;7n)hg^{(Qf>)op>Tdq|}d%wT4Abuwi{@X8q@`~g(@ zw6DZHbz}`U(rsW~3j|1x%d&<)&XK1dgj0zaik5%qA~nSLi<(jOxGRm%(~){o^(l**={urTnke_Z z58N6>=E2g2>t&&Iypd$TVfH|wzxe&}R{}$U#9*pU_8&aoflt8c6&k;~(e{eESZp&! z@|aKvAue&pb`T_j`{{{=NYhZkWS{r?Yj?^7C~}kw&|MwaeX#Qi#G(7ya9V$?bv`$( zlHh$f3T0|T?wezwfrTzvilFwSR1`={kSR9UKy?$^f!>BbqP`RF(N$nWdV_NeG1(KvVKpEFF9Q zL}4WQfQ>&QX=XV3_>g0`74HHoHu{6bjva@4mPO> zjYtouD*41^R`Gs`v23w3q$`_;B%l$6-ogI{;X)8KRJrxq2k9yRB>lNdXJA*we?=ia z5zFv=hw50LP=Hf#mi?o$fm7C^viOYFXAo8KA0?)}nPX$&*nJPS~Dd9>pW_v(h2iZv`;Emv8XUtn~Fd z9lmIxnIrrIFJMF7KI=CdSfF0fhYdwf_sFk0q_xcUp|F2qo%fBgJ&$=U7Old3PYd`} zc2RT1I}H8Ku8ZWRO8u2MZ@$L>kObN6?%OXHi}HC|&Qs3wX?uUEz|h%j*)2ltlZ5zq zsQjJlEj)Hn;+-!Kgh@aUO!jJ5?{bJFnrd*#vJpOjBo~Tw6TxvNS|Xx)9pdiBsRxF! zRg6MDe{-@P^B$ojVzMDprq3|F-66hIYSx5O^(WqdfI?y?+z8U!M>Q4B`${ZEzQ0yG zP!&shi?TW~6Lo)vbRq~=Azk`E%1IoX6s|;K_LJB}fzuiCiTNP1To?$x^}d*UJ7fY= z90KX>#6arYVkNmrya=1IK!ZY((klb-@yjkhM#g^_Tp_kX(M@mx=`05w3$zi*bX!@*aS@Z%GI=~3PweigWpm@H7E z60!1>TDW|>h#0^YNOnkSU~hjOO;A1F(B5p1*^WGjt_aLE~ix$dKxw} zhvQe|sLW}jDiW8qMh<;Rm|<+6+QQkKY0_}?J_F3{`zua!CCz1S9S95K`IB~rNfU?g z`8`_V=HPpA^x$0qTe7`>t66Q0oA%SXK_GCPr%f|)(>Py$Gawn6R{dk%H#apIfFMng zTT-Hs@RH!A>LEG>dI5baE42?Qk=vYZJ*dHB1Id!ZmlmI6RRy8T+ z>zKC3Ks+eT=U7^xm7REg$-OcfN9?Q9ol-S4L;)zU08hkB{vjo^5wVE2Z(zwPzi6b` zreOpdfbwa7^V*Hl;TP+swCRD?667M)mx6Li1Q6LAdaw6}Xc>(irPK(J=GzPAi> zAdk6}Rr*~d*!=I!QrmqddSIuo4RR{6kLv|oK>lV!$}8!oZ^_`QRb=ir92YHLhdc}C z`c&!q>I=2@N{xEjLr%=fJ(SH5*Wvbp1ON>OQGSen%#>dzE3Pcnb=3&72`az9h}dKE zY7Ig|HkcU49Mt#ugxX0m9My}$sM?-SmWX{L9#2$Q9~Lvb z;Ta4FcF_y9CN^c>>kQBkO_h_1-f{RN@9&jep_mvP6bF4=Jxm~{vH=F;uIM zE!!QlVdLp-vq_G*Boc?dm~FblxmVR>b3OKdC@?mYeW5dsm&@ti@P%f1|Fm+ZV=qdJ z>ZxGt0RpGo_Xw1?Za-fYUfd$_aInUNWkLs!po-}#Z~OJ?HmCa+Zt7e-*Wl-FtP9HKr`xvMABB+~Cwe@7;HV5Lifm zwn|fHj9d3@b1D2J(DZ5$KmbqSp#&CF36IwudcpZbo$f0iis$eBsDZ;b{GR-o*T(A9 zaT#*jiu(Qm13yB>1yBGxBx*DSg-6e%BgG%^YwCfyEfF*oNNz2HrCXs=WE9En1Y36E zfPrMiLla{;-z*vrQD!w+b)COP0J2km=g;0MtZDV45H83e5<~^$%rR;&21lG=uxiFG z0Z!b;3kkuCoD6E0s;emTx2ctUXFXA)X^+}7H3X7UEw^aSx$ov;Rig!6K3V;h8U4S2hu(bUjTJh z3DX+J-d2j~=Z+Mi1YI&4?^~h`Qs09#s{d*4vDpZEjNN}9pin)w)rVAn2o7Lfgpg!@ zVj>qOadI!uRViTJK+0R#c)cb`RtA)i_By67S{v6s&wmx|& zwb1rphU*y^nNVS%wc`5l4_Z%XFvZ!1AEo1mw+j|fk)pDvi>4}eE*kuNbj(&rJxr$fph(C=Yo5MzZ=1uS*J%Z0PKJkwzkxv6POqY<`N7k46)Ly2pXk#eWz>fO2x+!KBIuN(W;Zn0eJwW3C5A}6+AFNq2t9DsTF?z?DFgS==kMY zoXy;M&y=nD5Lw87O;eH;X{vYh)$c_Ivl!s-Nl&zABn&bN0c@em*_2TTLp23mmO8Fh zk~wuF{ccnM4WH@K_}W(Lf&_PHMge`(s2|%8oP;6zkp_+E(+Ciw%x7z*=n z#t6F|7r25W_=G0yMN?*irm%Vxd>H1%Sjc6hL<}7eQ)b(!s>BFB!KTtrA+Cu$( z_;mV#LbsQLc)z6vDHGO)vVOEF9r6bpF?(V=SAR+q4>ft)#{0wLs=LDN)9PY*N$(qZ zWE#*w{uFS!ujRMZ>Vs{xX|ea`EjAobZlQ&1e7Ug_^#f^;o!&q~mrZhkkch64F}9+I zSp)KaghpQBk%655r7uKGiOW+p^oB?(FAx>vF>MF9I(edP>IHlu?a;~P=A0o{1zr{wf+!8bJx4(rNqT|60FXPxMn8AbP!-x>qvsuD zpj}A1M(;q%L^vt)jl!D1A;mdLjo^Xxs{;goz~QIDFp6FPS{t`R)}>DIAKoU~LqLZ? zK-0glMxS@sQz`~9N2w|~Ne{#jGjLHTc0@nWCxnwD9Bf5@PCN>K z5uC}M0ib@8L)TD&gO}w)T@fff-vN82PHqO`5(F~v&PBfQ8>v$-&K|F6*$yW8p0Th1 zOxzDr9fiJ7(pCy`GwFrE0z^lkN(1l+u{#9XXk^7moA!mFtj)Fuys<&GPn-ZCS@sk< zc$qfSOH{o2N`)%bzKK!R5wpor9+nS(+rw%~ja=!Y0H}z+Q}l@`hwum`SL6yne54?^ zQOTN=w6M14P4z$e7R^l@9v9gsYR+*!LPZBe(fwH5j*@>;NtSPT)etf53VG&5JLDQ2 z6~}Zy09Kd}dM2SRg??`iV`I!k7ZLWTmA`p9h)T!LCE~9%6{8@vV}Ah<{f-QO+vrqe zq4%8vi+(EYNxMh(Bb_H^qy=}bR+_jegD9B2`kddB3Uma!fHXvCoAlKldXCDT&EN$x9*L2BKjj^L#(&;(3G{eP-p`DsMD z**etM%I-ep4}_lN_hSgiBHW>Wk0En_A>Z}S4_3k|!tO9Rqq~Iw&#*p&Y43e%ip|GJ zfGq~}&!256&`_e|CYWX@yI#1^4>~V#FXV6>e-Rq6u(V6KLu0|PKI!ZweN@w+D03v7 zO%8Ld1%Hc#3ivX3Jx@qf;WQ&n9R=0tjR=(+naULc2fdEG)CUTxz&6-_bx;+d>zXX6 zklcI93I{}QK+)bL>$$FOgIw!r@lM(wKBCa!S@=jqP&h^<)_c+Tq%=we;x|}y;3l+;#oW)VC7G^ zBNF)y0~2OL2S#}GZpO>s>i*auZQZ9=3$?2$4Ix|ik5T{*nBKEB9aQqZ%_J%`{_jvq zv2%ZA*WlU@^(#SpVjsILQ|3vM)9Go+S*2Mr2Jau7>H(*5`}|dZC&U^}9>3p|G{I7K z65=Am;zgeZCZH1q%~*dXIjfa4@R#kfhtOJ4A5bVC`e6VO7b0{WtA66|zl< z&c>Zao5-5j30Z-Pfezde%m0aAN%m8L!<4*HHt+ETtbg!-CvGWCMrGl+jjN2PRKuu= zh&sO>mum=*zM{+k8)-=%*npY>9!Nvi-n1n|fOh(>Zli#@;`R)kg$J|qxLRGS1KzwE z%}IQoxgOoodvHLv9p`anA^Ie@#6Zph2K!Fpr%oyq4X(TA1(uCw*iS-Bw{yV6Mm=rB zURbCE6dXN&DFP(^I?)B93I|Ao7fWHFQF4N>?gH90hp_PSoB^pqP{b=%k06dbN5uz35ZL@LSK~@vK zT0~v|&np1zGfW&^Mo|-j=1aMc8l}FYQe-TwP8tb7f(;(Gl8~esFi9o^cQM)sFrP_( z5%CWMfKn)q6{t{2cW{Cuc88ZCngq@Sg8>2Ezu3O)0#T}yqy1ok-=8QtkC|1Ftfaas zSK|^0RPMm)C=nWXD!Y2J#InGD0iAUinB_)TRA`+KDaj_)@K#bH$-1a@6K7zS zB00wUiom9VEZg}17vT|ndrh~`^T7_tVWlY zFjiS_mz2+RyvV3@{^vQklei=;JuFM|o8&X{3Hc7B9YlKs!0NMqKmv8f{cZ^b{JkPy z!l*O%xxwCjxq%ipGyiY)`)k^Nqt-8GQx5@GjW=QEUgFS*HrRbijZ`O2PPb-;=zFcCxmGtR|$K~6!+pI8n6a` zC`Ef*NCxK7^~qAaGfV)-D2d_}a&Zc{kJDm4)~UfLwweb@v9J=dX1=7DbwXXh#NXPg zD;)kH1cB2mqPaAWd6RX2M#Oj&a8@!RLuKJa3)O$8OY~KD(ca9T{4g`@I)UjL-qBJ) ze)|n#OK*pM&98_>%XD3wH?H)J&cIMB`=*=~qhT7Lr||ieXeQ-R)wU5ve>+rgY?&Ju z5tP;%=->U=QD@|9p%nwN^fPX305n3w-&(20kq{^#O3_J&A%bOv~ zKnL;&da4XM!XxueSX~Qs^(#~kITep{3(6zu^k9I#6kK_Vv^<^G_H)&@IH z-Jc7(*S@Ow9IokqbMwLSx8lpF>Nc533697L@&&)2JQdlfyWinzD1oPhAKA-_KNaOQ zy8<56XbggoW+^1_PZl{X|N^K)A=C<7g?w!%N|A zU(YfC*eB;-##Y#1$yA4nI*UQ9#d{m4iP6u0&vczhEd)5rH00sON?TpFrADw*-#0X)O9|TtUxwi7vySDZ!i(k6&Q}f z8sbrZ1UgIw{D=X{ob8FBQ0>Tnqz~(qXF<5fCLn>N;6=$)bm5|QaRbmNQfi=qM`%Gl zS}Gn7m&x3HRFE3}v@6NJgn(esmwj@^DMIToSClPCLaR&HP|qm6UzlW9sfYSW0Xc!m zBK(elj^&YcMpauh!h$@W(DBJ6W0259={L!LQEmuV0R$_3mY|R%iUFka)XATIx~xTY zAm>ClkDoln5_ujX>H?2M@_vee_6>PJE)cEMqSU~c4%Vm98Aqgz`H|5;n0h<}?MP&y<8stTjE8Pj!9K}qmLatuxayrGRJ>WW3I+wb+Sa4&yU>h( zOyBZ!rZc^#cBPOYaxOdUs5f0`qa~snR8aRV%F|?mfx9anj$a%d5I~*XIT@wu^gi^} zX{TkxC@T0LWjy2(06tvgW2Ia0&jKP=mvfn*Aa>kEE_?kxk|CAWw9d`0*?*!Ri-E>t zL>kV~f&XF%er&ny7MP$9_`no1Kqs<)_V^{zVxOJzjH(QiYVgpVW(`L}9oH zxXI&bHJV29``vu55;U3uJ{V0BaL26%<{;@+lmY;_9L9@MVE6Cv)NAI{I1bASU+g`%-YY;5&#<{tjpMfF zaG8++xmk22%8!0QF0)D0zi$G!v6@s+3_m(wG@XOM_$>xdh=I+k#fY>@5#=I$f{xp!$8O1fc zyQT|dQt9H%b+S-AFwJDe8y}y#N+i6jY?kFIiz&#?dwYOKGYW+S1)b@C@0O!gPoQHU zsK^R2L%oC$+k(rG0_(aF+5K>Ui;cNq6)2#A!mplWjHM8)-k1`<2D(Od(J4|rz2lGn zB5xDv15hJ&RbrKSH)gK9im$*3;8PX=9d%{c`;cCmt=|n!NkBHdnd518EmmbWbXzgj zkXvjWNe0E_JA8c_t(x(F|B8ScMPg^+-;=rItiD4%CM%#dFc!2E0Yi^%2m7dI{rW?~AQ3?WxtnHxAEbqAoPu_h=+dW zM264M{0%lWBg(mdzd756Vn?F0VAu40>3^V(;o`iJQ34(w8E_o$6cLx!x`+(U09`+V z$9A^{j)X;1A{7M@UI(iHei0Y?#(cIyhhUoDtv_7SX*2#juA~D*yg^n{981QOB9MS1 zY0<>!z@~tLY1x#I$U|xfAmwwLIIXjH#U*BX)xXE&bzGi*XTWyX(x@&{pxOZ?TNO2w zc-S1pJ2m9Ro6F0k(iZhcc5qL(cnIzEp2pBZ7SF{{md2-18s%#njj}?fDAgfE8nCON z1WUez&)-E(f6#!s+opVymt3j~ZZe^ZrF+$%D=Q1ofNlG~4By|KRNA*f!s>K{M41@f zf|IR*ox@9ilc*bdR|unakzI+g;8S?JGPghHa6?$A%g~+N4mzW4o>MfEB9BQI_fBW7 z9Y|HH6HgPo+bMY5GkIl`Km1QTvFn=I6Kh@if&97;zFVzy<63Yv(@Hl&TiZ8+B=R<3 zoCls!vS8w0Bf7e%9;B%H@+qsCM<`LUA<2q=wM%S3*Y{E8Tryt`lgAJ|bDO9H zeyIWzj`uH75bX`iW&Z+9)lPybQq}f;byf=9HSfFI_d#DEl=aXVhs-exM7nJqJ0MVb z0D;2SNaEGh9=|xQ!UUN7#>45%A`%|x*OYW@v{^7fqB}kRh$-L=PkZZGKwa3YJ1xK_ zz?i^)LF(DV@Q~xtsAQ`8Oo`U~B4@-QW!etKfAXq%bFjwpA_Y3tneY;WN=v%GgkYoS z99cPvqU|b0B8Agzaypn8TX0q@humrg3>Sg3c<#b&2%5A}&o-yfW=nL8ZLL0dXvKhk z#()6CgdQo>hah{K8-B*44s-ZLFNmYn)g&Sv@KNtVLW}Ejl^RHB;VT7eIr_!SJtebS z(vMb`M%phaJlC)laHAjU%xPH69@UWVC_3t2{5E@;F#Iy|eCpKzBLW6%Xh}4R%)|r_ zs3eMfO0HLz{+hs5GOsyq%Gc|fkGf@lj6$~m5?vGnI1*}sABsUaNR2f6W7AukM0Mp) z7%IfWeHDQ($O02_12Ke{l95IP6az@AVF|t}@M}3!nJhscI zNrGj1;;cw7;$yop8lXUq5I_3*S2wW{$Sqzbq2Z2EWyH@CZ}4@U_Oogz5@Ig=ASzc+ zzq$Dmzb^wdzx`5zt7{ny7$ZKVq6Zl%6*5n_xnyMH=nE>t{~xK0RyVb{-e|z z2mxUbJ-NDDxkze3S|CeNKu|t^A4gc)*Qxax>G?Us`kHLM!+3}WVp*HS*rmpKH6RXn zWRcg&kf|$9!(n++pHmT?{4yGmQCCH8kFZg%YiU-D!svuT0E3B+|HKmVf-b-3tKB3n ze*&pFTD$F!W)gU>ELvc7{!j|! zGAgyo6>6xFF2!EzgpooN4ulJ-i!Uh0sszgO6ZpmYRGY^*5bpwq0!pL_JppX@=n@^G zLky}}1|)Xf11s}$CO_vyw2=t8uw@^a5JG;}ijA>AG0hxSOTre#ey=ch4^zVZa;N>v zV(mBsQFLT&%vJFsshB%|-TU<_1f3Q6=Xei{aDFmsUPwKtLlneX;C>sCrW0SJj{yw| zM=ADKcimD$@-Pn7Me{@}7W28r0DZ{DLQn$E>vv;oB#Q*21cnSn_`nTOf&q4>dKQTk zO^Ajt6`jVOYW&!?{<@1EdsRrQ&%keLTh2U0fFN1`tcZ3LPLtGsndJ7L{U?SnWJsn! z`)){2Kg6H@pvZy;77*8w0J1E(Qvo{gcA&^L^oLfo_FIO+01>BWG=xQJr|x`jMG?}O zWBp{Bg!%ZoIh5lM$*#}McoxnztAEFP_7nc{iqoRqR9`P40<;j)=Cp%5FmOo$MwhP? zop+Bx8g*3)JWn`(snGG~BLEx5KWSXv;&-w>wNKCg6dsNj`B{xJOyI$w^a3G3+Jrg~ z`lrkC@Pe>F)-AN-NvbxBAN^XRkQ%6VK9R^JL8PEVfKYK)eE6>NKX=Y{Suq!?ma>dg z4!{wHDDS~=dic)YUS$KUe!&_j{M8>)wF{*>q1{wv^Q(`4dxcVsi6rz+`x`_hPI2vK zsbA0l?0{Gyxm^=SXqV>IDOo;}P!C%@l#hC&ky_H4Xc7yd>Bfyf$YrUme$$Eih9m&P ze8kKUyw|KbG*idYhc>PV96V&+H0?xzQvo;p>FJ%Qd@?6JKsV${@dzlop%aM$A|P@E zTAyC{BE~3xul@1{2#N)6b(*~7n*c7_2=FZf=-NssxG*LNAtE4fy2J%__N2ePa1_UI zVNHFPFa0*^fLx?7+LZ$*^-${wh#ZcWk<9glhpmV1Og=7$mzYT`I_0i5G@KWd5=!@9=F^5Q7n3M?#XKxYQX~| z8U8b!6+kNUxRhuf&7KCCn(0vnGy?O|W1^}wbw^3_>RzrA(rwmVV)2QJCIp<<9AyUG`@5bulo-q!aPy`~P zmN-ajy=X?SP(IFMoKOqgKLAte0FnY<%QumOj*3hwp{dgM!S&8atq?8qfjBvTL|w&6 zoUuSa>%@N{3IaS+01iSR^X>MI>%S!hRM&w6(i$7$Z;%n9o%nvr-@JaEgJqDm%43?X)lAae)HiQjky#qw_^z6(Ii*XwEb)#e-9J zjB!pdsakMUpXgDxB&2W?m}3^$7>4hYK-Xgn5c4mpAlfQ00a%C zo`+P=A7zJ|6gSy?pn?7M_Q|cSOAudE@a!5<1Ac)Xa>O;>3+Evek0`Kvnn~UxJO4S3fqIs8&+-5mdz-s&!i_sTf zm^}FY48Yd}J=#rR>gu~{vVadxp=REIx_!_jmnt0s;@wK}hugv*PRY`{j7Sc^BKvjeCzFbE^K!T3pO;)^n%rqvaCi z(vVqRy`@IuoB2dvt6`ph_*P70uNc^1GReKqK@0{^_Ew1;4d!VyFf*u1Y5PwX91t@r z&Iu^{xfGz0CurD2Oa0OO&clQpyc`{)-vqCJ*5C*bhSCaBuQ3(Agb24{r*h|Hj5c4& zA>Gd7^Z3~yd;kq@CvL{&QEvIl1aeG}OJGF%`&w-iQt)4mye0K!4Cvg_i8Kg+nB^Zm0{Co@sO7EL2S>qktvy_-laz9g{<2 zi@j7f_(v%ih|^8dwzw)c)1xwxDYwgi2RlDQfX4uEw&5%FR9I~VGV>fbqsYV{2L?$j zz#wtZSf|-Ee^CpQWKnnGF4R|z&|cx+Av;99q7t+~(4ncY`yXi@2pm989rHFs9z=cO z04;_Q^pe&DbcCv-9cAcRfP!H>Jn_UNrnzBSX}2Rq(e=Px#)}*qFoE^_avbn~2kS-V zec+6Az8zd0#E74&JkbaUwQh9n6ZS8Vq2diblYibysgFf!3Z*Y^D*&vJW`Y{7NPYn3 zD{^ED%Cp;4&{7j+xbPJYFn~D1a*R=X)JL|;f9Myh3a48T<;Z`{AH}I#?A1UHkruDT zNgzyY{BUu5nT^bj!lnyf929YXu(b+cF|60yqMu8*W`i*>f+*$iB^s~A=zJP2(zJvd zVgW0AjUIIfho9lN0C+C<4YCB1JR~5zc?v)PV+6fM(~qZpu*21X8_uJ&9DY^|L)Zl2 z!wbgygdL6(4r;vWF{S;-7g4VPWIammHS|d2>p(Qz*$RAcpmFW{Q2Zf(ST9rw723=< zk{}f!nc0Wovp$3u4ufTMR63Q&h}ZHKoK3M0oW95UHcsz4BFk+boRJl5pf_!FJaUa5 zp9MTR;w3i0KM-!*D3OwUI=GPs6qS;s*mU-<|9pErc696dGGwYIMQ%& z`x7Su!8`Ag1H&f~c3-z>D#lJYiQ)%Ba(dr6V03u8X3U~c%A4kt3RDW4XW@0iQ96{# z0T;uBPz(vOBZOYs?1+;EOln2*hWIb{R^% zJivcSCa+&!KvxONHShV(UdvyJkM=^ywO7k}r4E>q3Tdw&TB8&K`P}(^_>5-TY{a#l z-ltBjsr9X4))94bYn-1OYkvHI5#INYKMaZsWeC+5L}GlR3{ju1rXg*|e^wka;25_ujAvLtNRw(h`~*{ z*J9vs;CloGY|B1!fFq?9?V(j3IU8c9m??-KM$&M2`CH0t|UYwm6>JLhsxk&cHX~eTPLir4ag+7(3NL@SN{!vVzucmxN~7g5AAMR2h8jMW$(e z<}?T>T#URzkNg>8BtZV?A1+ID$E>?cq_1_Mh9o$Dyx|;0pZ^KcKdn9c$H}>wD!i|< zA%y}Yup6j^UNf~7W>EiA)d=+$0DL}&uYM+VjS4A}k?E;)V+Q5PDh7ghOGk$d!mJY^ z1Kb?MNy#?RC%wkon{lZi6i6r+f!_97fS^u%B;j{tP75LK+xRBkvI0~->ILS7-U4IK z6a1)u^^!Pn2wrJ%NfKWcd{yoW@=3S-o%zG@bD{-)Uwp(%xTcaNsSw!}fG=9CwA{G? zsRJkg9VHLU*py9xdnSGj!&U$TRt|62s0U#JKyKIrjE8>eXm!XcRU+fbJt+B9q84Rn zvgygHJ7`9aQIcdrOHpJ0K(%3u4w*Vl00iZKWnOj8A@V?iRH6IiwFH7oZE}=SV>^k= z(PG7uhzdOx^RbC=X zlk>_!L5aK%@fYT=g#U_!16}j!*#QpwvMIQ+#2?4M>sA^q+ED)(oH&j_#XCyhZPlTekjbsTQFJ}WdR&E>yM4bTCZW5R-4Mq>~RFNMVnCL(M{NYspI;Y z@cidD{gsWL`ki|pY_SHY1B0sxUymq#nxz&i;#*8)={{fS&mzWYKI~{$Al!35!i%gC zcIGlvi2T&aSQpAq#35Sl3Pm0$=55dnfMmzbcT%x`Wl8Pmgn}NL72gJY7vTs(!ahum=oN`6H)he%w7uRH+Tuh(#d0Zs>pf%-TBz|X zgmG?A5BHUi#`xZhh-tSm4X3#Xuz&&A`tw)Jq;)Upr4dwKPj?alX}Gbk#b+e?DhS5k zZg*&+R?{6g^bBC2TofQRyOf}cuJtt;#hLEoP#YNmndd3Du@KP2_LHjs3wIyH?jLfC zaN@Q<*E|-{8>~}5fLY9cR4sY&M*sPsU!$Xmu#1OOGrgFGvbc3ApDm*-7R$5*4X4Tc zYBBH)I{0~#qyl~CT6x#a>#iGL;$f|QbR1McGKdTWX`=oqKJRg!oXLS zPh)`(8VY@cDgPB+&k8lInIHkesCOf2P+h{b;0mi2$?W2}UQ zyiP{PD?Xw9REo6;x-{I@SVagPC}o>kPxP%yGov6AGv{eziFrf%hGj$mC8HxMt(OqY zyh4roQRszNBts+SJbP`XcwQ$>Pr|HqbD8-qYPLWF3I0TX!QwpxTt03C#r7kBJ=jWk zbeYzG_aqTNYV=&*^Ae(7iO)qSV;zQvsk+}WvkI;>;($NT$zG6B2AENa@p*L^)z0Qz zfJOuk%>{=JD)00}dd-odfi)Zfr4^lQ%A!tFrChtgQH)=%447N=*8u0Re$B+r?Ivav z!DhnjDC{0+r9e#s(oq%9ggfz5zRs1X;ohhcF(4;+;6)dEmwSnh zO0`OPVQ|KxK}Gcxarn(iBv(EikOc@R=nlt=#A3AQ+65b267Q?HQ@3W* z?3~GO|55{`lM#v@Xb1+>($a-qRB}zf9M2-0D)e)IHQr)@I^Z&twWCA7-TJ)I!~{T% z{~~gM`K2nR_9twp#|(G!`yP#kIHH$D zgRMpaE3$$saSUH{Cf{Ip2;m8r?q-Y>Vg&)$#6<&BX`zCa>!};8OHiQ#CNuf?#T{vg z`eH{Q1uhAVxp$%?AR2H9@?zn!&&+>+`a}i0X~>gI5KY4k07OS}`=}=Q5nqg@4aa@@ zs&Ua!HZmQ8N{u?v7&-%U_KYHn?(731NR?h>P85}Z>P1SyEE}f`;b0`i`Z9NWb>&P& z)Vf9J#U@SQGXuciJWUfH(2+!2ulU3!%3=>BYEgWVK+n@sm!SqK9d~{0ca@cY^%}wV z{f8Dqna1%XWmne*TA;)LcTac2k@yrXs1F->Ndmq%7!ip@-Gm2{JW-sUL~@CiI0!P5 z%f&T2EGz+fUX3)I9}CoSU)EE{p?)o!M{Q5yWJstNZ5L$auDkXxa>A=U-D=X!DOa>+ zqS*l;49XewdY60*VgwVg>|m6C94x02HzQk?%1VB5zOGdCO|P#(w^xxE)M;KeUkNHF zPurLN$gSeb==*mDIg&*DBFV%GXFmicxG>vh1yDNB_Mlwrs*b_{k0_|!;z+=u*Ij4> zv4rqWRO@OuKlb*zImp;h^X)SMRxePZccyl2do6n>d9D?6(KjF4>`)4SfI8Oav;|kp zR@@&KZDA=jY#+1v_%tR$_5Is{goyRcbM%ph!u*ipV{r#xbrv}Aart7(10*r|5 zV5}id1;);HHb8d^{tLpm1^AkR`Aq+paN=3lr1t#Oq+Bg zC5{IfpnBI|233@n$t6O5Q!99%%#W`O6<*zjDVKUXQ^clY_*_R*leC&a7bxI0(PvSd znF)HYe#dPDO85!}@W)z|V+A?2Em0-`d%UQWa94{FLu?(m2z^#cMgog@G{ zjlC3JxW4UV9A(#kbiyy?xt5kru4ex4RqY}TZ$`qsS6g} z7MhckA=DV`@}mPR2pqvv9t&^J z+{GGMD!T%s03HlS>(bBO7CL>ss=YE0??@%rueArKcgIo9nCNHFFMo#T%VmKTB zZIhm%RqGOuu@J;s5deafyF;I^zkoY@AzBcbiQ;aEqJWfh5 z|LUaxBm^Je>QoJN4Hw)j0`&ka5j%cdxs0uTzgL5hR@P#79;pB!6c3Mp^r%)^!2^&ooL^Ab{_L4h2&BJa^?Qn`*`*KDL9t=3 z5}P_y^GXqbGgrk2>xwXdY=R{p=r;fWG?e#$%~U*Qj&|w=E~lv_U6c1|(XDS_VAXTuMkH>Y%++hmQ<70J7_rk?WNe!7@B$NU<75)hLVwL6mWN>2d@QE;u z;yTDj08_721O_sXu2fYX=Gx=c<^_FGk_5?*b|5}4r;3wUd<2(9&x6Xgj1m;1?rJgr3~4AV>{u05AI;EJ6%->;qZ4 zMo@fxN1;;B@XhH4>Ju%_+D;w9p93?)hjGqy6_O6FeGo;hQW7GM%BXY{9b~?3tB@oC zcRiQ&5o+o-Z)K4Yxm_)}e=oJp+7w?!AS<$wROZM$TpbzAW*UJ4|4x*+TL@l3NCdN>+PWTv>N1LsK-M^0uJ>xSpJ&z}71Sf8U+0;>=B#E%jrx(LQT3Ww)Q3rbE;z?!5uH+k z*+Bs;t?%-(!oHvu;ZmI?30NR+45&mZ&gQhF`UIIl+n_&I6K+n>4Y!klfBV@1a{vj3ospiQ(m-B| zmH~edt2xHd5%qNogsD*Oz!)g?N{*-b;gujqB);%^nw10IW5adM6leS72k8}kjG9QQ zKJ;5TrroFl@u#?=`}HU#jQs-f-CU|WpA%`g-9TF`fS3>D-s<>0@^%Q#e?Mt724JYo z4m|`y0o^kb>(L4plY2UaXnrwK=#fdn#e305x->Nid*XrM8YfBu)^`7zaaDGoh^w)6 zRhMl)#YL*jg5^|L9B=s05whmI$f|f1f(8`5b4LjsHoz!u;*m|u-*}3HmC67*ml0a2 z*1&boC@%fGSP9_6m?_ihtQ*b^+Xv2QaM%28&ZH7f*?NF&OYa~ z7rmQAG`pO36-LSIetD2pFj`-)qL4?15C9XvB*SF*qM&K?6T4Z~f6vdGg%#Undw2)@ z^UE&k`(UM-3#1jUX0N<)9N|(aX{sy8Ai(I}Te;?dF>=nIQo-~;(9I}cU^aEbf`IP0 z03mz;52n-Z9C21k`~s{ovJ;x9DGT+TOhDkuq9*1a4^iE5$jIsG36Z$~aj~UB01p-> zoJ**jypyvQNo?lqi7Mw`9dKuCUG(r zvowO-fy?3Jx>PuTfl9<@^yFfP#|ab6*=W_YZ8TLiVJ2l!f0~@zztt1pGUafw#HL(T z(e)cFoGieG*$)SjLcP4gae&~?|G*y5>^^fS1g$Sh6D zf~LvYc=|C}tH4h}0=m=z_e*iB^qRegyJo4?^{rUce+_J`mfF-?jz@$FuypFTMMf3c zFCWk7A>DIUN+;{}UD|bsJD{N;=vW(hIFm!xi=YJ^5zEq$juptj6~-zsKVyuX0{ipC}g< zm45x4f9O@_Q@Enl`MY{VXcMe&!wHEYhW=55!c6hlS!GbN?pn@@<{p0wAcyV&rD*0e z+CA8o$a%M_2f~4Z?g+Iotp|NG`*9C|zK=*onyA7{tcqOrii}}n2*DC-^le=0*2$GT zERw6esyT}>K)*GpywA`9upDxuXrd_W3Wr_f&?-CW>i{^qbR7iB3`}k#WmS2U6KOYK8&@xv z9AYb~jcAMTsWvfID7awwX}(1l&H#H`F}(r??c%miOsK#Wx^Zn3Uig9|$SzTPE=-ay;TW6yx%eEJQvM1`$Pt^Tx{PhUp*7_to9<`*HZf z!Z8JJ_1B{DemJKg@yaJLQL|j7f4P+g zc7$@NN5U}>M>Z0Sae23jv_&}A3}4P9M`0C|`DnCgyv7M8p1wSkfBU%0B6d=9(Gu{m^63eo^HjSDDkYpGn{@zn=Mm1w(uR! zcQR+lB!bxtogo7o^V$v0{ecSqf8!-o*!yw14I2Wv0S)ShcvEVSl0F}4RF!lmGvrql zssU`(?N4)^NC?3gU^CoU%}}H7oz+Zk@SH~hXCkZWldd}2VP@TBLke>+QQ1{Wl};0F zN=^fZDOUjIx0Obz%vOe@Peeuc)f+7v-v?=}NmzC#xN>1osf5WQyDp0>e-M6q>Qd7Y zO?Xs@t~Eq}bt!O5;>UG6M(*NCLKcZER8ml&9BQr^%KyX{C2NU;F;o2zse5HArNiZI z$`pvp=lvoXavh4Vh>ELTxQG&-fLp{`$@7&n_7!40ndxdVqO7l@Y=Uj@QOJR+Fc5Lk zgq>=)X7zGKJw07HmztbB2$fm23?dK@ z`M&E83b9=7ry6h>6hre>Ha4&pvjeSEA&mIJVL?^=g#d~nlgk_4eH5)zv;pXMT9jM- z#*nsGqWCBUXY4R9sV!b652?#oKOz9Li1rjJAL{`qE9M_9zk@h^e` zMuYz#H}pWBv1k>5cD}P;94FOp8&a$J9y$&iJgv0=&FoZ=4_YlNsV7P9cu^eve>yWSHLPDs&LIiue5?dD5H*&3tXFyv zq=0KgSb_n8e-LnGAv8$f`YLK+5ED{O&_&gD;{USQeqtYGe3@FR2bcZr8QRcJX+|P1 z`!?^>Q>Z7?=1P@@8j2kUXi*fAedJH|-216Rmi_(!v@wHQkYAqx4BD@6= zL$(QO;=+U0!BFNRr}l3>MJg3|Po~vMfL@o5nRgymh?k#16yNE2!5spt;#xkek9X!) zbOc2of3+A2V6Zg^Iiuh#B8Ov{d&nRa3a}78$4{scHjG^r3;rX#&Gtf#gJ$t4DrEQd z5J07N=)A+p8FrRv^P1!XbYpl1Cy*UQ3hUUI(G*`PpsB$l1zpe35PZFPP^VMF+qD@{ zY0=@>8==czz5TioBZW&u)}pfsROus;3x^Oie*{nu#Zm$XXt?&`Z^PQ#PY@cEln^;6 zf$)9Q7{x{oW}&54PJp$gv5Z3}U$*mniVTJ2#O`hVEgbS0Txxc<9RT&Gqq^op=r!*w zl8Ii=A(UU4vH*~n>hpNX=@O%BixViJ%qTO=mS&AW*_1Au(bFn6pJ4#UD}?|gFH{k( ze-7u#kueeyVhq7l+NcEB05)WWaX=?&(-dGtgQ>y%2A((+D@`^9?opSIKwN7-e^*g7 zP!h323AE5e-qjn^K(6UPL$$FH3J$}smI5$ylleh${Hq9N@Nz1rpX%?e+Ci;yRAW`o zZcOJ=uOAT{h;u*btU#>}>?^D{10pJTe;QSGfwzl>B$b`#r5ir;;Jx_MjAJ4w=+X)& z*doJwgV^ioCMI!b@4k|&LYc^tdQSFRHox>}as;3O=LXgxCm?_}>F;rhs-NvvB~sv^ z8AV8fOH_g!-0^Mt;v^O0N)5Ruu;31sMOMe8?jz}o973cIr~uPISmXyQT8ZA(e`F_v zO7gM7FV>4#>UA}spA>RU=TmMcU!~(Df~K(ro&W}X?%0Uc3WTMJyIHnB2S1E6I&G#y z(ksx^!4%}ex%{V}B^kJ*>pF3U+~9{4mRPr@_cVC~b%9HcImT>dp4MRPB(+np2qAUT zj1@CxJZu1*`LG@{P=-YSiUUj_e``sHRCu@oXSZ@dfpG;ir84)(3BAU9ar1<^RpBCi ztPs(G0^7-%3dM2+fdyTjC!pdo1xW%-{GZF^*eC>VJk9;`V@p2tiiZJlhQoEgRyh^$ zJ*88eR=``VdVTMiT1-TenvrWA5JpS(*x%-P3&tLK9fVZUW%aJJ?(o%7e`nm_+hm@_ zx_x%y*GPo6Su@)|&aKQRP5E2LVF`UE%SW8oLRKP^w$MpUCmw^R2w9`C?AN(2k(C0u zGzde>RBjq$EH3>+Q;WZNky^%-#E3s~r|U?;SAYtv0Hi@<8h=JGp?mKV5?(fg90(XL zbLuarC1?vll@R}RGT>UAe+96JH1C#OX#{IXwEK6cs{C4IWiknL@bu%9DPWW`wi%zf zKs2AKk80^(yGg}Z?;s;rf(FpM`<>I8ip#-CF&DlLq_${cr+}3oJuB@PWW;1C(F&VG z&@lui_lShZvz#4lB5g?BW(L1rMLe}+N5drBgpweE-^hBOe+1irf3w9?R)q>}Zi^mD z44fc>$)2Adu^;9^5IaSv5F8X?*!)DGKrD8ua7Yq80GvbBjzA8nRl$R6p!a?6EZF+P2E6*~7NM{}mU%`J%NTIl@k3g`=ERJ2Jq0DkuEz<)}uokV4rNUB?$$So?W_ z>*~f%fhbjaFE#{1f3KVY@^`P3!l$%oa^_4!*|Rkd$4?9$>)nz|Zn~=vt~ghO3j7-~ zUHPPVB=0n|MPhQ0LwFIX$vC(9pJlby1p-K*VrqSsD9H!_Z$wxCIpj&ke2jwASwu_l z;Lol50UQzOc>3!HPcTJlcGeVGxtig64R?Khmx40tf6nOrzyh9orn&iRb(vm& z(IeCX9yF}>4kjcb+vnSIuM0D^bZ zpb#x0X2c1%e`hiUdcvc#Z&!s|TB9bpok%MF${wL;{l-usxzCYJ&hhcla<-`f0;A2{ zR)8C3rqolxP`G-0&XNn1lz=n9SApe7s0Tl021Y1Y2J7&kG~|v?cOX=e4dB@dya@$F zC^>9spjeNAUUtX<>R`KWau$R~^ucPe+9uhu&Esg#S!~_P|f>U8&93y zA~%-#jU?cqG2Q>h)c{Dxn;r{My==}nqa2851Rfv9x|o3;sL`*nDjF4;?~nr>{t7YZ z4Y+F5J#!qZynqA$G@IpzuO4#^ZI}Qi%+F7a0edoyELN}v^0pGFfJ-aADU|ZN_Pvot zB_Asyf8G>N`l!<qP49ahDp#W{zg*fz#dT^nF-jTw7=;uQEx|D zH~`tzZV_YWw>>m0iGBYYzrqL|30VE4@xlqRj#XzrufiH|7ut;g4*;}(bjN_T<}?u1 z5dgK~;WxeAzu|GddWenCK2sO~*iB$i6qkUXe>hWR0T>W3N1h~g8pc=sEPqYqoFFZ&gwevI7v`8D5L>6 z{f<{4=(LJtO~@bTi|ceW00EN)XX?vEs%Q@@9ljI^-_sQqND45^ev-ih1EHVd@Un^> zf18h4u0y%TNo2f&Fh~+jfv`%VE{PGS`oMW6hKX%k^{RM7M)M6xqD?;wijzo#Ux_AC5{TJ<8?6i1Hyds0WUOUdVL`~e_c(OhA`^35&xf^Gha zvvgNuv6lPTm|_JV!a4eOMXH7DojD99M*~iVmOKD7y6jA283hlQipS8o8=stNz3Dih z0!r$-!3SRj4!x`pJM#*pnkZQHf4EZELx~y~oHkAtEIhI}04bZ8NkBIxFh>vZj@-z} z+0@FQ#QZIY;2T z(di)m2f7@%5`{+tq^{`?au$V0B?G#6x4ew5P~PkbRaR`P!~tNY^1=9ge~#87^W=90 zT@TEld-s{Q*f^USSHhW92EwZ~LW%|` z2tF*sP}Yk3cp>Nr2kee3agd+o8%eKv!V~bwpIQ?@V<)@lOKc}Mu=lzcdjFrl?5yEe zB~ZB*NC8f5ZK*=7Z4(Nme{PXphj^Pv2_s5M9H0R)VVr$ktTfWD5(dssKp-BC*bp&< z-)c2~15_^8uv-pa%v&WQbwNMFVV;9KBktOe)*_6d041H6RtrH&PzsiVmlC-jlq*3f z4FTspFwJQqY2Q|$0C4HE!cGaf@mL~2C>QF>z@Ptq|Aq63wX>N~e}UUF#(Y(#=aU^Y z01TM(KU_Md2;xGt-f_Fs4J4x2%CDii^GuFL#Op)GPzfSgtZ)K>>*k6tInQfzVJMs; zkZCaSGUX2tPQ6h^b2gDEVKS}88-fFu4;zjM9GAu9S1&c(FcNdFk4ji5&w}bA_+?i- zFlWo;l@Zv8kO1che+79J-5dZWok^q!$TtDYaAx z2xam>!~tSv^0t2D%9Lzqd{m5x&kyBPk`;WbQy0v0?|WKGky+!LWkkD2o>Jblp=`BL+` zhfq57nsy}-+%|OmrS1sI;q>nSign1^~ zeCGS5;Z+gBe^K-jV$sS@-7t(Z+`p?Qtk-3~E{^OX!=)w^J=Cx&7L;6wfMvi=fHOLP zZ8d-jAD(_Q+OU~<#EnP3BMv4PYA%qTJ%Dhh+#MUv_6rq%01Mo#1?Ui`qPe>aR6c*J z(H`CS2Oz_!JkZHaZxe%4O)ix%)RFn$L8_VpuqI-;f7@9RRlo6V^)DKLZS1-2l;5P7;z?c9KkWuO?J_wataR3** z5CqVwm}|>3hRsloCYO>TAF@)&Gx1e^LppRv`|8hFX713VevEtbia=tMc2a;u!D} z++`-dbzt;KJV{XmZ{OKkB|w3A{>tW)-cHdV2?3^b(ljpgnpcQ3=b14glKK@(5#dP8 zySh|t051zqgw0bq21)_uVM_Ni7^?k3rp?IQc^lmoHhHlGkl*mMIK~FdTF_c~e_t4S z{Ft79xTdeC@5fLM*(nOt19<=!U8OhTh0u<)=bs3v7!n9Du*4Sgv#srbe&4Zdfk>qM zLatB5mI_AijV>Y;jKRg1(0DJ32L&X5Bp48CTlZ>hld7t(#3KlBRWE$~ z*-GKKBw1y+5U$s1`UI|Nepg=w&B2|CWsj_bxfr_oo5QN>LkDfp+BA|l?a0owc%e=1 zF@C>>XX9KVbNGKTxszMKmiw5wnHfdt&^?VR`?T-+y?+HHZQ+L_o~Hx?e||ni51pY| zXwmv3HbTsoS0im1zt65E!pdoG$ic1)yZn+TO@M`ynvhy3y|WeJ1ol-#J*6>Bvkae# zatKiRm~l^tl)O<|ef414k(@&BC7FTG)t@fy(3ALa&j0W9rwf{LSL$h7!FWkOw`w`& zxkbnB@M2}Qm_G#PW^8|1e>IJ^!Oftep99E?MYd{lF7*usSnRIt@}>h<0!7AVvrnMs z;WP0Ynfg7QuAa^yEFt)W00aN<{{bgCQHfZ+4;ive4zQMQRl=%-=|ifTTJ5|~z>#Mc z0Y|TGLRM+RI&sevJAr04lUz(UN~>P|raQWY^F^Xlq*y90C@0bTe`+ITZ$9u^LN)%@ z@BK>Ladh59g{mRa*|kU}M_(D{6uJ^Qyggw7dx1A%%JT!}H}{65^|e0(C)$0UnVIqz zy7HSlzYHvrL{yRIm^E!Dw?wKWN8y~&C?3{f*?*f{`aWF|eC`RKM_)&O>m}p!bh`S# z3+j~>uwE!%*EBYue@rBTpB9HQvy1%SL86tu|&iOr{$^nBkHx|>07H4Ah8 zL*`K?UGG}$f$fW=I%Le7D0ybUGLWxc zW#<*byU?=F1s(7yW6_20uUz=C zJtUpdW&xgi;&#_-1b)K+?=UNdw1^~Q6ZE^%O#YdFRcy*|;~zF+_#3DWdj z@iY7#&7j!f#IYsw3Rfc*wg9yb&o%QC6RP$Rse$#;e-nHclBlDV81``*n+v0?q3YrH z=w9k*qV3r~45~fKREH{7tfci#d+Hy>%A4qn;?%$%I9$bNU;VLt82(&D5VuQnpE-*- zsiq^s_;A`$FKFO7!i*WO|Cqjzwxt z)cef7e^y!zf2z11JZJmpk~f8REIZyyd69Re+>KL44YOYaXU$PsMZ>fw?gxjBB32d!GrNH}Xx zh#)z3ZFc>h)#FY%`FHn()Y!LSym%L#?FJ3YQy%2=#07{RlK7zP3U5DNy)e&_4-r!bH#TX#MEiOC&hN(OzA#@ ze^?=b+{Ehv6q0O5D%U<^I9m7d_p`|od%%QlzI(6IW_(6p`u=>i(Y0#3`^k^4Uf-$U z>E)^KTIMyNkbk$Fr1nz{9^OF*Z{o54Jh%WzW?Ei#3mNFP$we8BGSk?b^CZ~VQ}q_B z)HoKu2&46PCw*&)9H`CksD@T=TirmUQF=0ksX>gs1`y#AXLLh{*pf7vvFvlcO$Qtt@h3fkuy_w`>%jyV znOt7oO>Y*d>GtL*rsZ$8(SN5c40|@E$!iAa)X z(B#N`NyJ1-3Yb)v<|cz=f5gdjqmKak=yumzZ=9U<4k=`0l5U*U&#@ zdDs5x$X?~)NdV6?bUv5qEJLI0Pm8SNlUuste|g>;elBDQPF#J1oX3J=pN`mDHB_KT z2Lb)McJu@gX6IDx`YX+77&l!;>{9p-Mkn0LLI8j>Hm7Gg#Z%*-f5Ft%on8ayL2D^b zY;WysPS)#@Y^2haa(l-(#wMR*A_YE!+zk3Z@pEs!Xdnm!j$Y$9(9?dJ(T+DhVXuJq z;$6LAy)`TvP) zy$y)o8j1(_F4OwvfBBihd*AOr&)4HP=I7O~va(BCqLO{L2tWXnVV!Dc&P8W_^vB~J z#bzUyWW4EEzmFf9XwG8iFW5||F^Qe+`;KCbsp>}|?P+VMPdom1eQ=xc5MQCISLN4o zE+G_?(5VbQ#jOpEWZz`ah-csEr(y5CN7P1AL_C@?%ao|=e?`?=GN{%{m+`QRRIY!I z&_mGQ=M#f%V7$UE=|;rNJ?oipROY<^0sygUSn1Kw=@8aE>j~%zC`Vo3M`y&1ILajW z{e}zGpbWNN4f3g-Z&$Mr|GgXfUBsKpxqaQ^?sB>}>SV8_S!UvXkGjwrY|yw9ohZP^ zmfQ2sklZDwe?T}Hmolk7dqK#XaX(k%^cD7a2xFF6ccd(gm%JxnV6aF#2tokm ziz7xLfB*6Um`c^Z)-8YSt2sqOJR#e8xL&za8$ipqWTU<0zJFKZ7 z7Wx)ye;v@+_9~XZAkDH-xPReH=k#%{xW8pgq;=B{`-^3%Aqzed)} z4h6Dj+8Hivc^XFt%YXNmc&2^y>`O0h=B}n8rX08-?p zd6(EYX)xQ#ZwU`1O=^6CUbER}nh*dW4NjxPtLs@0A)j!rVPf$n5+0j*d^`Z6Nn_rZ ze=cULbWTXes=^AtCf22g(_^p3B*oO>Iq5=` zbu^PtG5X|7t(vzQsMwn)x7_78r)=Fc{|5W*qWDE1P*T!g z$WG;$MRXwY4+vV?9w?|`Q~om4xs%d(eHGsbL7xG$85vG+I-oI)`r8#vY^8zmf94xG zpg=uJmEPA9Uh~%i4efHG1XmjM7k z7Q5vc=bOF43`?ILr(Q|?sP=h-r?x@o%1a zngj%dAH4hQ`Fj^Zd-WgO?5$c@fA|6r1vl>DS7|WA@A1&&MxmF@@>S*fbj*{7$vnFT zEk0f2jq&q`$GDlLHIw{U8G(Wd)}k-~0Q>cc$Xus!_XL3@ADH_B@m^{|l zf6ORt{dB&78?ULn_!yDdf1F8j(EUeUuO@M32M5x;L^Cwz9+?GR+C%5ws`S^d#Ohgz zDMSF*vEz{CsI&fxTk286zkrn@2mk=M<1k&v7oV-bA==`7BCj=ZQY8?Z9(b};=&k&k z=$73)MOvGq5*IEC5CwHkb&Mydis|laH~qVVJKG#It*{^VFZ&13f56H>%x$AaiPF-y zF9dedaoDrZD%Q#MuYh#N;U4xCC`0+&wQdUttpE^!KEL(h9sboSyvp8HzUz%lw`3A8 zphQeo#Te$9SBUcUA`arcXIJY&u>8QOZDpY8ukZ1ELI8k0z06v3>0_2rfATr#75yFIA$yw7qb}mFxYzaMInt~MZi&V0c=%d;WOqNpkIxew zN5xpZ@=(@8j|@;*TU|&GG4KaS==jR|%m%7Hp;$KbpR3D`rZYiNCy9vBH{SDI28R=5 zx!8H&V?Ijmd@&Ye7XI`kYXATUVf{Ed>^AQ)7o+ZTWtd%lf2wA=rFmvc9peN17%7oY zIUB|tF^h#|E?2X@!heaj(V+1|G}!-ppRO>AgD#!LEJ_sb;y>$+m?WvK=Nccrr??t5 zF8C4u1?{j^auH}sCrnRAl!@ylZ&W-s)7tDL7#vQI|0v@Jc;dE|{y4?^UkA#|8_f-Q zzZ(kFE`#}Of3Z`8>&Cw3I4C@Wei}pk^;f*wsL!uw^DJ}N36vl{M_$MJTccWnI}-X|e#?hoT24y;T& z*=;r)0sw$3?d@C%W+Q z@LMd&9N8(89XB|?#dbn~n1-=xE1&J+2tokE8PQG%Wh>Gr>ykY4t=Y;#I)AFU&EFrp zQTJ@z5IGFrPOKVy`m?dcT)sNULJ)&|d7`gp zyL7WSe^=(FOZ=9j+(RW;-?|{%(yM%wPRb}YeN%o$HCpk&VRvi~P0dj6fTVo&vcs33 zY^wW|hug}AWRn0&Pwo@uIZxQs@=?9x=`xXFXpVQ$DtH%g-`<~vM$-~M)x+~aWCr%u&uhfRwqjV~$m50fgrqVu{_+oL5Rh`O! zgS}XV)P;wR|1fUXfW`7^S=qXKO=G=1%xm zZ91nE`W=1F2CgE$-1_$6P~U|>z?t{8QiV zHFm2V{24mp8D?Y_57RU)QJH^e%@wD-a_8pr72Z#As~-2;9wMy5>3RoQa{t|re->;q z<-XvFWi~1($u0kUKmdRu$3AVksMnUaChqthJCs^fBC8`~RKx`Mod=gBWlfX)G{T4~ z5g0H<7s+E&3<$dBYzab>6J$?zJ;^?P(+)$|wvGWyTIrPFA2#8Q^Tzl*V%%2Xm<&V&H~R~Bj6xq<+PAm#sJYnP6BVpwlzPJlzkydbvO&I6D8o^Cl> zzJ}6sPcp~UCPz0OG2bsKHdP!ZNIBp)>({Ga(kGQRA$*b`sqsGx>*k-&~j*A0wK_ z=y#CIHb*_}!q{v$A|=!_ebuDC+PD+lI!x9~dcr&Bau-dDN8dVH`qNC_Dw+yLzo>E{ zUe_MXIP%TZ4K(euo8Xq!f98CkDG|_T8tt4JAa>4MFQ}2r7bbGMCD<88CPxk7SRo1V zG~GzQ+C8edkiB$5k+$h{uHD1~PTK0uRcO43?>mi-|}|)l$T~?1}nIHIPOndzP81QH*{fQff1QK?$5| zRn2G9rAtLJ>sGZp2JZahh^^S%!my_7>u?!2Dwi+TcfqaKwy`ZdX1|`@@~%4rCc>RS zNCBpY*@QSPI5_Hoe@1T}S31rRfC1*WF)e^%Nia-gGNf8J~@I=I6dDB~vX>}wA3 zONb`81g0o#{qcHTGjIR_4GcfSu(m3Wl=|kb2GS!=IZus>CVt)FcmPW6A|@F}rLHIc zf1Exx+B%~f-@Bpdd~2Vt#E^a&=NjeSSDTXikl5jrCFITbaZp_C6fI{RT>=mQDC5;X zzQ{GH$*ivhe^RB~=LEu7;WJhPme*Stm2Dfj^!2}m& z1ui58n_E@4^HEj!rTPu7%%7NNHAP0nnS9iLc|*AAapYI$o$MOAIny{7FfisP&0QH# z=IRG&>*LEYsaosQKEt-#a(_PIN4!<8=GtKc{xL5df0hM_w8q+2zItauIKGj!k~U|A7ma@{_0Ok_Zqc?(_r1 z$Xeq3E`F9@EVW<)5C=AeIfG-C!7s)Nrer@xW4W_?9LH#yM+IEj@m#E}aSBSB#MnCD zDy$=Ye@kXR;Re#5gS3*BXRaZS%ZuO;-lB*VS7h6Bx}_n1OyeR&?WRkP3gWS;Wli+T z|Gq9f#P7F8;vk#h79zVH@^c12!<-2`0cC;>si!!aYDcRgIV7@N=kt5`#G1b?)QJ1o z0PGi7tUO+Y=2z8?4lj1L#MB5Q06 z7$#$>EExAw{DaCU9Qs! zS{&6;U+lfEeoyVeQgu0;)k}%Hv$gZBr5_S8R5S1bUC;l`o$jJdvL6s`qdpAKaT#HZs%JaUvv3d zrf`!~#c4ATKDBFJlnMJh8;1@ySz&GHbV6vT&-L3F_UZOAd+auk(4E!x+Vj=eYb&zd zS)M=vg#lgxArIpu*^ja1xbz&nd-4D|e=kSB5e@NFRC$h~#<*$rZYi5AJV@<%lQBfz zDu4(>%z*={vCW!t&CKMI+hFm~5QPN1Y{)*z^%rK!bAE>TufgNoMKoADj@c6x=C{}MfOJ57*xQUW1bU?vUmtD8N!TpGcD61m= zD=My=wt21>-yfq>cuogvY1)~He<0{d1UC`8K${Gwp2MTG;c@&5oLCM##~QP}L7ZaD zNaN)%d7i#{ogev|55DT=z=tO=QlQjnl7=?quNTYaY&B2CZc}|gWlG5@w31ZNg+rqt zn;(UTwq_?X>BdAr&k{gF-qsE~b9MkHSy89P-e^?a{TMlf{%m~{uFsP+f1IDF?F)VD z4ce;s`+WX0L)c$Di+?8PQe7IP>M=a{|Mbqqqt`1(Wm7$PX4<0sX%iCP6jakN!G;w@ z&C`e+(&jskSL^jZY<)6)QCPP!kRV#2LI4I>5&|MFIVbebsdP2;k!+M$k3C*!k`DH9 z*PfdjHJ4zZy4<#~cQ3tse>^veR=|P{#S%}TgLBTsqu#cjH(IPs|GwlqLZz~MI+s4x zVgv`gvUOxRCcRik3`OE*c2>-r_DyyuV1NM)3EL_WFq`V?YX;Z5ahGLM_ zL~C-Bc=vzGi%p{GnEUwPav4G7gcDxfn)NsI=KEuQYNPnEto^;3f2Fh0sI|Hu#xVwS zNKc#pF!xlAig5qviVlRG;L|bQDh5yTz`? zXQxOIKekeSfp-Nkh9KEQL+_B>SM}ZiqHPTUbr`$`a%Q7X2~!Gwm%C}C!m#`Df4C-rrAFU+`H*nI^A%~w zEP5f5i?!}<2m%1r4U>sRfUdpPkcSsUj1H zNtUfPF@tuif2f%^?aXW0Y9cjDNdGWI;$iE|s;w(a0K+`vyZ(K%i#s#GF`6{HszLQR z7xopv+UO0@_bxxp3|#As;Pv{pR=*}|B63JjhX2J09K3y%UOXj_TpDQizOOt3wW>&g zP6;S^zW%S+X2t@a3-*-rw=1zOXYFk9(I21Knd!b$e=cvW5<4x#w}*AJFnaRctH6^5 zarYco)HrFWkH=&|iPZd^!+;@ZQU8R302hD(C{sQ3;;3-VH)@*qO{{}!>yIku3F1ld zt6xc+c>3L9Jlai(HNgT1#-egr>D#0P1%e0&P!K{JohD<;B_Aiz-6qp4ar*1(Qn(-Q z7P7%%e;qMXub1Ui&ohm?KCktqWb0+fo)X-S(tGW#G<0Q0^4*fA+$O*ffG3c^5T}#L z)lkmuaZ~`(gp!Dn{-6f0qoMybj-UMe_OI0SV?<_K;d2`EsHoKKq&w>hHgJhu-+NmI z@1mBr483{N=dM9_EAHkJdFgeMm&j!N%}oe|e^}M`$U;wBRzXv@{kYLezz~2hz!Dby zWze(XG2d)Oh$sQR-Xb7L002RY)DY@xy&OFLmOq_K4dIp9WODo%rs&>>HW~g!?XQ|D zTAGp1(5WYZl-e(xk}ppoFR`3iCXp*Aul*igaZNITlq}{%huY72SGe^}z%}H1ei>ZU ze;Z%`KotGKFg5|1^52tJiP&;huON}aC6&-n)}vwxAgKSr4MsOH@7MIb zcM)FY*6pV**esWsOM`sCE|9aJaPS^fptTMR|2ZNaVwD+cj z=Xr6yu5DMDb5Q+V!v-vX0xI+Y+Mo+}e@C4C$PkhNixmVob`KXiN~VfsHTQUs>^a&V zljr*P^zUC3Deg;^hb2ZIa3nN8)IkZSn&IKyPIuEf|0iKh`?CKOs#QJk&N7v3G~Xrz z`xBuK^hjfT7Y}aZU`e`w?+t!KbEL8^}T!q z?-M8h31`6t1#ikC1_!H+(DmRbsq2+#c|PyevTjDi71BTmi0>dxt#>`^nJ3(z_-Ybm zp%B+y`t|gkPrehM_xC~dN;bB-f4g$@852ImElPeI*vc?T4J9DbZW1(@oNvZZSJhM@ zeR3Y-b-A6S{tEzr00@r|3dDd41zSsuodlUfh%3$MJt2i&1#~GmzAL`YqJrNS)7twq zG5x|%TCUu9yKwqzKIbuQ5^sHW`P_gFgwnwT7M1+cEO^f|SLAYO%6v%De+Vy){XkFC zH+5B!Pzmid@7yeYK38E=Qn^oEx4P5gWA%H5TNoL*Hdbr=rbG}Aa1q{MMElv^T+t*N z$DZXVONiNr8cO4j?B#i#yPV+wjrU0)Lm)S^?;0;xW>5K)xL-CXubuaWWL52V`(9>y z3;m&{-xa=$64-l!OD>)5e=Np%mgjyVOlW8@yXNe)F|8rW(N0bBo##m%cc35){QM$9 z15p5>_v~s{UwhP9W$YD{MedT-Ex?5+Px}>MZW{w&Y7BWXB{P$pkin1U2>_8*?|(dYNr-qq{9+yD^HaMv?)t zYDR9t<an(zpHlHaPR$DhVL@bYTjtKU%LM zN%`QNv>^xro8+HKe*m68b7?2Fc%4%@MFzm;yUMbXt6Avi`R+fy4|iFN<$F>-2HFn# z^=JV0>&O8P!UP3*o8Ot&+L@i$ARhDy0Qm_7YgNYj7$67(kKyUEB~Uw6#CgP6*Y0V0 zXzmmJKor1AI3s%Pn31=l+_z}LKX9U`k%L8W#pMZJ)QOx});wK?@TuRiE6hJGboHb- z00aS32mse*iF@y0w9K2e-X)~8Sm;ZCy7(reVSqx{WzUJgcOSP`j;TRCI76k2RCqL2 zyuB;TB8#Po^i300tKN=A^LUy$G|z9gH~ICAgQLvrf1Q5j>Pr~YVUVl2pSfwKqk-~% zFVYKz?x;+5yd zy(UN!3K`S5hXi zf3K5zI;vx^c0~oT=t`ArvVK%TThzpDJeh3U^}*V8fUrb9sm|;ErRD)585Sldq;vig zaxQvnw6jU_Hc<9i$PoH3tZCi8{Ebc!Ki0&c009rUCN~!p-!Uk^u+w+ZX_3@T*sx(z z)plJzA8If_JFZ5bDZ{)VgE_dDeomPL0T1yY0v_`1sZ+6bpc-aVF%ah3D>YV&DsA{<S7xK=)kaDSutF=aqAZ|T1QpYU1aTsA%Zy00`qk@Jdv znq^pD;z0mJ>=A+(2^@`X`tnLWQ~&^}44rz68uph>8EE<2bzh%N6067OVX6rrFEyhC zWC7Nf8gvFo+lmLbGmC?OyK~YMYuv<{Xqpw>W1VgxPLQ$ ztKAYn2seT{2#6FN-Db+l`@ekiPe;`9-F0<&RV$xI!aFUfhPf}y#@A(}W&@n-WVzkt zX1X^LI4=21mrRy|6D$-{m|;u0@>RO3X_V^G=+lF~4>?M9;d{)t%}gK&0jLlJJU*`8 zPIKzUBer3+_}3~mQic6-VXl3J2Y(}Los4;MV1NM+%ZLI2=Fr0RzOBUGR;vuqi!_(v zRw(rn3r8PbPAC$=sd)F}S9^T=6*+#4rDaQq^cQ1$U(mqbXxVNnrBdoxr#wjIQ-u;t$*8l?6)g0U_Qezp2p)B}VYKv|)7T``;$`^zJ%QOwpQqxo=kQIDcm`N)a); z)|fIepIxCIwYq6zycZspr{S-P{O#B2S3WL;0(vcNdjC$JBOVAQJRNl2BYvq-IZu@8 z(`4r$ceoW82Mdk-V90Yguq`9C^q>wk1#1`Z77zh^tXpilr4N@thjf;sBs?-YHyA1`y}2Xlu* zmgujwuksgeM0g8kjN>wOo0_V}nVq0kjBtVw05OKIWKSIMDD>`dDY>?8PENErY~}y2 znZ)qE-e2a%@g_P~>j@n?;WN$dTlO_}pCvope;++%C;iEgKtt{T(|@8MX`dyVu#MgC zzXNrg;qrLVce5P@nJ*q@8Fyqbpnxnu05f&;RvgSgBoO+ShY}z5`VMs#+l`RA6!#uW5FCO{xj0*5%vrI7M`!Xojdu~hZ>zU>cgZtJ zBfd~#+L?!f)^&?Lu$3M5Qp3lplv``EQE@7B7=&Oo(3I^?XFbd|wjvmBIQmWhZB5dL zr285t0uY0uS_lR-0?OTuLj}JR5aUgzUQllU6QKJ-Bfv|h@qgtKZK|ImE988Bi`C51 zd{@R{JF^uJ2{Dm-nDQzqYj8|mMKsX&gpzt-br_!gY}uUc7L1~3UIQ)QmeAM<@}-V^$h;J*MhKq6~;U+ zZ4$yFKYx`#rW(+p)^4GbQ(NDNR>#FN!pz&MA=ZHGuKe8zApb3a0IGrVOZnHk?)(fl zj)4c9oTev92kOiAzhVFp;1D>xE-$^zPU3Gno~lDNLpL<{>80K)Z;}1EKR5An*&qSS zP(NLwA)5d^o<$T9#?WY4uaozr`4|1?7CN!a>VMT}I()~zczU@V4y(hLbV3e%fCXS6 z4^DB1507L{d5igDyZcJ@YIb;4E`qKj5a5mX?>~=<7d(ZW=mZy9T}Gd*rU};00zpgA z<@vo$@JQc=b+?leD}EpxOP-Rqmu1WNqTIi}x)!r|+LE9W!GCJl(N z$ba{-W9X+Zf%^A=Apji$5QgD`40NW&@p%GuF-o|=r)9_Se)8Jed*u?6mGZrJ8088O z!_S#7xA8iiPOGZka9hIGP_llaCi9IdS>09u>vtHUCVzQ3p7({d4;^1+5f3EsOgBnL9TJ4TI`Q^X zj8?_|wL3OyLe<~%&001K-~Ia?ti_tdxuwDTGpG82nVTCyngRaOTAk5Ja9PkRlQ45 zC88;5Fv{0FWtYFBg1wM#72>ih$>6SV2tokCfIn1k7zFAuYvR2qBwC%v^5_Cjej9~D zOo3t_uhd;hHrP|c-m594_hYSWfpEyHPj%`%qs%qW2%#3=xfKTs)RM>UX3X&QvFcVd zFdXjX2#C|G{)8X^e{SO5CCnBr^`%ZHS+On@{HK~5z9QeI1zPS3i$$?l-MdLTS04cc z_k9x#0SE#;_ezOc`N4c|jDH2w@2}g=h#!HL*%cmvVZt{eXV^{(Mrhy$sb?G<`g{w4KBo%#6UuvJF{X|~A zWf|7_PdtGD0vzv#G=Jgt>Oc3El04LKgCUCUAK)U z{=U;%`Z+a^I!vb`H@mvP`*Wy48$A}B`n&kBQzVgH|BlUkEPvG#?vaFocMD$ZcR4;!>R<1et6lv0C-__s;n>Z9L3PM{ngoKK zKnFJKJo5gR0u7o?{LK#gw}7ql{E_qNj%E(nYbB5uU%uAfp%br4tvp=vsaL!RnK$Ig z?}RD=^Dhv`QGXDyez!hz&J-^vSKXpv0>u%(#!9&rOmqN%A^B?geevzff0W1nuGZWp z%tbi{a}U;35MCF@fT@fD2m)BHfqfzG zJxMvQ_@y3>L|h(-WVTnDkCfo9;N>@swMtoNi(O9b*?&L~O$YUpt7*pdrJr>+9h+1; z6Thg6E<7u@)3j7}$iWG}yiO?}|8Yl_JDaf9DZ#d+zOtN^!?t0Idm6~U;wP6SH-s*n z{ZTm?4=S4<@gS3J3AX)INKc>0Y=3!7R`2f1F{PjP$#U-U5AMAA2|Ip)06-GnKdV_a z9Ky=tqPKRNwLJk%VJ19Y)JwKetXzXxP|NyE_ySoW%9 zRk@#UCNcc-D$4E7s@haElAc`qU!!4o-`?ROV1Kp%03rJ)9p#+fexY*e&$_7AEdEf={n|OVRyY!}_!e4%pkJ z7k}IYtc;!S8CS&N&%BCM@%VrQ%`GANAsC;C*8Y%#e`Vj~wpzz3iD@FRhQk3Xd-3m` zVw#M3NY1nyDW`9C6M9EvDBu^$xsdf)1zFseI-XOVCzb?*J88K2J8u|@>Y#`qx_AVA zs@@a&|E~@LSHSgrukesukHXPI!J)ZDeV|r?qkToN{TNMLx66;qPUsul_IHOsv`YV}?}uZm*CgD4xn!2C zY}Xp97BL@JJ1n!^2_zgv)$>Zs?yS1Ppz^!EuvL@bD}?`V<($C1lk4*7-T1DxV_emb zga8OiLI90@(NY}nDtE3m6IF7?xqm-S^6bh=BI@g&V!LA{I&mMfano476yIQ*-{!(adc7GVZ38@1EEmsx>+1g9U-6G+M_BYeq^8N~dYUpM{Tp$$NyEL@5? zJp7+3<0$;gi@pmM;#TzM>Q}%NOb<@mp*X4fsh@W=)^>|+7iN)kV!5zNcYh|)t9TJ! z74Xbh^7O=yJeqIc1CBLz5Ef4^`qB0hDqgnv-p&>j5})M&5{m!QZlCGP%qyyVCw*-V z>wJyVKNVuH_Uf|0n*-XM{IO^;|A_m<D7@iD$L_D2H_^k1-*Rls zfFzV?N*z2C)GM|GvfkGFWcr^CluaREj#X7CA>B z$yf6;dO(%xCH0yd^Y6Ce!+|bdokD`OH<(+=-w+MKG@Ql#U#y2iz|KSdbwBgS^5LQ4|B5%^1lW#kVm_O(Xg-EKC#R*kFutRN1zJ*vcQ==z`DgEhd^XdJ{>9D5Y<5l?l z;=IIT#%k)Ar_!~c2seTN1SQ$IKe02MeNl8T_ens;lMs{^9e+35%}M(5OF3*!>6S(h zf<6lWS<*o=acXocg0lL?q}UF7W$HQRI_JgTOQG3uLAi@SSU);;l$HMqf*?a*zs!&&J(@~m?%S}& zUvzx?##WjCB}ODqGg+QM5P&5*7!*r|9uAm}a&O&nVbe+8`er(RK6$#IrUw*pG**y~ zU(3sa_UL3=IFFOr^ZfegW2N#sN^uGtWN32Gtj(m|mwyIxvuBJ+yk1(Y3-2(Y8Q%Rv zl1eDQZpGReb&F}V?cXeZsV0H(_2&@u9#6M>WeDne?sZ{)u6`8$`-Qz>HDu%=2m?G~ z1O<`=1bpbdFX|K z(PR_)YJXVeyv{H{7?f{-AiklRzUt84OE`Q@s&<63 zh{Nlu&S(2j?$;&CjsOK-Sy&^Tu$lL}!g|%P7k~WMB!Eu*k`6x6cS?u-Z;#n1zRhVr zTO8-_wAKM@ku2AcsK{IQw0}P<*_3Ieo3vMfAA|M(&tHZ}Zs%3f35AOQ2+(1lulxT+ z=X1WJ`jr0#@}I}y=f90Uzma4`cyWGTnFY#VzpG6vc{8wl$c5pcNd*?+I1&p2bBCip z$A6cN(r`0!TmScq_1E97CenK)@A%8(<@Q@QvW1f%G*0_yt9c`jieJS=m?rVw@Dfv{%NNrvu&#(uz*f+-O|R0f=^3%J>bHS zNmJ5UJA0g@p|eTNboUHyTR_U-@&!=xLhYf0+^Bx41&b` zibOo(aGmKsnw{~mW>OfA8iXMLQ@MDt(Dy#ZQh-xTiC7Y@uzmU@x|WiBB7`2mk^k zTqu1219eHA!u;-j&sQ}cBA94S{igAM?|ZC?>$}EoSovco#?*JXwfE(~0XvB~z(_m& zvi5?$e$zkx2sD*#V1E*P7W?n% zyL$!7PP+4G8DlTvIy@3PK$0|FzJ_b-e8xW4EJL+@X|9{miefth#rf=cBBmzjZ$NPkY05;IN7@w25OYz)V?Xp#} zjDH^_kVNf{JFQUtkKD7OAdR^shwh`d<_)Vw7F)V=Fq4^-T9~~pf^%HFVmF0F45(vw zMNFc^k3#S4+Hl`E4YMqrA^|nD+zt;%{MFoA{2;mvE_r)b4ClAB*MH>3sk&%++&o_4w{y6pSnF~3P2|NwbcQt~`$H9cY#Z7OO{^`$n`1wt` zmW5K3F6od05C-81so~YX8zDm|yHTvh-{kQ-1o78{AMPNPC7(a7wyK0jFCPE`O**)C zNq}Daxm$h72oMxDHGdub{RAFb^;{kgQQ82L!@kCUk4jv!A(gD( zR`ZrWbER1|>?;wmU;Bitzvwk`Sj?DN{1 zq9-j>GD%=W$iL$lUb^SPY25$TYl;{FsPN0FHFRw5yo#{Y?HQS(i}~@l1$3X~lC9uX z@Ep4$*s;3YvpGV;q_&tD009VG7q_wVS|@TDMkOD%H-Af3XU{UJmv5J2joDZwKj;g; zulRo&dRA*YD@I1zjt~@x1>^Ohf&ru4`~HS{eNXv5Ob#A*hokJb2#lRmF^8>w;H(g| z>paRYHtVeFd{=F1I_s>_p$&m^wv)?v1!kXhX7V!Rr>d!0SCn=S+bL3fkw zp5pW>K!0~YPC2$YZciEJ_w*h|p=`%Ox>1+}T%namp1r@Ax^zZ3( zKqLG7ceFbv=Dq}W-*^4fH`L_(oO;i;N>Q7{Mt@==RDup~&~M?4!;uLM+y9H0*FM%S znN9*)bHbSknI0G0D>UD^z>whA-~(7esthh zcYpg5Gpv|v8;0 z+y?`tglpaS6)RzKT)X?ABp8K=ssCF2zaPT~xX@#Bp0{TXr4Hsh(=7VhJ`lLM9}@yn zFx}gAISQ~2To6p3qfO8J*TC(4?lPTBihq-oCjJZ0+vNg5>s)IIBvOz`=Ueo@*<3Dr zHH4hj>O5|*lO+Gi$k{yo94Ja@8o&rEkn!`4sz@N936$r0{j5JJ@14Ge6CIvM8{5{p z-i6)iq?c|y`n^!0D$)2LBzVzO#;{gU;)R7O7x#qci;Den-ytEA>@K+VI;9C*M}N}s z(VvM;dvMzdqyZ&Ffs)_gTUcKmQ_syV_z{_BsW(hf)bB5aK(0DI-=#=p<8f zagPcftkgZPI^2*X7Azmy_(Q|%Ly}qhB!E$h+oyZ@eD)VE5?-EBP6K3u1d<8>17wC} zidk0&m8q5GUa+`P;c30G?+%{m52ha};c~dkJTv zd-*472m~$a6ASBWwzGdsq|3i_nTfy&DEV*of9{6#hBn?aKKJAL2?SESxC8@Jp3vhz zm*-@pk5MgzpKQ3nLR|)P9U%|Yq~iZ_t}lTXaoTWL`&lw~JZV%gA(0 zfZ<|VsrXsHtPuRSd4v4pFxlJp?c!s8=lt&(JAS0~*?xw~)~J9>rhhsT;gW@==al38 zb$|l1bp=GtcHL1oVK%7`RHG}IOTS_7AbWAnK2-=n5C8zd5Yew`pU6lerw?d#zGF6Q zjXJou4Vj-o6_fkcmM+`32~)#rS@Mc zMo-WMKQ5+8RkX->*uN}QvtmC5Q=2W9*bn7iFSWW zEz0I1sAcfi3+MW&UPUkcu>~a={4Fw3Xwr1L0Fr?M&$&^CR}XE6;z1?~ZT zv3-^OK$1O_pMNf@c_Vc{h1GVENGf9|Rn7@C`Se`0a`S;kB=ecz&sv38CAZCTzjLG2 z)}k_re8zuMu-#|JXYb1ZFi@BuUAkk8+}HscR3qnB8 z=3*T22E&!R;A?=dBd3S-rMy1{y%qD?sfa8A+2r1Cc6$6m6Erz(uplpgQ7V&iRWdzY zBX*tQ%cAj9{HGi;}`ff&6k?Z~9JInIH1fWR%rXohL1?asb$&ilygP|h&9+Gtv6t3>CUs3rqy&I3p>>hnPvzLaF;G!`Fj!QT3$`MG^?SFg>Zt@cx_`OM z(*s$YQWZ|!%ignNesHAWKubCSLDtsM@&CJ;!?X6J8aV6O^_NyRWQ_R;i76lLwVKEI zAOXlA0e;TWG;8#l>P2x>p6+VbC}1cNasQeDf)FP)s-hrW=k&fD>RmbcyVpr((VgxL zL2vPZ01zMm!Oo3Pa#2EuQG$&2Kz}RhBs(1U%1No}G6^fJlvsXn1en&ndJh{TNsqY} z{J0Ng6}bGv?ARn8F7_|t^PJ0v6=<~A`UC)R!4HaS@anO3`KD{;!(TD8P4BRldc@M# z5}X4%5ioqcb-NUxKmhggS>ruopi=Al;6__Xv{Y}kxxVu=GO0zDw&;5(gnt!wR%+s@ zF3wdjp0ABK6O@Wx@Il{IYdGpJ$#t1axj#>a>Y~kNSeU5uZ z#bPfi5e$~WJLhH~)W8Iyri*?ggaRd=>(^Vx5P9@jDaXu+-+#G16n~{CoC-2i>M8{< z$I2~7(TaWl05UnjINd)rS%0u23?_b^>e>NRs7>t3Eyhnr|wc_vaHt>LU~YWmFTR~+f1rUyee9xwx85v zi%bo2t0(AAJ?;)pjELzcJrNhJdQ5GF1)QrJ0e0yivk7n2DU5;VOn;-3{rmJ=KM(Yy zY`S0LPoz#Inve-cmksA(0YEdH7hUNf0e|6-+VToXB10iV<%uCUR8-hYz#Vuc59Y8- zd$NuV7RPZ!Vie&5nF^-2N1VE%cIezXHfuw&Q+56FB@@vmIE@~SLQn$Dq%r6PFa@XH zH=nWt1@mK-9puK9D}SRRp7zyp65SLXrRy-L*cheO~2ml!6bm&1Zqs`-vnlhW+H0wT*csko-XwcG#N*gn$K< zEBGWCoV4VeSPtW6v;`9?qbIxnF01-gl{i|j%!1oLdr!205cG2V zr5Wl82`k>QL4V3jtD{O3cU%1jyEE}g(2!Wke-}rC%Ain$7O43+x3kQG;&df84Ii4*s5R1_EGM6@oKle3>i>pM zcfO31hiseOYR#u>W5WNY6X9l|TZsVs$O02~!5*~lntzM@rX&C`tov@f9Euwi?Vto6 zD;#a@eIcPB0aU-aGaKV`zJFQct7QG#`&r2ijU`zG8XgauDF6a$k!0^xeB{UAL@1!J z@urkHrfciF-?a8mtBdo0)CC)gp(8T2*>jWeP5+>v8EwSwtHqCvz`j~Pny`|o8l193 z1^6i+27iV-)}Dyrjsqy1cE8XiCUVV)a-RVPNtxeZ!a@BJiY8oOk-v6bD#nmL*V3LfWh^*{`1XD z&g=K{twAxQ5K!Y&EoziJ9|zKy&?**{0F8e4#D5sNqB1}4et*cT>;Q5WI$utPs!YTv zAQgZH)g_=obMhNm*ps;YY`{^P&a29V-i<}pP%7e0>mB$@@ioOqsx6oExLz;-C3OZK zzD7b-?^C*v#6@)eL=wVD0S!}np2|5>3yM~If!C4&hdEmu>UjLM+1Ne&2MucE>_<{WlR;L3J|)g z1B0TAH9%?DIaj4P29AQl|GYqIz{27v@qc}HrZ^hETmu~PZ}*&E5{!$BL^Pcrl9Gb< zU?pWix>CU#4E0kCqIs7o6&a0IGZ{hBaepV-KUZh0%*IFC0Gf&t&88Rik+xA3qzJID z$EXy6SY`Y(I`t$#I=D3|H2HVK;*Xz-Y{5-l%HJCFi%ZD>6aYdNUIy1*pcXPw=~hI= zRkOD*T0gID&rbNW(Bso#lacp)cqla71o!}%2o-O_-#bJ&pap7YNZ(v!?{%8(jek_K zVq&~5W;So=8UL^r1EdVLMcEG(Mzl3WN9HWZ9Wg3%Jh8JwPFT?^T6x`uVpc0H7!knX2;?31za2MF1zF1S~S1xRRgRU5mZ=Gn1a@)JeaVwecps5*LAlh~+&25TAx2?grr_cRW!QchLUuXz@Z$9vAG zRWfK3UN=9Vi*>iG6+^_F<LX?dNGhKP7GK+-B&)3z-CbPUoqsS1r|<7j zXtw|9Xo##g((z!FXr%H(ix%hOEK_ZFbIz<%0QdnO9r8cX!I%y2&)%gf(GgpU)+J?t z-ie{iyzOPzB`g~Gs~r$SNDJzqka{`Cjpnx_w{wKkV~9<&1MfEGgtJkM%v<9;o5{qa zC;U3NMY!_VUG_^?WCsiB-saO694SxsTCGpdi#GJPiiS5vdF$ zvq>mP@?E*tjaikz3iLnKaGt)`6}>@fGf7BE%6CZR{56+3IbN6(+I3= zMVJwe%&T_kAU?f}W$NcEd)cUQMH+3RQEs8uC&;G%>QrkGmEizdq<<^9%wUBH5tz&c zUO?dN^3m9ObD)jByMVuh-&z9G{oliS7@h(1*J|Y0`RU=<|KPKHa|HgbU4oAdY<>(` z+%#BYft8m_d?{Ac_}4m8Bi@x(DpLpoRxUyGGfHEw2ngp0;?a?hB&3RxOSw9&FaBEJ z;rY5!UuaVY;%ohyy?>7wfE){SjNW@|v_^hmLX`w5vYbuF90=k+0pP2d`vAoCyxNzT zg8N>bI3%ZD?A*U9JS~0sEUD#!c@JbHMPh3Ol)Md3 z-NN@B#!$4QbLWfr&t*gT0KN(wvPp3Cr>Ie~Nh{Q#w@AS8N`EfNKAwwb_dpoEbpL)> z3nLJ+%LRcefiR&(kpZ^v#J|=6m|!F$sVyN@g=TkHvZb@;%kO{)-~B5{g2^IygC_t? z)H2=5-5(l)`SJ5vFuw*x0I$y{f=nZ)+vR;Z?oTC*&!neZfMIdft zm{3BOO+;%v34i5_;%Y@&RI1qn$Hmjdk(8Ck=)I%^9aO-8xS22)*z;?>ifs<{$4ea` zTXiTa5eqT(y<`DNHHPz_on`LwxstfKXTg9Mr-1rLo~^@3ES|KA^N^m$N~9{Aa3!=% zwo0M@RS*LZP9~q+Za5>1_{0j1x7+gnjRkQx5_5kVQ-A3I5ep$I2W!EaYBPxyz>F`IC!kBlb-~TOop%YY~~i`Ky#` zhyYhYUHaO?1S)4F-rZ@z(xankSsp~whyEBFzps{To4Z}#_So6yU1C?fl`6R2SMJHs zhSn_N6MsZTpCS3)CMg#hYzks;y}958`~j@T|Lpc;;dgi#Eah7jDN%Fw?QVWkcKSV= z4@{w9Db>o4wtI&bYh&5U6_Oo5D((dX7D`7_ve~##> zDx*=TV5EX1GWxC(iLHz%@BTVPMHG~RLl|A;@qdc5DgcIQRPnFM3jA@aVlS2YV6{E~ z3h!oM4ZjumUG-pwQ#dtcciWnH1uNtLX~M#BE|vc}yX5cMv52;sAWZ-XjI#Bjt_m_u zg(pXbrE7aQ4k5a%Du8&vd_UXdx%8SLLJ zG=G1A8f2e!vEBK6F__UuK}?wlGyx%B2~V+74>o88phLkekGn{$1m|CE9!8iD1Q)}%&E1&yGf=2C$Z91^}ft-Q2QS&b~c|f zy!mq4O+ceHgwA%L8VvSy5t&0dN(66xx%C?g62Mkj*_wc2e7s+~O%@3%$Y|0!AG*J3D$VyS0>LoxNXU-)TfgRl>pm_Z z3EkER>hT%$6Cp_#nU)p_my5;`>iQrq>VBXZ$;8Vsa#w?`KydR7R%c-_jeoVc(ZXx! zd5^m=7)0bs^wZHBB@`w#O#riKi7bm&hzi=#Ton5c!T9d--qYG*0WPt6>X^B?OyEz!z25&-`C+&qYM{~L2$)hr1L zE-(ZV5@dkMt?~RnSS~@vtAAOLU)FXbU+i5evcw$C_hF+ch>R+95f?!?e*3rU3Eh3V z1c8@J_poM?Pwsn`XcjPpfCdV~&!VR1gf!N!TRgBCfW}K%Ag*zng92K7%@}5dtidY6 zXZe`8%}<7yi+(blj*lEk4;S~J2_;UUW+W)WdY}|9%6KUKRKyn@Mt{F>02+0eQs*%i z31NvqngGR(=T1}ttA#~(HZ%sZJWr=*ik_l0#7*XdjuKs{C_YUekC;oT#-)h1&OeKs z2-)d-N>836=V*s5D!EipeaXC&)IS^*>kWIniZf0Pn=wALVk0_~(MDP1 znqP!#_i;wX94u{73V$t@{s7K2`51Bf+kIrQLAKUKwM%Gd6dkAKIK)aLx@BBSU6Rnx zCn}{ffr8vs0hP=(VKYE?*X$KrIs(O4QnNhspA@hNMGBt3Ni?>Km7p!uFCzgvTJDD0 zC|I;KPPDe8Q~hJVdww#qfo7NSJkd`wu#IAWqtGff&xZ5nkbj2uqZ3n6x(LcO6WiL0 zzx8UW%FrB#Tk5C+dFK`cM<;odiv*ZOZ`N9#;hufaOO@$h+xPeB4c zo(fGrfk$9}myNEIK|lb%+Wf5=+I)CvvY`|A)!wGnzTD=d0>;qGW***JdCm`EMa1Lq z9}LfKgT2eoc7Js>0F6-)*39RzT0lt<*uO1o)8}n3eflPLsYf0_Cz&xFE=dKJ*b;#a zD5zjvAUo95yu{r6xXB-_QS@?I+7t_nBF5N79vym^pcwydQ9!Lut(UKG5vZWCB1EI$ zey+w3;}Le-Z^I?&_E1?zBbREqVYd0~2THf3P>r$pw|`OFaS0#x$|&~rpY?wqY!xjs ztBpYv?#;9lYT^SAHR`C3#u7nB?~q9u#FkTPv7`cMxoU1XUI7FKmH+K9(-k*;H-t$Nd@4jtY+Q)fp75AhR5% z%F4{Soozm`npE%@x&SFHsmv(f`{mEwXO->U=6`d3x0l%}iE#OlSo%4vlf|X&Hwkz} zCt5E!DQ^WQdr5~silWT`UR6G~wf=-mW$goPUaW4kS2yt@w`e(<%gKP`TUzU&42ZD)f{~o#&72(;89iWGJ_5ti?uw9lo0& znt%Tr>_srOg$MEu=T8fmr=pQ>JlYnC(c@Ki7AsYV2VHdL7>?Y2wz@xNbkGJ1#vy5;kIQUq|)7qqIN+` zWw2t6&!1&k6pb2aca%r=oG(`Xada%-fNKF|M(7j{{1*bjUeSczp zTUFIyY@_xtQ5Y}?47<`u7}7ukfoojPk-?)Nk?P97ucc%`2KHJ>>Z8M94Q~41Jo%rC zCPk-aQ z-Bbz>t*oCaAX(=BKvQzyB^f|4wSWA!Q561qpN#(!!-ND9Qxb2(K$HTU%;jwVu8t$p z$M7HsfB|9St2F`OQm9~TkxW4%5*9G_m!3!inyx5ivWTU3GAP^*gvU04H0lj`U6+_M z%kW!i2!^Z|3z6hB$>4!sRGDq-pfCM{5)x9+ojp66j8`EtJ@ir~19}shIDbU$C$Ngp zm5D%&t|tc_UPWRH7lT|x(_VJytq+i>`xIe9%W6d@m>JIs;>)jqt|kQmP>NOS?*9y; z33K|?%!A{2BJ(4S(P z_u!yW1zoI{z6g3VDM!59C8DMme^&$~=18T^-(S2=M0awb6Z@FV1znDX6ry3hzOL4h zctvT#1vXo1K$fVKTkYK!)wf@$lLS)3tG&5dNHB`~<_h2Iw|zJRj(@SvZP?7XqfUh5 zb`-Qymsy=hQU~x7Yi9XBKij|}TIU^0olE+V_QfR?P#1|G!9d4-2qxb`P|+A#DfO{d zLQ#DP$ixVra!(Z``Nd++`+}siHWwL)MD!;FSb8_%WTq&jx?B=;?rN>}Ua&~`tn+k2 zcBAR~{(>~j%7vf(MSpH`z!xJVi3xQLpCXe!&g-q?TI@)|OBb#1RS*do*IFy$Av2wd z;%1o?md-t2pa3qn`=#rHSdq$Bz#NCAKW;LaJcf#ki+-n; zmjq>(78xJ#K&OzK^0SJ;DweO+LFhw%(}&@%=gq45WmG;mtG@Zb3!H%`D z0w2W#91Or!snJAd9GV~@D)}{{jJN=~#(c>$0B9WJ&1X@Y@JmwyTs3v97KDiVbQTU!-)c0dOsdHs>UblBlm)oree24;ds zl$oL}`cr%6ZtVOCumNkL)imm5I-;&8vZ8iyDzfoIryWd0n*N}^?7rF{_QRhek-%85 z(yZF6BVR7U6WPTxxq{oG)@Gwk6=IXoqdnyBCNY&+e1D!M(=EYu00N=bKs}6Tjh2cl zNu>#^o+>`AR!wCUZ`I!DfhVW?f~^WN-FgaX#6Y8}vq+tH%Q|n_24uu4-RgaH5QsLlA?M`&4D$`b&X6 zgb%W4g5vA?7^*a1a+QW&T;_`^u5G}_&P83E^iZ1ICyJ5WX~edp#skHL0lmv+KK!>; z!)g<78mwyd5Kyf}U{|$A6mph~Fm;qYk1lVSWq(3C>)@;BRWE9#E)gasO7v?GHP_jv zjtERDbdgs%OwrK(q zQGeG|XnukDslH;`A`4+wh>c?GfGq*L+%|p{dz^=s zzrNVQCU|dsODqKs#*Dpk^45Et44=bTKz|4*NP^;#4$f~aLY7%;+ou0Y`~^wfF#-|$ z%QyY?0G-3_m6~!-AR(q)LJn%Et2wpHZln<(Dga3E>4-1WtorB^fBS7iGin5Bkh%R> zteo2Ns`_@NRB8|m`XedFcPC&c-}_B3wn+|$MH==$5GiiuA#L_i2_bpECdc3ak$?20 za8)I4{dG!ho4lyaVKxE2O!i`hhk@*FQ4H?z2Ceq1F zKnx{*GBs?}%|I<4Xo>Ux7vv^h@IGEKm}%Yow-}7_O#%_}%L=I}_WQc#SK~!aDWDOk zXc8zAe0ruI-skO6+)SkuP{Gf|8h=;)!LQW0l3rRHC_7w#tumDWJvtU;P}On8tIHF0 zwhIUJuIlvKCI}fFg=qrArkg@KO602Y_cjqyX_5Q)OxmHiK!j+8+t=o$ zC%BRr6E%m=^w1$Fl2tAH-i*$^6i5V8(+{Gu*1Ub6TJV7g*`Fmrm+pdvT7OR+8Ny2= ztBKFSebf;+TQEyyDp!j9zA0yL(V$-D`YzKZ?|^Oks0}-Wj%Ln*2`b$7cbVuk3t}}3 z0tC+R5u_$q+hpWQYJg4VTc2@MnoLqtn;f`O_hMXA7hwQrvq|01HlF$<#xDdV*Dwub zH59|oX^H`?(1J4y5n#<+eScte+9YSQSjk#98L+fb0K>)oK?SQSx*4TcYbv>@Gtg4I z$o>T;0t~Zxs@LUY*^q9^mRYCR0)Lu+Epkta$u)mEm?Z{PIRFa1zu1<`al5JbfLSV5 zL5V9w5DHey8JG~MPc9#+y3fR-UF~S3_7sr82~C8@%IJtK8fkvOe4lLVTA!rFN)V|snE#-rK5tb3 z4nOZl6mN1pph@T{V(*k`j%H!Z7J{H0nym!|$i&oA3C}aqoT8HI1~-3uMA%vdW3(A@ zPF8$F4xz50C^O3@B2 z6$G_;lsa66NYrS++2uM&C$ut6YI*(K-Km_aY zt;q8z0<6M;uzy9J{)~4tC3^uF?1c>#?Z{^mIu;HL`(wiZXx1?TgSx1yn%u0s7lDJ< zadkAg^yL+)*wvUykqPar1fEduZC~za9T#1`K!k+P^+1G;2j4)1l^{@@&Z^g%{#IM8 z0$-eq;S%UHnozYpk=f6-_i^L^f^~gw2c5Y*E*Gl=@P9xECw?A_uLJi*W&dOU+M6GF z0#~H5qOx&r_P5F^3oVoCPemS_ub69qbzt0|{bCo-AWY*3R;kX}7zi9(!+2XDdb3KM}@PQS#G!~j!3tiM?PSG$VL z3KA5M7E%iuqKbd~^ocYVGjj8a5_K3?{_BS$?Zs5kOuDJ?%F$eWXP0p%&0+QwdL=`{ zVf#2ptyffqtH%BEGN}AIHJuuvo8{aA8MGug3MCLmNjODt%B;I7cil}8UBsKCj_Oo= z;X!^~l|Vt9PgRv!qy&$W-k`Gq0Ju`GiCgc?5L_*H00Dne$;v+&k^|R|DOI6A$ zyCZ4r%}(o|a(+6ekN^Qqe^Jl?7#Bc*1WNuWBQ=3rnIN`FiU3%067>d6RiMXGtEw!< z?gCIjl9{TudfE(sCwK~R?~au+P?N~TR*mA6+oG-H zD>E=h)9&FFsvP}JC_s4unSbks>+DMgy7G@6J6 zs&1;xyj3jPlAkzIW7NO`GbL7GdCzBiG1a@(cO`8Rs4f=^-zF5GH+ zsL`YFbeeps*Lg}ni$9hR^*>Q$vwjkuInt{-j8$e5`QU>xRcbUo);B(a%BEtjQrUx4 zby9#~DwF(#j`S29C%%((R(EgwQ~-Yo#{w63lAP0#8M5N)-q;b_Sk@2#^5{w|h22r~1`s@~5aRs&_m=d#D|lCB85EKqsWvJR1fH{2~K<8vfsQ z{r~`Za0Uro&MQTD7a>-%s(0f{Y7^>Jod6}pQnxAgd725nr4_5nFA%8+vN}n&hJplb zRw5*^05H)rU@t>lpz$QA#L9pCx10pJSb!I=FVPevXdPQ>+8vg1ossmgQUzjf}5yKJfQ&c_I@ty(v9Rt&0+*3y5IX4WPk6ILZZr6 z9(AD+oMI((M!M+0c)Cc7O!)}Yy?Rq0OU@Tle8)+ zA1M-1t(=In*;;^QYJY-(FG50DaOn5JSr26@X&a}mQD+@x08%6XK1)CZ=EUw424c^9 z19xKxlI!NN;Q*5fYvX^5UnM%LYet@~NCKA}PNd?SKFTW+X&|5y!HoB8k&$PgG-`lN ze;mN8X_lxQG?t`vl7M3C9i$SM9H0`)SIyG}aJU>_6KTE4N&jjnNxg|JUMGKqAdlk& zQI>r&l>qrBo$ls?b%>s01vK~-R$QRVW36`(0F@{Nofssh^5uU3mZ${gR>{j$0$qW) zpb}d;uS+d^(bA^iCgT$eRzo`@Dx|0cx5AN4Kdkrx9pOL>SI;X2a&!_tT;}G?g+|jb zmGIIxo%BpJzB+(+wy877s(OE*fJjgyrpK)#Aw9pS1e_$essX`|NGjoMRBlqCF3kwd zvcNKly{bM=K4^a{q5i1bH2}8DyvQ(%W8mC(G#MrSFN5&&=?hHf$6t%R%P0j}yr2`M z=&+#UKY;ZX;!MwD&>$&M{ynz2>=J*Q?1)%)B@dsoIVQo z=dO~MdddOnVUz+d?!E>J4aNnA3Lsx85>$N*3B_$jQ(J#f2)xN`Y!B`D{~vD)@QqN) z^LIRZeFDuNg5d%qae<3~2z4=A09IKK(tEpBJSwy~x*=of?xP-`<-(09v?V1#`Hq-@ z!qC=oBUDi&s){9V_L(H!(dXmjb{{9S3d;aCl4=)S-}Nc3Nqc`dFO&PnMH^zA?gVtX zDV4biP%eMR&`YKoi)W8US0gU{q<@+3+tif{j)_TH1m1@&OrAsO@&dYQ?k>|RlMCjZa}i1HxJHBgfHA#b z0+GY(OJ>}3ugt3T>CeccE2tp;8*kTll$y-s*AagPMff0B&qDUrTkrjbQ`511kVz3h z!uxN%KNs$4mA8Hb0Q`Xj57Lv2iU3OP`O!lc+_uW}m@OQ#+4ZX?q58$}&MXSdCM+&81V9 zr(k~~`#)#%)~m7qKoT@7i(Y6wiwajOZ$;u&yRKy-o?%KYP02=1%5Rk>twaa~+E|Yq z*aSP(6hF_d<0=2wPGp%hvZ{*s?%i~jXzh6!JwXk=3t=@8qe}rO`blULFSi%>es+IZ zLAQd}d{jNquQugxl}Z1Tz6Rz`^tVuCK^=cjXog9*tg5aX(>bhjieaHpSJk|~Xsf@5 z0vCz4u)jX7bE_?q zKsNY0O+rf>(F}k9T^xd>YQoEL%?mgz)r*9MNZ>lA${{XZiAZYPT5@GA0r@SGNZ&U;DPO34TR4-9E4!h-zQ*phV-pFes>Nb*+Gf(H`v|A7xop zuff%o8eF42{4EF3z$!|oY?Bl&d5F1UU!x#yEUt!|J&Ly&ojU zKeRz5Gjh$g2i5{up#E}kn8<&ngzx>@ZI1WdL^9p=9T$Np z_GJQrrGg{n@!M`27hwZ|AZy|*S83;{At99z!FWG=d+BSk0BN@^MIRRtji$rb(3@(f z)ATUEeg#O*>QLWx&RD1zKivI5D>lJ@nOBVgN<>gBt z0N65f*+6Pn(^Q{%q|%n!KU_d{8W?~}hjsD+p~ovZn+fC2qm^?QsIO2E#8Efl7zI2S z91TC^1~pXj6_|tP`=U@p3&Jf~5HlJfQ{6R_${>NAz`jVK4)@rjnH?rY%8WzJH5E$B zCk1_NW41|L!z7_vjYNMM!B2_e#3fsufjz1cwZcU@+{12AZsmQ{Z%Q-n2S^aWoPP%A@- zCo&M?U?x+bzSIclNThlM#&Dl6=?fvuA`osMEX?@{tO2e^ARFp_=tb445fR#>$)9EV z;=9F=C&V9`uWZdRh?_PEfPw}tfe=B=Y>0x>t8oM@5?F^XLlgENp%8~X0sWiz4Gzx=!^FsYO6Ag+Kj-~2pRtX<+b|J8UKU+!ltM$J^)lYPklj3CoPQ@ z`XEz>#%GAda8)g>n&SdA1VZObPa}e0ogQB7|NHM zCNocX4E&>2B%sjsL_zum{scgWRJPpX2%5T~5%+=wqoRo4`Q{_SD(px=tY`o;WTo(3 zE|&yWI55&xYhM^Mf&_pycmg^kykEyM5y}Bg0tzX!*O-7)+8|Ek6&@%nBKtW~rkUbz zi0rrA*hzn$egGm*aDXY;w?WEFCz0ZO#ivU{j!+IFBMFz~hIt^Ip|nRRcF#VV7mz@N zvwth$#SSYz-V=aj*Yc zMpW4W1wxvlzz{Y!@*SF`LK!AIj-L4g;9P%n%Omvas3V+$GGIr~6|%+vGvPGZlvw0o zK?dw9&O6n3pWvOUcC3;~`49j~kc++`X@hrX7;K)B9+(g=R_8I7;bbGs5=OCU%5yYJL$5i5b5K_)^18dcu3U6O(> z?pOrlK{_O-7>F7b16Tp^1zOZQAc3!^Om<-&p~)5lvlV2)Sd$csx*HEe6*Ou4?2L{zt9K45KAQ&Cj<$Fq9|O+O1sG>A2HRbt>d7aTDTFKnFZxx5S*8J*Sg-_m1q`gLN}+<&4h7T&&nN|e z;LbLIHVcd{=&fKogao|6PO}%-4N8Wi$X@oTr1?8Gs9H;^Bdlom)vv3Im`eUI7Y(up zDA@vbyFD+UK};5lx(#2M-CcjG56W6|9(_hA70m)f1n_?FYel~WwQdNmv%I3-G+K1^ z#aT#7sZhz?zym+r1S5r9`T_JRzx=FMObGKm7_ENBIKpW68A39uD!>w+sN}m?NWoU! z^JWO>!?p@SeUkX{x{^Ibg|Dao6WykUFkuiK+Kir<_Yxo$=~dh7+2VfzeyUmf-7T~) z>dFKkgUk1Jq8T)xBB?T`mNDhH`APs|>wtkF)?Zo9&iL?xctNGK+PMJtg&#+gZtgH!lcVXMT& zl}cq&>ZMec`&V;syVELllnMH`#c?At{*^MYgIh4YPQqmcOcC$n%=hH0WWkH(oXRIb zwb?XEh6Xjhygz@2Y(&m&`${Fv185e+Tn7ONgU(Lev3*w~CUiFaUe@vf~@f z(%YI}bz9v^_v<(z7lE6zf(GT>?m@)OvKEQJEaPkn&TfAO|7;s_gGx)ui$={x{}mqJ zfaoQ;zV!WQ8q-QD+(cRyS+QNVK`gwKtTNI)Y;4;>xuDLG0_UEg%mbcn=;_arfI9_G zB7OesL>K**vsfsaa~Z+e#{f5!@FedqckdDct;?3I>ZO+>%P1gbBEV7m-Efor)Wrp( zVdH$6ef)nTiXQ6-NjY2r7F|D&-J-=eRUh|Csz^qXcoS?_Q~SywHrV2$rG4c>uEhk~ z&xHVrhGjEbO$1xh!us}{+u^O-E+p4{eJCnObc7&Ku-_H0s{~XC#eWT4WiUzewt) z@Y#23fB`xOtll#$&nW+!P|(y60Q;h0-xlq)?RXey2W#Gw5`XH7PE#GxZvNk7x6%Xw zQ9gf20B2Cjc88;Cm*8V4zbv0m{`BA={O5b!3869P+VMmvstw3h_@`U}_vR_E7icQi z)ElJvzs3Nb*m@KyJ053Srfb)Z_h~KQu>mo%UfE$Gu6S(4{vlR}g5(edUkZQ4z8HIb5iu&O&-AJeg2XWda zQXk8E3-}`>0^vC3-ZG0o(|M#}0NlV4uVHg=h>QReY+{S0K#X#ag4?LO2zN&{S)f_6 zpklFI;>iO{OO#u*pHa>t#|kqru8M!Mzk8Gl^40W!T9TcovY`EwN%X7$DuL-=g`|Hq zU@OKuTSD;QzaIJIeo+$HaF0Q2TpW^v7;n3o{E8`iY%v)j_aaaal7u`z65_ohJt9yr zSs2GyAOPNxayi%1j#VRDZD8w3*rQ+CUjJ8X!RBayT@eI}TcC>|NUQS7BYJ-XM-w|L z8uWLAq9(b^b~&gmRpQNE&LZWU{X!QFGcih~R#~ZIpLrkx+pXJb=6sN{E~gZk=FYME z9hm@}H@uQ}37tZ}wtJqEaTcvYFlt{Q6M1Oskwd~}2?MlAZU84slFNVy)&C@;l>lto zMIeep;K`Q+E-BKNdEZ?LHFSSFW^-w(Sp^T67%E+kZW(Z>6Fm=5AZ=sdkJ5@?e*RO$ z(`pt&sLDVBoKyrl))<)>@@yf^Z{KOAO0opA&=h2p0KV6q`xpfF4<0{O7s+4a7wV|m zNi`PlY{6J~iYy590P)}=YIBhQS-RDu8m|#uPNb*lV(J2#Q@)3-v)O-2&tz1B39>Fq z{#@<_8IAx9jn8VuMLX9&5$fjVncBSXRkZgbF2!}EPznV5MU0||c0fh;)qssVz9j#Q5Btm`hO$=}U6YXAB zOUlAd=oGjrJ3T!x6{w8cP2rqCxD5zJxn$2GhmZaMUG2Y+X(!$t@`TbgJcTSGH16(4 zlm4FG5TV`Lc#DAw3(p9$UI@_jGN;9K5cGd?W%K5UkPrzl_)ccm^xBnuK1#b<&u99D`(hg_3IhoIhlHWSLe5ckP(Oq#t;fy$aDubt_Gbjp6d2_a*~*} zN8bwkAcF378n}>HOyg5UUJ|2R37FuO9q1rU`Q$lZh37RRUqGMI{EOW%`MmuMW=H@f zG{~gR*M} zNWcKUp^Z^C6I(fP@Pmo82H%f?RYLtK6irqdr_*(8r>~(T?)4B|1v|h-LR1y%hl~-6 zxmSR0YZ!sdQJE1J$K`<#5W2cWA`qP@I0}}T{!_zbx=enKis>aK@B8w?{lr#zATPU= zhzxx5Q5b&!DBSI!i#4y(7KhnueUq|aU`mi(@S!v7O8pl~@gGh;LnEJ1=XW3ZD-a8X z!)^b%=XbVA0A3lnP+bY8fV;?~P^c4jFqB1lq5uX}>CV>jgX^14-=f){vugoiGy;#X zZ2l#x8Q{J1A*dw4RWw88^Z4PMj{$h*aJ%!U{%wB?f6Vvm>9H@J$vHstW@cQJo z`|fh9J61nJ024fg@~tt5X~S6!5y)BS2b2X;ARnN7Vm7Py5PCX^X`gE<^ZfOH*~BtY zG(TeACmw%CHI*CeNu4DP%?}Mq@<=KC$wbOlkpbtMG?rto`nmk70iqeHoc)NEhK(iaP z)I`&j{09Fp0!1kmOlnt>@hQEX;`C?FCPsfay@d$pV+-+3s_Igo2_mD%P%IG;T~tUj zt#@;tj%~N|O|D0d1rGJ^G>S&xMizWyWW^g8F|X z+^CMoLEJTM33;hxfL)*6v-N>uHW`hLmcZ*Z8qr-LNF)I=nl%T+3g~`r;n^C8`JIM0 zr{xt~U?Y_;L?uD!B@Ed!E039}De^~E<-mvq^Z-}@2lo!r0t2<)C?Nca1YiEYe}b+$ z8uv^YY|)FRp?Ezh?$T0N>5;RD#ZrGiqcn(IbF?r`I)G7uUk2u-x2QsOGnM>X51|4m zz7YfKvZ^&0#8$oA@qO0+0sD74N34K(2`Ny=sz3leZ{DS6$KGDlh*Dz!1^0T02Guzv z06)#Bu-yq%A!UgJh&=#)id!|1&^xyJ%9s0eXtj%0z)i^h6#La|{)-MTC?|jZXS4X5 z8i)+$0zA?H0n7Xi?#CS>&FTA-1hx}Itbz~S|0dZ+%J`7y{1Qgk4^Xo;2S z=JcRh06X7)XYjNuGMOk)wLll%OqqS3)`V;xVk4r8lsOJVx#q8S58r=whx|5gG`HDb zVa@BIPU7Am9VdJ3xM6S>gVKO^eD4zqgcu6I!2ksQLNOv+p?d@hzbkNW@;W-1F05QE z0rhx|d0p;!0$Iev{`j>QN;6x9;$m_ zfg}hS%DmS}0#koND)X7J02&NUG!>eA5$X+(S?2~aTB7s!q6CNlP3d)Ol@hnI+sPTT zN5>H?;H<+D+prpg7f_u8VhyygMZV%J0$2|lG>S+f0p7&KR^^2jxjOlET4HHnq>_|C z?XVSLIK1@)Na|j2FI~9A77C8nrleIrLuzwv8reA<0JVQe6MbR3(q2$bJk~K(Efu2U z=xQ7~WOcm|Hw_AI%8Z_Ijpm&%jEDh52{O1-HOv%P$}Amx3P=66(j!b>MoM|m&{pYyN?+_1Zqjrrjqke0db9&T)!?}SJ{f{r5tmN zn{2GBDN`wdVXsK>@*)IqPD_w%e)V(_&V!4?2-|-={!JLgyYKtT_wu1Q`2ROhsffuS z00tR+{lEP-o-1&wP(I16XPYmOeVkqk<&`yh3LtT9T2pW4gCaT%dmf2Y?`7G%4>M%<&A}6aH!@18597JN*$3c z_qx?CMM2T{JlMhk`oI7%S~vo~UdFwn+(yr6oeZE=zglu4#sOcvRNVq&YO%^Mm@3GK zxEfR^lX(Sm!vPmV4GD>|Mm&l>cYq8dXv`05a-#Km%H>@PH%o+;u391kXZWq@DX=Y$ZYc$KY~V>M)0#s=9p{ zn;Y*d?3GB?)gL_5ry9Z@17GF3GPukaO!ZCMc(mYYh8`r*M}%|J7=peOf; zSYkh(t%Lg~Dy|byqSdw8bXnaZ+dF@$cwf5d@0#Gfa6(=H{i+ZnYyT-s<~+RuHEY%9 z@(A$&r*)i<>PIwuN$hB0988|vBd~_`z;rF3z$mj5HBbQZ@lY>Zzu+Eti{jiw7k=jB zNPV~^fJrs0+`r1a%`?s4&lsMGxuW&eB6QSTtfOWDSy>>ZrA@%j4MS&#ge-p-G5#ql z(Et<0Uj-h)t_-@w9Jq1ddL)7nAcBXg!^|YWEdHWzRUZ9pA?O^0qXfo}90Qx~YEJ=c zfo9xYUJY2SNW`M!H6{-)NBEE*9K3R=;r=gSM*V2!~=!v z6%0IQ2Ruv=VyMOkMLK(;7Be3%OV9+zVxj-GJBFg)ebf@ zv{3F14}2#SC8gg$7m#-F|^K!Lin>ET(^RzS}HVGc&+F z4{sqc&ZcKtwM&B&_0a{i5IaHTe?F!i}XHD8~ zPys0&a2Xd?DCu>4NLJM29rK!dp{!y2nGT=0O-br2HUtisD@Qq?1kU|Ij=!1nJfIZO zWWNPd=@HpZg-hR4Kr1mCB-0Ufnn#VCls2+O8wbSteO>~gug!l7tL?A=mb0pF^!;va z>gp!6NWEy^8LhlkHdo2UnQNXl2Tz}#sBUc_KiUTu>DDZ_A&{@j-AABwP)+w%&HcL) zmVQPQ;LM^sm0Z!%a&Xup8u3Pz(!k`-TB{OpXA4146bzIrhba;Ju%25WDFMbB3*ANf zsj=kfTpq(+NlAZxMl%EwQ%G3GaPr9gKmukEqA-w_U7@V)7%gZ70Rh{p$hf*xh^v}A z|K~ta%8zb)dMT%%a2T3 zRwz~JGOidT`B9#lc?dq(aCF6PSJ%tQ(|ubwh44CRex`rmK0c>6R63cZ4H5i%ghUAt zrk`npyBIyt+B`<@)$q=|`ahxa8s{_!_)1PU#fO0#gg_{B0}!J7Xa#Gq``dD1e%TWw zw1BuVQfm$1O$Q{p~pp7_(CR^|FRDci!YA@pQCy# z(0=1;czA!y5{-Cw`vgB;RFJee0~3kw`k-=&!R1T;!xW%}ru7P9|F-=_Xa%*C*!ih!)`VQfE1-Lf#i7)X&lC!S+evpP*029$5f}Jfs zh!PVa*`$_PiO?iquYhd3AKm2QMK4bIm9_@>tjvEu088-0q4labZ*AUCqYKq`T&Vie zyYd%uo!!8IJ3>{TggGYD_64f)DcfRS#}aH83jixcBuote74pX~`d3vhWk7!cDbn5* zp-{3-jF$Qn&=(-65=knfUE8oIw@tZctP=vPZ99}hW^xo*Z7wEO#9H)_%b*e_pBza4 z_ga4?u3(@Z(j&2Q*k`tDyv9VlLe61grnPxiIMmrGR%!oC*kyqqucQH-5hSWd=$$h~ z9)MM#pj!Fao!yFK{*(!1<<=wx4|bfW69q@!3=TR#)sTB6s^`IgYJ5bP4KPv)uvIhq zoz+(H?gT0EuCQo-(u1X=Q9~Ah{ir7{ zIWHckYQw7i_a0u)fdP%fH4WbAufS%2bu`ev!*PP9&SZj))pno(9(en{aolwYzZ@jy zf(Ra@*<1ypgWKtn^EP2~I_=Ruz|ysv-f<}zfQKJtFy`}H=gASxPO7gt|DgFe$xDAJ z|2F}*F!&*uf(BUZF-#37q2$K{o^DytoM$^Ts`XzfI=+~G_G{<1Rc}ogP%-iGGi2VO z;Wl!wLBsQ^F%FoZUpj>JG{HPw6G77bIqJP0VF$Vli~PKQQNDGa!B%#yKD|dNA%7nQ z9!UkhafDObHu-W!dWv%r2`3BqV*7uda}DiWGv=kyVo3)3dO#4D>28Ig1+VIyk_1Cg zw4>R)R>WT7rtF^zm5Z{g&?j==I&UzV(!qY92849Fm{C%-G4U1DR+B%dl?Wexp}NSF zA`s|=ii`B!{f;^Ag2g1FxD!tSMx9nlsTvr?Z(&9xiKoma6#?hpDuiIl0q4Bw~Y$Jur0 zISk232TX7*uB?$zKk>c53Yb{r7u(f@(^7~WgafQVK$6Z4o@yIDcsB|3&&#LCoZR66 z)F=kSXen$b_l%)PjW>~1<&l5DrLT2;ii~$1G$H|Yg>1ihxi{LgZpgC8c+32p5HZ(% zytc*X4aIF!=@ENg%cH+iB2_6`N#CF|3XSO&W%l??rx-)3s7dNnUin+$hNDhY?%jWa zXGP-7z)o*#VO}(_E1XX8Ob2=$5bt4C9)Hp5bJ;BLg>#xesD24UYM+{2;D zyXL&!K$e91ppgLsDiBoRa{K=*86kAT=Dimfs(cEQ89*R>px%K4Y8S15M!gWae4GAu zvs@N`+vm?<1xx15_efXUMf)w?m>0lw<{Ms8{&%fn?(ujil5^I}#HzmR_|s@OqvX$M zmy=Rz-yQSXdc2TRPh@|ElSe?~0ZBE4P}AJEv?^(>DwSn(Njdr|CmVu-TIu9KK)nbB z5m35VX+jt99j#KCJykvmKNdW`^IDWn7}<1j92E+|0{6@&IQr=x4xAVOsrTXQCKHn$rG$SGwzLTAetMEj$t4%6 zc{)Xp!b~-uLf`-sOjx7DZ@bdP0%3ZVq6c%=l#ziAM?@9b(nO9Dk>~(93ECm1y8Ok9 zwz}R>4pgwp%qN0<28%bDS=G|CVF~IhAIRD5&G-tE#8!v2mUl!pr7K8Ib#tgvh^aY&vii8W`AV~oN ztH9JeaQ0Og&_JS41t$&HI0eMk7R(wY&={iiaRYB@a$`4>sv#4-#CRGN1L73m8l<$t ziNp91^z@_o8s$K7P!`3&{eQpe$Y6wNut7b5ooqYItl@w95T(Wq9@@hZ?R!AZZW1W3 zZpTh)FMd%E9C1|=P-3Y;Mk{g z=;6xZiS>W7uW$ORc_iQ$&MTEj{+KWY*H4>Mi}CD0!>n{O@UxFV7!FQxI8M}J?k(>Thq)D!TdB&2{@Ypn z1oVILu8iBwH}N%0kI^*;^#E}nPaa|Jf_ATXITOHnm7dWZMV0~uX|D(FeoVF8ngmBg zGn{Yn_Wr;tk0pQ$P;bY`TO`)dM)E3Ot$(bU6@qT!MO8Yftcn%>Uu*=$a+Mo)BgNU& zfvc3E;PS*Ud^HxAdic!LvUk7xH@TPh){%b)m?~w#S%x_UgRKAT%=qTgp}O8E2jfjS z92{Kq<@&H|n{UxY%8+{LoS7g3dMCO3MNS}7=rWAY>`9FR7jjZvrvL!W+VT+)^4672 zwwB5VQ6LB}U+%ISMD5(iLdFm$_0-pDcNH2`K?OXJ0>U;)kU>0x0Si!=Bv-5qY|DSl zdkUG3{tctK)+7q9+}BF~yRZZbnhoO?BH_RT$xMgp3ixM`ML!_|d@BlOdpI=z+yVTA zUBoF3!x%TgSEZjU0D*J)|NTG|c7Ym9fdi8_RB6R_G@0zEVRwZ{eXvwKE;>iLGH5;m z<5YbZ-~jQB>_Cm3M#>LQQrJmcfPjBi%TAn}^i>*%w`S%Qq$L1>=gOi?3;_d}dt5S_ zcI24j_8{EPNDwcWE6tcLXC{9n4RY4Mtw*4jVAV=2ln^cm=*WZ#ux!loWQEpC2?PFW zA+ph$-p#q^zyYQSgJ{GsQwqq1##TLZ{cq?B*aK;`&5_nCioB;stu%~&`&+mx@GG{DdL$>Hj@oO^CmFD#74Q5qV1dlg zlHhakJqyea3Y}msno~B_DX!c{?o{lzjLd?w6BBM&3(pb6tQZcPJm{=WiAm> zu@UM4ZT(dn@IF+j8( z=!2cPL;zGf4(&z2=m*mQa$$)ikW2s2c{VF@i$vkbfid1A(bESa!L0+~Xz6V=Ib)@nd-fF+Tqv>8dbqelqpFo-* zzKs1{Rc5rW(gfe@&6dRiWC#>wM;@qaR9v}b-eqYhu40pz>6oxaj9&VyE~gCAhCSb2 z$g22s@Faw3T~&Vr7kVR!5&6qN7Upx8Q_P>6lT-d)yLe5KY@a8Q`zaJ=WLS4EI<|TM zqcaW&2j3)3!eJ5;UZ2y@ME{eIQsW8mNW$?~nJO~aT(Wem-L%i)IMB!-88sIXEd|d4 z5x_A+cq&}Q?HXc4Lf5zo(04RlYD8YF!}=-!0q*&gMP+{`SZ;KeGn-M%#+!BhQ|L#Mzd8abd<=)b57 z7!W07!rjxdfgT7KeE^@a^!V*QbHr5rB*6nkbc8@<=evG4iZrs0h#Jpd5YGzz8mWhw z_C2BI67+vp8+gbHpSXs&6uCzZNX+*FVS_~@O>zDx$X=obxQ#W&#v?ZN45UzzOno=Y zA{Ks+WY0mZ&ZOkn``^s&A>{-g<%5LZ~GF?PJ`+M z3Q^Xaknvk-R5`QMB*2nxK_}1(3@0OC8!EYKHn_V5r{m zIGBHirB%d_$!F8WKck)`xXO9#8o>7C058W11ffE+E$HsjQYwWHPOI8euPBoA={d_Z zt}BLD&BR@e1eemFdsUzlnhRW6>EXNA|nPc%IO{F_goxT=5T zoK!f}CFycvM0y=48R`n4Y*c3l+M@L0ARuU}cfTAlll=8f${sxEFo@c5xSL0fNSJpxOjm3ZBPM&3O-C`#C$Tt(;zk`q!WcdnZ?K}Q`YA4Y= z|ACU;0(ZQ)T6aGMi=ra+lyabZWbL(V|2nUk^W&wQw9<;1h}>~kcc+O78V}cg`sI6G z)Z8|%s(h_C&+$HZ0A#->G@@*Sl-vkzOze3r4DOhQ%M~aV6~A#_oRR>A`jvko3VzkR zx}oqIYD`z7YNGFe0{{DO&xggzrq%nxTWJrfO~?cqF62k-kD%^=Kw&v}6{u_XXF<%O zXLy>2g~%cL`O&3A^<`oI2WNTp=;cw=%1Em*`WZ5CjETy@Z^3=lIijx~3p-%)^yiqu z=f|v&OVzpdQCv=rIsiAL4Vr&|1KAb%5gW1qT+KirP%pd>WCh1vXW{ajWnS6~OaW(T ztn{I4(}`|_@@?Y z{A%@gz*9#sZ}N$C1bdh(F+!g)SE>q(KpXqEE96BZlD4S& z(&WKElTN<-d1GXNO02-j1r6|yY~2+|!1{vT03FLYOcit?;WkAN&AYb2xSjPEsH^7q zf?HO`@Br^3oaKIi0P=t1d;#xCgWqpZVjIDwMz)u#_~yz14P{nFGJ*f# z_&;?3yRK-(@d+$Gz*Z)Aa%XQJ4r&h*!toBgx(6pSuZI|@=m!9v$Rooa241^8HK;9Y zrp>8~l|^&{E-mps@Nf9?p_=kPAAaaBdE=Mk_4OjNp0KA-4KaU{tn~?ciGlaXaek1| zrdy_ibMlaByJn6#A*t_*CZpRph%ZDY7C6#AC@I8LVU);5z?mLA7vfBO)kx_!reh|+ z+Pc=NKVT7?z9Tn3u!P#CAQS$rPVcQe2nEG-iVBDX-7m}qD?L4HcNGv0=qe$gsO&x& zm*dfpjeXk8W;1_N{1tCj6kexl6oMdwk(+-hHp)yI8=ap+3jdKPb1h}3 z;OfMKKbnHL?SmW&a|||ZT{wx3Cw|Tc#LdPKZH3i1{^+y3ZT4lyQ757S0|MFgMV?y> zA!Mg?seqFK)ugvnFq+?lOYhrRl~uAe<4PBRDbjSbMl|(*ipY4$Jp*nc{vALTsfRE) zxjOZjP%3{Yk30~P(bk~x5Ca0L=_~k{jUg;mKIJ+{jpphfY!gf1Lwh|JtcleqP#^+tscSAb0alOH4?a?UGk zCVrnQ6*wsp?`}^5=H1B%IdEIG_Hr2x2RKpa1kiaWRzfhnrUL^@lTZz9itQW#=)VXY zNT3qzl!}8C0n>Hj5IYDgj>cX(j`Hr)_m^F##n7ktW<$n01NctSRBI2A08E~#R|m4` zCwhPTww^{O@bf?5GV*I zL@9a51^@(|2rgbg2a9+MF`-mqju7*b3nHWG)*LkBSc*A|td>&uSd07;bN~}M3b_qg zMO0z{l^a#AvX+G`5yHM`4I#pxVJs+2QZ|3j{KOCn^Z+OL}@Y{;u0+ zvq>}q4QGfN5Q2bcc3n0pD}{q}5i5X+S?PqYVhI{P6jIChhQ=^`!TC6uBEv1%$pkmp zJ|94gs}Ns$@QVE!td65=3=Efv03?+Nv0W;%jdRNqtwISEQ@8*ZygpMC>hSrcj%6h#A)~mJY5&5c|Wk;^#S6v}5 z>z_++#>RrXI&?#~1i(YJityV-NT!rRI>jO~_3PBGRzAZj1q+&WcA5oP`MiIWhobpO zoWSdJ1n$H2flQ_MD5F%Q0t6dw=DP~oYks?_?(!dkLH3lL%Y_Fj1p}o6*`~C|ErCEzsT3Z5bz+p8RvOZq`8-g8rzRn#7DegU;gBO;uVVDr-pLtN zFoOj(J*=UrkwF{2>zquYb*L|+x(S}D;A8q;UFKOb00=wZ+aksTm??jV!EkMf)KneQ z@JWA-`XP0Kj4qVxo+eA0L9dgtJ7e@;_C%VmDXPUkRA7E^*c}{B<1k0^l}=Q< zvs2oWhD6#!&xa!EEB}C8@r^+wGk+>l=iVF+i2zeTtiL5i&QFXq7^bj9cbv3|bZCX{ zAmDP*JKeAr3Z{tt&<(L;D95F(=yakTu?6lbMzbw!NE9~JtWhHp*$)wavj_x0o)TJq zX8QJhg=M4acyG7bomr5o@|9mRjA_YIp+O+H1P7!t{l2`O>v7>%LZh;jaLF?#3@ng) z`+y|6YJ_~`4>&?_eZNv1fC>S@AhSDt66lD4ZfI<~e!ziXAQndmF_N+(>QhSD!1&pYk9N`ZTYY<+DWP5Dn1cGUQ{9eFaM@?2wAg;J2 zih8j4wS+?HbH^%nR5?tO82v?}7K3RzulxSUKLC!6H97}`BD>-D_xZX5$d zA_H7epjJTxv$gOH;}b2UjdO)S`zaq%ON3ngyz$8(rKTj2PXI_E&VB0#5`D}jPBua& zS?8cPWPoIG$j8c4`rP!GwUC^hvyflG0D}P($LfLWXe#`Fpz;3rjM&u*m>!UzekK zYznp-7OsGQD%S$W9;&m4tOx{INjHqQegYAxlB)q{B=B<}Ev91=CaOtC+4pW!OX2f8 z?N%mLjHy#44i;Ja7JtqpBLvH`#1)@pcS5`@0p&v9+}dUa<9NCj949wOn?cFc-rvp} zIZ)@f(H7Uz`NQXa-8{7LA}n0i1Jv@1Wr00}*lCP^#~9;^&>v{tEg$d@A**bEvF;X$ z)#z})d2rogwEx5Melh;+n9STsfOb*?V)k!0f{t>48rYzFUC)&Oh)%j+0AM*EoPwQc z^=t^}3b)0VY(y6e!m+X)X$R&PoBl)wsZ;QmnX#xTIe2Z@MzfG|m!^(3yN02Ih@P&~MqCEQ#Y1RP{6yN4+W7x#G@Z>RvDCk}}hkW4Hi zzT~vNh~xCtRpVxv`Fz?XKH=H0!4Z_jvjpIO18q7tBCKcTe}WQZjzVxKb_KOh&|Kf( zAYHl)-E0+A@9FQs>-CbgKkZv3@*7T6jX z$PM!fC{kdi5iq57Yb@J5Rflcu7EsCLsYE*vJ@YG@B3(4OGPjggB}}nspRiB zHo#Pz+87LB^TXRb{*Az``9AE4*$%lEB$oAM;ny6dRB55@C+|@3OEL>r zztIUufeSOwqD;DfyCVi>Ot0U}|8A$+3zbma9Oyi)A)_US^AtvmE?A=#%F-l(;cp-l z_~kCSSye(sR`!vnBg{v^L%mfX_>Tm&T(XiGg+H8@PK;TO1BzjQ;8M}*7`Ww2>y#l~)tc`w+1+ajSEWK0h6+L`^)v|cxF9xGK z5bJd=3Q3rJg(1=RZUun-i?rf-*q2nciSHns^P-&m_r6SsAYDKM!z|jLZ=3=S)@5*< z%Cq2R!5biU(GLn;BR-xQ)B@{xBF%c#zkl4hpngON z`*fcR#_g%Vmul$3FV1g&b$#$|i_SU=W{^oYyO+=({FrT(=-lTaRu0OeqwQvb)3XF^ zJe1ukKN=zV>K`uwvdrA=>2}A680-dC#GoCAYA9H2mySfPRH*zW*RzI;Y^d#5JQ&cHvkzmOYQzxW<;Ht8XN{q9b8cHvX z;%CWRCR8!GxQfC;6_JeCWTBGd0PW@6AcHit-jV&$1o(!Iy!UHTsi6-zl(qPRR0sef z04$WoXDYCLYj@N^0HlOiB$gQc_9P_N+lRF2)DT8pI`@iU=SW#lsC+q(PboGQmaigd z_|mmV1|qg1`~bawDhMEM#9w}0-me(nmb_|@2x2|VMIbX(=l%zqjh&iug?a>bpI3|- z`f;vH6Q5QC`tGWOJ1@aMcHu%1AX7Mc@^e0*f(O$>dMF(WVegxfx=VDCJ+K=tF?Fs# z<-lt8rnk-^yMk=(87u9cafsITEY-A{{soY7Hf)nc=@O5BI0i2FH?eAXk26qxoFPZ*=b*T=zz79lHQQW-G_q;0X zBT9Gn4M4kp-dCYIcHpstf$u?k5v6@}ZP@TuP_85b%R%^;=pGyT2mvePAV-RmpE$|< zsD^moaj<+WPBin?>MEY`@KuV0sJ|!b030jgAaIqfY#m~wpH}`T+|7?Q{z`5~1sY%f zerED9zJLKbEa|wyXvZJ+E5=HPx#-Fxm(hFSurX$TtO2^s`LT)&A1I1rf>Cai_m6fH zE@3msVr$fFZNFkk1>ELA?X7&WY+vn@dJG(;Us;drp?l7YqtWh3e8~_&b0X&)Km}fi zf`06(1d>nyfiqzp<-ER4Cr3=eT80Tj-&0l-zF{Uw`dpF=#REhl{{SvtTrzbaOi~N# zhXY4{(^s9p6*B6rcv&iq(KzP~1*svD@e1xz1NEdZ}@mtuKOEXsHLAJvJ`OjAj*5+qKjm38EUo8=5oy)!I#s4d*`#4X5IH& zIs|**6R(Jy>-olB61ejSZ9;kPZx87V%~Iljpc1V7z`qW=+0$__{rWBYa7iOcK*>SG z24-by?f`OpH)#XZU+CK>39ZGhp#;K5U^V~(HQNM)7Gfylru=j5=&K8Zl(d&^e{XEs zz-8Xw{G6G;@45+EvoXnEjJ+gPis%Rt+Xcgwui`tNfA-IK8#P|#{sgSTNye%eP)PQF zg*dy1z;4oz0B-EimgU5MEzZxLX@y@UVs{ke-!a11n|mGUZ8EC9QG9w83ISoz-MaV+;hSJl437I{J4od&B}jo?g%VO4}xwg_N0QO^#DBJj)+44t~}qp z0HJK>CKlh31Peu@f6#a;Eym@mEgM>3R2cp7qtc=`YW^n4AF-;0odc0TA6LwO#*X0c z^j)+pMG*z5zBDrUFC+5s#iu7Y*$S>g$YYcP=y)Qow)Uvm?i+VSDU+UZZD1{2_d;Vd zQ2S9ku1<0xpAY2PK`MK6J1FRoGs5Kr9;%~L&V!`%6tPF&M7|&AiJcdO^CpcI%Dl zMinmLCw!I9>uUW70vymln8h{|wNg8GlQI0zv1EGxvDHUib65U_iVCr@x89Ej`ZVfO zzs>B^?~340e=cd~{LLhRK+Pxys(+?6T-_hJIDsee3OvAdlTMEudkUX_q;|VZDn
p501Z-9KsZ_D+Ex$=Xx{W^8!ytOMux&c$35=46-gww(c-`#OO` zP*HdJ;Zh`>*&6ri3KGCmd9~}dy^$J_H^kZrvsGvx7 zS&jeG3`fmK5Z49s41gM&@8b?E=%K?91>EX+07QG!BqKEf?r5nffiEiAu4J=Q@fOVk zJNbOZ3ekTNHOV!?$$o)ThIxF$jLVh)!AqtBFS)EZiQ`9qX}e^i8zdL`#Qr94&{SmU zCl^(hgCDNV=@0@*5O zdIr#q-dK=IKOdE3s$K2r^gv0c(ABPjTIa+hfsEb{q#`_|fFK-4l@VMP?qTr$j59t; zAv_8}L#7me`_G*L{`ar>r{KV4hO@QG1W3h>=R&W62j4!L?A0&*x>oo&IjiY?Ge5bT}F#P zt{(2ZuL$q~ih^)pRJ7MI6Ht91FW^4OyX5NMQy=Vq%6T{z&&0SJp8>Q)aI#~-e-A&=uuf(i?y?5dNq1DeK*9<%sP7(+YB2{- zPntL--@aG<+`+o_PN*;aec1Y8Sq_jt`Rw~jt*4eQgzt;)oXTZzeSG}4&Of*7wK->o0 zRp-3``vD5Z&)Ck*3vW0@=~Z3~-$~U9PMU5Gbr)jG6*jUc471<-OtrA1Isp8=dzz!u zp>4!p93cCcv=(Qwme~wQi+4~B6nC4SvgN6Np{sq<;A*)Hw+cIi0%R2sR->-*m(WxG zfd$O-B68q9&uV*73FvULp9MoV=gPNbgTT*u5qp3<$#?$=1V%yW08mSRH3tn281)b* zKqu~q%)kSvau5#Z)Sg8*6+Met9H`Yu5cX-3%djmFuGUH&EX>2FfPpLIeEM^9XPT;i zKDB2>Qwe}Ru4p0xl@l&h>U5r2c<=xOw#*jUiLnNOLNPWD`uzla-mA4AEAusWQ-p%+ z#ZMC33$UXx5YwGLKxv753=NFy9|RA#URw}mCLvOgs#S~yBZtBLm0UGQ_8hTly)?x~ zCG~xHEx8*5TiN{p1bAWK6rS*-@2WO`yAp0oE$3B>Riu3tciFZ_h=WVbA#93OF$xaw`1+CgWRReRjgHR@Vf7#_(?= z92ftULF~6qLM2(I5X9y@q(>Qwp3I8)%sChZ|B+8IP&g= z#yEhBFY73@em-|4xrspQ}u=4e1MB zo59W?4+;t(oyOn-lY*p-+y$!CX*4I6OZli8j2Ze8^G$Qw85;82 z?L37!{^g>q+!Y&^zMnev;$%0$u;JeQJ5TAM#>Fuh^gzy{Ijf6WqY6HMS)OUIT{~ip za%YOSd?Kf}TRi*>q(GZ;iuBGc$?|sULu6KGW1{p=` zl6im2=L@7dq>Z@R0tMH+vYnESr7YlqSj_5Kf7kv9cWoA{0pWkK_3O$Mqj!^J;C0U5 zov&$DV;oI@>L3=AZk#KB*4@T|V?j$u0AWV+w+VEAaqC$X95M&DMb@%3BfJZJd)Ndu z*E4ii=!DCm7RM!D2-k+8{2^?=bka*#0egC*V-OmmseQq1(|wQNJNOn!3#KHxLNYnN z@gQ1xwXHQvRC7Y}stY*qb<=>UOt)U&p4HNeU?zZ%c-kBzQ9e+AVtyKJ93RMjtizTw z<__;xmgSBI{(EPDy(@zt0${9lK7b?}j1o7QmuQ<8(zGRmw2rdNXBhY*x?bg>oXABYet z@Af($m($~bo)Z^!=EgtoS53$(;qn@Vs|^9fRuNoIL&+@v9Vc_*p89!vwUeC#bg1w( z7C#VI$kc+%1I|Rcc(jnPptlg~YFp7c@cXwI+6JS*rs_?9+N0SKZ5pH&(V5j6phv26 z!%kxn982^Js6Vp5(elL}{P=&PBluOpCNqwvwX;yuXlz6#YuP9ooB^M!r@3ncCdDRY z9e36Sz2;o&>W|G;BZF^P6zTu4htVm8iB-ZFZqFuV5y(Gf*j1bev6STTs0LJjwJ;7F z80G*%cP!a|5<4^keY2kAOc&%vn?MVujSPwCHS#q6W(ET<&85p`{JY}Le4!uCOg(V5 zpcw&IHJni~@ieLdekOd9o^8GZXiqRjYqTimwzv?_>5iw{#f3M-ApgyOdUq9;=@p~` z1kZY%qD)$q8TG`;dO;_Pt$Ts~QM<4w*X2O07!7TIYBps+HexTuV}m`H=CS*Hmk!IC zNd^ZuR-7!;W!>x5MX0{$C}no7byL^`9b%}4xJqU4{A3)iYR~`;Nloy$+agKfddOWCv>WJe!B2HvNj&3UVz0>y4G>9*(0`dBJt&j_F#+7R8 zs@T>G*du3DXvH``H2}HuG5*L}BX=y?*(*hM_OsO4a!R&F|7NMumHQ=eeyG-G3kw>u zieF|F@ebGkcTe1pegnzqs3m zFO%I-DdV?O|2uOUi2uN4K$z>19p;JeY;SxyeT>X@L!D}veq>%Rzsc)scO{cxO|iRi z0Il%Q3`B*tA$bwdikvXMmu@R|c1E7kBKs2UX5^$u6Q+V<5g2W={myjXW!oFc*3`j& zB(yn!{C$Y6_WPap>ktHJ<_PR|+F{EIWCR&^;&;vL3bSb+LPNHH5Yp!^Y8-L=)EeJG z!qj+6ui$zPvrwMOIaKdV^$l)`?%85|3g*dJ3j%hcP`$O)8m9-Pw$y@{E| zqhZg-A^CB|naAD*~;=Sr|Z7-HLGLh(aGnrKm{)R#Cspte^i-Z^?1vlRhSYZ$H=& z#5KdI4-njUqp=G1E(~`l*OYMvzNqWGV7pZf$5yEEw|^(eT;^O0$*UDQ@5@X8^aUk; zQ*f5aWKSKxr+QBM>oDFikAvu2@@BHyU%g`u-kS8qUrGk8P&H^{9j+G6!MWD ze7$Vcb@}{HzVb3bI#hmAWt97W{sjoLKX-(h+kfMT0!eIuTYsQ>KfO8uN9w0mX9S;h zO%MKdl=wR{WTB^zWmgq8I~2Hz1_OBExg3z#yh?0SzWJT8Dm%WTXsHHuKq%kV-|>hV zGj4Qjuq9Lu=|wQof7kyiHSRu)kQ$>CPu5j-GHiTWWjPh!qd~j5o5TQ z3qj`FDN!E!p@M|LQ$P}2_^VVEmP+{fl?U73h_q~wqk2qjhn%A>@P!YTSist8H0jMQ zp1xm7^NIL48i_B&vm_a!pB z?Vo|wyr*JctwC~Uyn2$lf`M)4h)wq-YHyB|FP8;a)D^iw@FG4qi@Vcm{ae2mOC}Mi zE9O|awmv8TN<1}p_>C^L?u8pWg*f7l@Tut2A!@d5I~&N;^HGj}nwM=QR*TxbT)mEC zfcQFa9kqGc3LK+%ZBuC8hCBeSb2)QMU!b3EskeQIfkUPmuv4XemF$PyO&SR#v~dwy zCAb|~d`q!WqH?tMI z)Z&6MiAwh2&O~)X>MhX7{yN(HcDQ9w4L;fRa-#IUXA2G;Mbu|-QvfRB4J-pa^z(mg zXYziMyHQv2%S8^>HXx=efawrkaZu{`{DlK2x#2>&M)L)K*S`>ux6Kq<0b#;mrxR5` ztplJdesBPjx8^UCk{0qr@@O7(sN_Mu(-bpg{B#T4RGe1wz=~k>=j9)|5X2HB98TUo zVpl#niWe)fD&U7vr@}!V@dX%PHT<$_U zeKVzigIL&q0&)I0(=h~r_m65sSOB%fV$|}y(S+{40#t^nf~R-@OspWNda94{92|VG zhwJo<@c;(X)}!kC$-X6Aj8(oxjuy`_k}@4AcO&qWK~S{f3O) zS6v}#vz(F-=5J|=;b0=`tIn{}Y_IoXQYvHaGs-4^tx)#B0=ew+Iam&YEr2wLu99(! zJAH*|$}LQzdXtm4%;tC-iH7EP%%{;9w;4-!?XKkB`=>mb)=XNdaS?9ks89h)rdpw> z%@qp&J+__#?{BRwe;}2hK-5Wi=RV4+(W5t$g6K^Tlko9}SLp@H*H}eq*Lmi&+GM|h z79jY4dnvEC>_k2^o%1>~;RodB-XO|^TpKo<2t5lEmcPW=MN9fE`kUdsO{$$xrdykC zkff-$f2jR0zhXidpV<|l(_Dl#R=IVY1>zPCj;*RlWLmaL{}UfJ?tE1@CXl=W0|B?3VKV0u=qEulxEVWfAd|Ss8MxkEQlr=gYFd%dcoxf|hv|HhWn#N&_^dG$C*)^NSh zC1@@@^GAgb&uP)?c_2Q=*eJuiu0d9RZ*Ap=r~vKxW3Z9kjLRF!51Uw1c*y#*|Ct5x z8_NE7gT@heft`;)wVtg>nLzanr#2Z%u}p@a_w~_RS_^dj!bCL)uCRD}>hX0^c)++2 z_2(UvGx>l8(0MmIv|!iTg-eWy&13B5w;sgCT$xe z4TSbYmegVr@M@(jgaBFG+%l)>L^haUK)cX6{i%dsXRxYrOrKONy9_Zl({Myw<6wb( z9D1Wpq%OfTcIm-i*VsiKXD;i1QrKsFk*?27?{G}5m*kEJV&O89@mT7)7In+k7QS+J z;3Q2CBRY|Fg7_54An1;zS68pZ0%MgNpm~boDN9%A$bO&!lm$YXKBoK-vW70$`}76T zB05suL=2{tEpH3~#{vd5L`#gyTP{d@6y3xLy$m_Ub4HBXm{SQ-yHyf@i~#a8v!EQB zjTDtvyMfvud>opfZcTKlstFsr4X~T$015i?V;jLlae&Vho?jw$l&jU!33Yb-msJfN zNb84RW{Q6*)!)ce%9;tLXm3nOyga8qz-Oyl1!{OL6w=yjU%UNgf-SnS zcXHw`I(zEgy-P-&F@mm-M|6M_I-lRK+g(T~zBQ!(L+S4lg#h4bab=S7USTz=Xh0tX z_pS<94qclnqHa!8^@?GQpfCWuSa@ZtV9lrstrbPsN{gFEwiwQTZfVT|Jjcrp(U#^m znqND4_<{t?tv>l3@6~`w0J_X-vL5+@kIP=}C)}Xzlux|~sUQnZf$lHRYbH}=6y{u6 z*4-@9<9aN+U4FlntyYWpV731Jt%J94tMzy3u_YzgIj%4Lvvaivq}#3B_g_R%`#sC= zN|uLY0NnLQX?*m5A=cUv0CKtsU#AEL@4ezs$ zt8V0c2iUKBPSCpdZA}-Iw-{stokel=*oA}ItxWQ>yu<_`2q?OMiXX zf(7zZN=@QjDikR?eO_#5;Ck2>k`E`*H1|2%kXLeaAmH~(g$r{ZChTCES3`J#xDjS$ z1q9MS1U~(Ldp^n_pMxr&#A~nrxByVFyUODcW%V6rWS#n2lMY;Nw)hgR?$r_ePZ{A!w`z+g2Tmqzrd$l;Chn2DP_FW*>^uXpcHPB>eoCc+6oui z5Dq8kfZGqbvfFQ1=3mGl{;^H|)uNMB^U|Qr^y%_{a&^~PyQFMlTH0Cue0i^iZ$qDK z_4C`rLSxwY@HMOA`g=*zp`VehaNCs&HvpK`xBw5mu|u{2G>jHg`KlM;SLG(Zk2m^? zskV>oICE~Be<*vO^mJdIoa3TeWNwf11`!>VbCsa_@3L{P2G=Lz7Ive;02s*BKhP+E z0b%-odr}d#%8oe9aj2EaY?Y$3@W9(pfP2PU_O?vPelJCq`r>@9n1=#_3|rVopngHt zL$AdpXor*>UF=ZD9`p^mtGw~e8|b1)LF6up-Q-hL1Vf*2Oj7QZh_7+nw_L|5AN_ zncf9s4hfrTRdE!dh1ymVViPNBq7ZyxlYHTdNUmRxLmh3m6Nn$OSY)EQ27u z40!;LUt3#zd1|BD2S8AP1K`&cab3g#6O|*tgRez-hcFL9oG8)-UAIoLrZj;~ao>e+k{-ByVMAt23sJkO%Xlf{b47HNh zOPRW@f(P%$TV(3Dn&67Fdxq@fQT*BRdjk@u;0lurEM`z#E%r-RncT|w99*v6Y&bamsav9MV zi5&;S*;YGUc>V=SFZx$!5IHvEUej%H6}$qE0T4V)vieX~#E(qlvuhf0geF z7NH;RXDHUgpmc;di_)|Emr%TyPI=WaeTRCCFx3P@M?@5IM)x~e%YA!)(aNg2kq`LG zqB@!d4v-k3M;VjfsMIlNre{_fo5zqY6|g}0eC*Rbc>MAfd5ube^;8B{S~)f%^jbby zhSmjT8C5hZlu)unb_fY+2x57d#K5$3O(FsJ~GymC;K-JMi zNO8nFLfk*%qq-G!-u<3`a^A5Xz-UTthG(7Xbpt=0v#L0H>;>uwx&hwV)7n?5TvTMg zk3@JjW_u68I-!sc>Xs|@GE$zm)k*atsUR6KSCAdtSNK!_pi?j>GChqIeE>T73C=^u z90i!tAhj=^-c)1{#4=Nho4W1&Y<~xL$s~5y4_9Vx<3pPw-KR-^i=KXUbpkSkihX^R zFgSk6#E0*}DIKa11(Kd!70(;!F+g12@bv#!j)k1IA_nMQcm;zwDRasJ11ioU?g3b! zaj_={mGR|Yu!ePrD9P(%NRkNF_0m%WI+ zXq9PVFT{I)KXHWE@bMncFHETTPj7*)!bcbZlhRQ;&>7rioLj`!#RV75x@{zd=9103 zrIDCzFzVm2htaWdMMR|5wy;kUfM)@Hl2d29|8)S{Acn1)$?8e>h3QoxZ%bpSL1;Xa z7izx%wP|=EaRo0FS@46Vekr;MKhs@}8|loIB6XpEK9$nIPXRfabiW;$u6|8gF(4xA z>)Y<>Uc?hbku)kMyl6hp_AjCFP-|1bctCT`A>UP!M&x!asjc-zOkK!+Qe(IxgMvg4 zQ%sJY?RO(0pV^^GhwPI&9@}%V9N=VuUnQp00(o{I27*%@WhTGJb8U|V2%eoN5@=I^TmGw=poX;+#dS~blVSZ03WNUow@IvoHN?{$>37@MYxRdp ze^-awDpYHJE&8kNuPnZC&J@aP?Bf0j{5v~;5JMJ*-P*OW%LPLloN!6sBt5QmrKl8@ zj_buV1B&em3|w&@uR*LNN+D;LC@I;>e1750xY4o`VPDMBe!z;Dnk#wkia{2>s!%1d%^(G}?r}gHn402$ zp&f4at=f&vZCqUBh!1xwKId3}9|L(+c8uWMfqA%|A4ns8na1DM�D*_4LQ@;D8cq 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%0ASO2z*pmqki+b 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\% as_epi_archive( +toy_epi_archive <- tib \%>\% as_epi_archive2( geo_type = "state", time_type = "day" ) @@ -134,7 +134,7 @@ df <- data.frame( cases_rate = c(0.01, 0.02, 0.01, 0.05) ) -x <- df \%>\% as_epi_archive( +x <- df \%>\% as_epi_archive2( geo_type = "state", time_type = "day", other_keys = "county" diff --git a/man/epi_archive.Rd b/man/epi_archive.Rd index efe5d5bab..86e21b895 100644 --- a/man/epi_archive.Rd +++ b/man/epi_archive.Rd @@ -213,7 +213,7 @@ tib <- tibble::tibble( value = rnorm(10, mean = 2, sd = 1) ) -toy_epi_archive <- tib \%>\% epi_archive$new( +toy_epi_archive <- tib \%>\% new_epi_archive2( geo_type = "state", time_type = "day" ) diff --git a/man/epix_as_of2.Rd b/man/epix_as_of2.Rd index 4bfe32f4d..ac69e9a91 100644 --- a/man/epix_as_of2.Rd +++ b/man/epix_as_of2.Rd @@ -60,16 +60,15 @@ in the future. } \examples{ # warning message of data latency shown -epix_as_of( - x = archive_cases_dv_subset, - max_version = max(archive_cases_dv_subset$DT$version) +epix_as_of2( + archive_cases_dv_subset_2, + max_version = max(archive_cases_dv_subset_2$DT$version) ) +range(archive_cases_dv_subset_2$DT$version) # 2020-06-02 -- 2021-12-01 -range(archive_cases_dv_subset$DT$version) # 2020-06-02 -- 2021-12-01 - -epix_as_of( - x = archive_cases_dv_subset, +epix_as_of2( + archive_cases_dv_subset_2, max_version = as.Date("2020-06-12") ) @@ -83,9 +82,9 @@ epix_as_of( # muffle such warnings with the following pattern: withCallingHandlers( { - epix_as_of( - x = archive_cases_dv_subset, - max_version = max(archive_cases_dv_subset$DT$version) + epix_as_of2( + archive_cases_dv_subset_2, + max_version = max(archive_cases_dv_subset_2$DT$version) ) }, epiprocess__snapshot_as_of_clobberable_version = function(wrn) invokeRestart("muffleWarning") diff --git a/man/epix_merge2.Rd b/man/epix_merge2.Rd index a42e53e42..11d0aff5d 100644 --- a/man/epix_merge2.Rd +++ b/man/epix_merge2.Rd @@ -59,15 +59,13 @@ be clobbered in either input archive. } \examples{ # create two example epi_archive datasets -x <- archive_cases_dv_subset$DT \%>\% +x <- archive_cases_dv_subset_2$DT \%>\% dplyr::select(geo_value, time_value, version, case_rate_7d_av) \%>\% - as_epi_archive(compactify = TRUE) -y <- archive_cases_dv_subset$DT \%>\% + as_epi_archive2(compactify = TRUE) +y <- archive_cases_dv_subset_2$DT \%>\% dplyr::select(geo_value, time_value, version, percent_cli) \%>\% - as_epi_archive(compactify = TRUE) + as_epi_archive2(compactify = TRUE) # merge results stored in a third object: -xy <- epix_merge(x, y) -# vs. mutating x to hold the merge result: -x$merge(y) +xy <- epix_merge2(x, y) } diff --git a/man/epix_slide2.Rd b/man/epix_slide2.Rd index 71d3a11ce..8d822bc04 100644 --- a/man/epix_slide2.Rd +++ b/man/epix_slide2.Rd @@ -199,9 +199,9 @@ ref_time_values <- seq(as.Date("2020-06-01"), # A simple (but not very useful) example (see the archive vignette for a more # realistic one): -archive_cases_dv_subset \%>\% +archive_cases_dv_subset_2 \%>\% group_by(geo_value) \%>\% - epix_slide( + epix_slide2( f = ~ mean(.x$case_rate_7d_av), before = 2, ref_time_values = ref_time_values, @@ -223,9 +223,9 @@ archive_cases_dv_subset \%>\% # Examining characteristics of the data passed to each computation with # `all_versions=FALSE`. -archive_cases_dv_subset \%>\% +archive_cases_dv_subset_2 \%>\% group_by(geo_value) \%>\% - epix_slide( + epix_slide2( function(x, gk, rtv) { tibble( time_range = if (nrow(x) == 0L) { @@ -252,9 +252,9 @@ archive_cases_dv_subset \%>\% # to each computation. In this case, each computation should expect an # `epi_archive` containing the relevant version data: -archive_cases_dv_subset \%>\% +archive_cases_dv_subset_2 \%>\% group_by(geo_value) \%>\% - epix_slide( + epix_slide2( function(x, gk, rtv) { tibble( versions_start = if (nrow(x$DT) == 0L) { diff --git a/man/group_by.epi_archive2.Rd b/man/group_by.epi_archive2.Rd index 3191b134d..fa9040c3e 100644 --- a/man/group_by.epi_archive2.Rd +++ b/man/group_by.epi_archive2.Rd @@ -83,16 +83,16 @@ to \code{group_by_drop_default.default} (but there is a dedicated method for } \examples{ -grouped_archive <- archive_cases_dv_subset \%>\% group_by(geo_value) +grouped_archive <- archive_cases_dv_subset_2 \%>\% group_by(geo_value) # `print` for metadata and method listing: grouped_archive \%>\% print() # The primary use for grouping is to perform a grouped `epix_slide`: -archive_cases_dv_subset \%>\% +archive_cases_dv_subset_2 \%>\% group_by(geo_value) \%>\% - epix_slide( + epix_slide2( f = ~ mean(.x$case_rate_7d_av), before = 2, ref_time_values = as.Date("2020-06-11") + 0:2, @@ -118,7 +118,7 @@ toy_archive <- time_value = as.Date(time_value), version = as.Date(version) ) \%>\% - as_epi_archive(other_keys = "age_group") + as_epi_archive2(other_keys = "age_group") # The following are equivalent: toy_archive \%>\% group_by(geo_value, age_group) @@ -141,7 +141,7 @@ toy_archive \%>\% toy_archive \%>\% group_by(geo_value, age_group, .drop = FALSE) \%>\% - epix_slide(f = ~ sum(.x$value), before = 20) \%>\% + epix_slide2(f = ~ sum(.x$value), before = 20) \%>\% ungroup() } diff --git a/man/is_epi_archive2.Rd b/man/is_epi_archive2.Rd index fd2f0a1f5..df258d3eb 100644 --- a/man/is_epi_archive2.Rd +++ b/man/is_epi_archive2.Rd @@ -19,15 +19,15 @@ count? Default is \code{FALSE}.} Test for \code{epi_archive} format } \examples{ -is_epi_archive(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) -is_epi_archive(archive_cases_dv_subset) # TRUE +is_epi_archive2(jhu_csse_daily_subset) # FALSE (this is an epi_df, not epi_archive) +is_epi_archive2(archive_cases_dv_subset_2) # TRUE # By default, grouped_epi_archives don't count as epi_archives, as they may # support a different set of operations from regular `epi_archives`. This # behavior can be controlled by `grouped_okay`. -grouped_archive <- archive_cases_dv_subset$group_by(geo_value) -is_epi_archive(grouped_archive) # FALSE -is_epi_archive(grouped_archive, grouped_okay = TRUE) # TRUE +grouped_archive <- archive_cases_dv_subset_2 \%>\% group_by(geo_value) +is_epi_archive2(grouped_archive) # FALSE +is_epi_archive2(grouped_archive, grouped_okay = TRUE) # TRUE } \seealso{ diff --git a/tests/testthat/test-archive_new.R b/tests/testthat/test-archive_new.R index f2d0bde58..98f708d7a 100644 --- a/tests/testthat/test-archive_new.R +++ b/tests/testthat/test-archive_new.R @@ -6,7 +6,7 @@ test_that("first input must be a data.frame", { ) }) -dt <- archive_cases_dv_subset$DT +dt <- archive_cases_dv_subset_2$DT test_that("data.frame must contain geo_value, time_value and version columns", { expect_error(as_epi_archive2(select(dt, -geo_value), compactify = FALSE), diff --git a/tests/testthat/test-compactify.R b/tests/testthat/test-compactify.R index 4400c94a1..58e978848 100644 --- a/tests/testthat/test-compactify.R +++ b/tests/testthat/test-compactify.R @@ -2,7 +2,7 @@ library(epiprocess) library(data.table) library(dplyr) -dt <- archive_cases_dv_subset$DT +dt <- archive_cases_dv_subset_2$DT dt <- filter(dt, geo_value == "ca") %>% filter(version <= "2020-06-15") %>% select(-case_rate_7d_av) diff --git a/tests/testthat/test-compactify_new.R b/tests/testthat/test-compactify_new.R index f2887eaf7..cd53913dc 100644 --- a/tests/testthat/test-compactify_new.R +++ b/tests/testthat/test-compactify_new.R @@ -2,7 +2,7 @@ library(epiprocess) library(data.table) library(dplyr) -dt <- archive_cases_dv_subset$DT +dt <- archive_cases_dv_subset_2$DT dt <- filter(dt, geo_value == "ca") %>% filter(version <= "2020-06-15") %>% select(-case_rate_7d_av) diff --git a/tests/testthat/test-epix_merge_new.R b/tests/testthat/test-epix_merge_new.R index 594b7b5e0..10041dbb5 100644 --- a/tests/testthat/test-epix_merge_new.R +++ b/tests/testthat/test-epix_merge_new.R @@ -1,8 +1,6 @@ test_that("epix_merge requires forbids on invalid `y`", { - ea <- archive_cases_dv_subset$DT %>% - as_epi_archive2() %>% - clone() %>% - suppressWarnings() + ea <- archive_cases_dv_subset_2 %>% + clone() expect_error(epix_merge2(ea, data.frame(x = 1))) }) diff --git a/tests/testthat/test-epix_slide_new.R b/tests/testthat/test-epix_slide_new.R index f748231a6..49ef5e410 100644 --- a/tests/testthat/test-epix_slide_new.R +++ b/tests/testthat/test-epix_slide_new.R @@ -800,7 +800,7 @@ test_that("`epix_slide2` can access objects inside of helper functions", { archive_haystack %>% epix_slide2(has_needle = time_value_needle %in% time_value, before = 365000L) } expect_error( - helper(suppressWarnings(as_epi_archive2(archive_cases_dv_subset$DT)), as.Date("2021-01-01")), + helper(archive_cases_dv_subset_2, as.Date("2021-01-01")), NA ) expect_error( diff --git a/tests/testthat/test-methods-epi_archive_new.R b/tests/testthat/test-methods-epi_archive_new.R index a267ba58b..eb2c14be6 100644 --- a/tests/testthat/test-methods-epi_archive_new.R +++ b/tests/testthat/test-methods-epi_archive_new.R @@ -1,9 +1,7 @@ library(dplyr) -ea <- archive_cases_dv_subset$DT %>% - as_epi_archive2() %>% - clone() %>% - suppressWarnings() +ea <- archive_cases_dv_subset_2 %>% + clone() ea2_data <- tibble::tribble( ~geo_value, ~time_value, ~version, ~cases, From bd2aadbba0c3853f967f95446cef60fc0141ea75 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Tue, 19 Mar 2024 17:05:27 -0700 Subject: [PATCH 7/8] feat: update vignettes to use S3 epi_archive --- vignettes/advanced.Rmd | 27 ++++++++++++++------------- vignettes/archive.Rmd | 24 ++++++++++++------------ vignettes/compactify.Rmd | 10 +++++----- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/vignettes/advanced.Rmd b/vignettes/advanced.Rmd index d4fad3e74..c010c1f37 100644 --- a/vignettes/advanced.Rmd +++ b/vignettes/advanced.Rmd @@ -111,17 +111,17 @@ edf %>% edf %>% # pretend that observations about time_value t are reported in version t (nowcasts) mutate(version = time_value) %>% - as_epi_archive() %>% + as_epi_archive2() %>% group_by(geo_value) %>% - epix_slide(x_2dav = mean(x), before = 1, ref_time_values = as.Date("2020-06-02")) %>% + epix_slide2(x_2dav = mean(x), before = 1, ref_time_values = as.Date("2020-06-02")) %>% ungroup() edf %>% # pretend that observations about time_value t are reported in version t (nowcasts) mutate(version = time_value) %>% - as_epi_archive() %>% + as_epi_archive2() %>% group_by(geo_value) %>% - epix_slide(~ mean(.x$x), before = 1, ref_time_values = as.Date("2020-06-02")) %>% + epix_slide2(~ mean(.x$x), before = 1, ref_time_values = as.Date("2020-06-02")) %>% ungroup() ``` @@ -219,9 +219,9 @@ edf %>% edf %>% mutate(version = time_value) %>% - as_epi_archive() %>% + as_epi_archive2() %>% group_by(geo_value) %>% - epix_slide( + epix_slide2( a = data.frame(x_2dav = mean(x), x_2dma = mad(x)), ref_time_values = as.Date("2020-06-02"), before = 1, as_list_col = FALSE, names_sep = NULL @@ -317,16 +317,17 @@ x <- y1 %>% version = issue, percent_cli = value ) %>% - as_epi_archive(compactify = FALSE) + as_epi_archive2(compactify = FALSE) # mutating merge operation: -x$merge( +x <- epix_merge2( + x, y2 %>% select(geo_value, time_value, version = issue, case_rate_7d_av = value ) %>% - as_epi_archive(compactify = FALSE), + as_epi_archive2(compactify = FALSE), sync = "locf", compactify = FALSE ) @@ -337,9 +338,9 @@ library(data.table) library(ggplot2) theme_set(theme_bw()) -x <- archive_cases_dv_subset$DT %>% +x <- archive_cases_dv_subset_2$DT %>% filter(geo_value %in% c("ca", "fl")) %>% - as_epi_archive(compactify = FALSE) + as_epi_archive2(compactify = FALSE) ``` Next, we extend the ARX function to handle multiple geo values, since in the @@ -457,7 +458,7 @@ data. ```{r, message = FALSE, warning = FALSE, fig.width = 9, fig.height = 6} # Latest snapshot of data, and forecast dates -x_latest <- epix_as_of(x, max_version = max(x$DT$version)) +x_latest <- epix_as_of2(x, max_version = max(x$DT$version)) fc_time_values <- seq(as.Date("2020-08-01"), as.Date("2021-11-30"), by = "1 month" @@ -467,7 +468,7 @@ fc_time_values <- seq(as.Date("2020-08-01"), k_week_ahead <- function(x, ahead = 7, as_of = TRUE) { if (as_of) { x %>% - epix_slide( + epix_slide2( fc = prob_arx(.data$percent_cli, .data$case_rate_7d_av, .data$geo_value, .data$time_value, args = prob_arx_args(ahead = ahead) ), diff --git a/vignettes/archive.Rmd b/vignettes/archive.Rmd index fdb0e3c61..0b57d6391 100644 --- a/vignettes/archive.Rmd +++ b/vignettes/archive.Rmd @@ -76,16 +76,16 @@ the compactify vignette. ```{r, eval=FALSE} x <- dv %>% select(geo_value, time_value, version = issue, percent_cli = value) %>% - as_epi_archive(compactify = TRUE) + as_epi_archive2(compactify = TRUE) class(x) print(x) ``` ```{r, echo=FALSE, message=FALSE, warning=FALSE} -x <- archive_cases_dv_subset$DT %>% +x <- archive_cases_dv_subset_2$DT %>% select(geo_value, time_value, version, percent_cli) %>% - as_epi_archive(compactify = TRUE) + as_epi_archive2(compactify = TRUE) class(x) print(x) @@ -154,7 +154,7 @@ function `epix_as_of()` since this is likely a more familiar interface for users not familiar with R6 (or object-oriented programming). ```{r} -x_snapshot <- epix_as_of(x, max_version = as.Date("2021-06-01")) +x_snapshot <- epix_as_of2(x, max_version = as.Date("2021-06-01")) class(x_snapshot) head(x_snapshot) max(x_snapshot$time_value) @@ -174,7 +174,7 @@ this case, since updates to the current version may still come in at a later point in time, due to various reasons, such as synchronization issues. ```{r} -x_latest <- epix_as_of(x, max_version = max(x$DT$version)) +x_latest <- epix_as_of2(x, max_version = max(x$DT$version)) ``` Below, we pull several snapshots from the archive, spaced one month apart. We @@ -188,7 +188,7 @@ theme_set(theme_bw()) self_max <- max(x$DT$version) versions <- seq(as.Date("2020-06-01"), self_max - 1, by = "1 month") snapshots <- map_dfr(versions, function(v) { - epix_as_of(x, max_version = v) %>% mutate(version = v) + epix_as_of2(x, max_version = v) %>% mutate(version = v) }) %>% bind_rows( x_latest %>% mutate(version = self_max) @@ -258,15 +258,15 @@ y <- pub_covidcast( issues = epirange(20200601, 20211201) ) %>% select(geo_value, time_value, version = issue, case_rate_7d_av = value) %>% - as_epi_archive(compactify = TRUE) + as_epi_archive2(compactify = TRUE) -x$merge(y, sync = "locf", compactify = FALSE) +x <- epix_merge2(x, y, sync = "locf", compactify = TRUE) print(x) head(x$DT) ``` ```{r, echo=FALSE, message=FALSE, warning=FALSE} -x <- archive_cases_dv_subset +x <- archive_cases_dv_subset_2 print(x) head(x$DT) ``` @@ -362,7 +362,7 @@ fc_time_values <- seq(as.Date("2020-08-01"), z <- x %>% group_by(geo_value) %>% - epix_slide( + epix_slide2( fc = prob_arx(x = percent_cli, y = case_rate_7d_av), before = 119, ref_time_values = fc_time_values ) %>% @@ -389,14 +389,14 @@ points in time and forecast horizons. The former comes from using `epi_slide()` to the latest snapshot of the data `x_latest`. ```{r, message = FALSE, warning = FALSE, fig.width = 9, fig.height = 6} -x_latest <- epix_as_of(x, max_version = max(x$DT$version)) +x_latest <- epix_as_of2(x, max_version = max(x$DT$version)) # Simple function to produce forecasts k weeks ahead k_week_ahead <- function(x, ahead = 7, as_of = TRUE) { if (as_of) { x %>% group_by(.data$geo_value) %>% - epix_slide( + epix_slide2( fc = prob_arx(.data$percent_cli, .data$case_rate_7d_av, ahead = ahead), before = 119, ref_time_values = fc_time_values ) %>% diff --git a/vignettes/compactify.Rmd b/vignettes/compactify.Rmd index cad065e71..0b68c73b6 100644 --- a/vignettes/compactify.Rmd +++ b/vignettes/compactify.Rmd @@ -32,10 +32,10 @@ from the second from the third value included. library(epiprocess) library(dplyr) -dt <- archive_cases_dv_subset$DT +dt <- archive_cases_dv_subset_2$DT -locf_omitted <- as_epi_archive(dt) -locf_included <- as_epi_archive(dt, compactify = FALSE) +locf_omitted <- as_epi_archive2(dt) +locf_included <- as_epi_archive2(dt, compactify = FALSE) head(locf_omitted$DT) head(locf_included$DT) @@ -48,8 +48,8 @@ LOCF-redundant values can mar the performance of dataset operations. As the colu ```{r} dt2 <- select(dt, -percent_cli) -locf_included_2 <- as_epi_archive(dt2, compactify = FALSE) -locf_omitted_2 <- as_epi_archive(dt2, compactify = TRUE) +locf_included_2 <- as_epi_archive2(dt2, compactify = FALSE) +locf_omitted_2 <- as_epi_archive2(dt2, compactify = TRUE) ``` In this example, a huge proportion of the original version update data were From 3e00379ef6d6bde0dae7e86289c7203f3fc35a90 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Tue, 19 Mar 2024 17:05:41 -0700 Subject: [PATCH 8/8] doc: bump version to 0.7.6 and add NEWS line --- DESCRIPTION | 2 +- NEWS.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 538fd0232..93a979363 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: epiprocess Title: Tools for basic signal processing in epidemiology -Version: 0.7.5 +Version: 0.7.6 Authors@R: c( person("Jacob", "Bien", role = "ctb"), person("Logan", "Brooks", email = "lcbrooks@andrew.cmu.edu", role = c("aut", "cre")), diff --git a/NEWS.md b/NEWS.md index 5bf584e6c..b2c267751 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,7 @@ Pre-1.0.0 numbering scheme: 0.x will indicate releases, while 0.x.y will indicat ## Breaking changes - Switched `epi_df`'s `other_keys` default from `NULL` to `character(0)`; PR #390 +- Refactor `epi_archive` to use S3 instead of R6 for its object model. The calls to some functions will change, but the functionality will remain the same. It will also help us maintain the package better in the future. (#340) # epiprocess 0.7.0