From 864fdc90e002469929c3ece760576ab31bc0b660 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 7 Aug 2026 12:01:36 +0200 Subject: [PATCH 01/12] Add touch actor support for hand-contact detection metrics Add getTouchActors(), getTouchActorAois() and getTouchActorRespondents() to list a stimulus's touch actors, pair them with their interactive AOIs and contact in/out data, and filter respondents that have contact data for a stimulus. Add getAoiRespondentTouchData() and getAoiRespondentTouchMetrics() to retrieve the contact in/out signal, active intervals, and metrics for a (touch actor, AOI)/respondent combination. Add supporting private helpers (privateGetTouchActorDetails, privateDecodeHandType) and endpoint builders (getTouchActorsUrl, getTouchActorDetailsUrl S3 methods for imAOI/imStimulus). Add tests and fixtures covering the new endpoints and helpers. --- imotionsApi/NAMESPACE | 7 + imotionsApi/R/imotionsApi.R | 459 +++++++++++++++++ imotionsApi/man/getAoiRespondentTouchData.Rd | 37 ++ .../man/getAoiRespondentTouchMetrics.Rd | 32 ++ imotionsApi/man/getTouchActorAois.Rd | 42 ++ imotionsApi/man/getTouchActorDetailsUrl.Rd | 21 + .../man/getTouchActorDetailsUrl.imAOI.Rd | 20 + .../man/getTouchActorDetailsUrl.imStimulus.Rd | 21 + imotionsApi/man/getTouchActorRespondents.Rd | 32 ++ imotionsApi/man/getTouchActors.Rd | 29 ++ imotionsApi/man/getTouchActorsUrl.Rd | 17 + imotionsApi/man/privateDecodeHandType.Rd | 18 + .../man/privateGetTouchActorDetails.Rd | 23 + imotionsApi/tests/data/noTouchActors.json | 1 + imotionsApi/tests/data/touchActorDetails.json | 26 + .../data/touchActorDetailsMultiSource.json | 18 + .../data/touchActorDetails_missingfileId.json | 26 + .../touchActorDetails_noMatchingPair.json | 10 + .../data/touchActorEmptyRespondentData.pbin | 0 .../tests/data/touchActorRespondentData.pbin | Bin 0 -> 2665 bytes imotionsApi/tests/data/touchActors.json | 22 + .../tests/data/touchActorsMultiSource.json | 22 + .../tests/testthat/test-getTouchActors.R | 462 ++++++++++++++++++ 23 files changed, 1345 insertions(+) create mode 100644 imotionsApi/man/getAoiRespondentTouchData.Rd create mode 100644 imotionsApi/man/getAoiRespondentTouchMetrics.Rd create mode 100644 imotionsApi/man/getTouchActorAois.Rd create mode 100644 imotionsApi/man/getTouchActorDetailsUrl.Rd create mode 100644 imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd create mode 100644 imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd create mode 100644 imotionsApi/man/getTouchActorRespondents.Rd create mode 100644 imotionsApi/man/getTouchActors.Rd create mode 100644 imotionsApi/man/getTouchActorsUrl.Rd create mode 100644 imotionsApi/man/privateDecodeHandType.Rd create mode 100644 imotionsApi/man/privateGetTouchActorDetails.Rd create mode 100644 imotionsApi/tests/data/noTouchActors.json create mode 100644 imotionsApi/tests/data/touchActorDetails.json create mode 100644 imotionsApi/tests/data/touchActorDetailsMultiSource.json create mode 100644 imotionsApi/tests/data/touchActorDetails_missingfileId.json create mode 100644 imotionsApi/tests/data/touchActorDetails_noMatchingPair.json create mode 100644 imotionsApi/tests/data/touchActorEmptyRespondentData.pbin create mode 100644 imotionsApi/tests/data/touchActorRespondentData.pbin create mode 100644 imotionsApi/tests/data/touchActors.json create mode 100644 imotionsApi/tests/data/touchActorsMultiSource.json create mode 100644 imotionsApi/tests/testthat/test-getTouchActors.R diff --git a/imotionsApi/NAMESPACE b/imotionsApi/NAMESPACE index c23e5b6..b435a8b 100644 --- a/imotionsApi/NAMESPACE +++ b/imotionsApi/NAMESPACE @@ -6,6 +6,8 @@ S3method(getAoiDetailsUrl,imAOI) S3method(getAoiDetailsUrl,imStimulus) S3method(getSensorsUrl,imRespondent) S3method(getSensorsUrl,imSegment) +S3method(getTouchActorDetailsUrl,imAOI) +S3method(getTouchActorDetailsUrl,imStimulus) S3method(getUploadAoiMetricsUrl,imSegment) S3method(getUploadEventsUrl,imRespondent) S3method(getUploadMetricsUrl,imRespondent) @@ -27,6 +29,8 @@ export(createExport) export(getAoi) export(getAoiRespondentData) export(getAoiRespondentMetrics) +export(getAoiRespondentTouchData) +export(getAoiRespondentTouchMetrics) export(getAois) export(getRespondent) export(getRespondentIntervals) @@ -38,6 +42,9 @@ export(getSensors) export(getSensorsMetadata) export(getStimuli) export(getStimulus) +export(getTouchActorAois) +export(getTouchActorRespondents) +export(getTouchActors) export(imConnection) export(imStudy) export(listLoadedStudies) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index 92c445e..14dc917 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -1768,6 +1768,408 @@ privateGetAoiDetails <- function(study, imObject, respondent = NULL) { } +## Touch actors ======================================================================================================= + +#' Get all touch actors defined for a specific stimulus. +#' +#' A touch actor detects hand-to-object contact on a recorded video and marks a set of AOIs as interactive. Contact +#' detection runs in the iMotions desktop application only, so this returns NULL for a remote study. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' +#' @return An imTouchActorList object (data.table) with one row per touch actor, or NULL if none are defined. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimuli <- imotionsApi::getStimuli(study) +#' touchActors <- imotionsApi::getTouchActors(study, stimuli[1, ]) +#' } +getTouchActors <- function(study, stimulus) { + assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") + assertValid(hasArg(stimulus), "Please specify a stimulus loaded with `getStimuli()`") + + assertClass(study, "imStudy", "`study` argument is not an imStudy object") + assertClass(stimulus, "imStimulus", "`stimulus` argument is not an imStimulus object") + + endpoint <- paste0("Stimulus: ", stimulus$name) + + if (!study$connection$localIM) { + warning(paste("Touch actors are only available for local studies, none retrieved for", endpoint)) + return(NULL) + } + + touchActors <- getJSON(study$connection, getTouchActorsUrl(study, stimulus$id), + message = paste("Retrieving touch actors for", endpoint)) + + if (length(touchActors) == 0 || nrow(touchActors) == 0) { + warning(paste("No touch actor defined for", endpoint)) + return(NULL) + } + + setDT(touchActors) + + # The endpoint reports the stimulus database id as a number, while every other imObject carries it as a string + # (see privateAoiFormatting) - matching that here keeps joins against AOIs and stimuli working. + touchActors$stimulusId <- as.character(touchActors$stimulusId) + + setcolorder(touchActors, c("stimulusId", "stimulusName", "id", "name")) + touchActors <- createImObject(touchActors, "TouchActor") + return(touchActors) +} + + +#' Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data. +#' +#' Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This +#' returns one row per pair, plus the touch actor that produced it and the path to the contact in/out signal, so it +#' can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area) when +#' one is available - which today is only for a touch actor on the Stimulus/Scene camera, since that is the only +#' camera \code{\link{getAois}} can see. A touch actor on any other media source (e.g. Environment) still gets its +#' row, with those four columns NA - contact and metrics are unaffected, only their display labelling is. +#' +#' Requesting this triggers generation of any in/out signals that are missing or older than the contact detection +#' result they derive from, which is why a respondent is required. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' @param touchActor Optional - an imTouchActor object as returned from \code{\link{getTouchActors}} to only return +#' that actor's AOIs. Defaults to NULL, meaning every touch actor on the stimulus. +#' +#' @return An imAOIList object (data.table) with one row per (touch actor, AOI) combination, or NULL if none exist. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +#' +#' print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair +#' } +getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { + # set local variable to remove warnings in `devtools::check()` + aoiId <- touchActorId <- touchActorName <- hand <- detectionMethod <- mediaSourceType <- stimulusId <- + stimulusName <- NULL + + assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") + assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") + assertClass(touchActor, "imTouchActor", "`touchActor` argument is not an imTouchActor object") + + touchActors <- getTouchActors(study, stimulus) + + if (is.null(touchActors)) { + return(NULL) + } + + if (!is.null(touchActor)) { + touchActors <- touchActors[touchActors$id %in% touchActor$id, ] + } + + # One row per (touch actor, AOI): interactiveAoiIds is a list column holding each actor's own AOI ids. + # stimulusId/stimulusName are carried from the touch actor itself rather than picked up from the AOI join below, + # so they still land on rows that join can't see - see the comment on that join for why some rows would be. + pairs <- data.table(touchActorId = touchActors$id, touchActorName = touchActors$name, hand = touchActors$hand, + detectionMethod = touchActors$detectionMethod, + mediaSourceType = touchActors$mediaSourceType, stimulusId = touchActors$stimulusId, + stimulusName = touchActors$stimulusName, aoiId = touchActors$interactiveAoiIds) + + pairs <- pairs[, .(aoiId = unlist(aoiId)), + by = .(touchActorId, touchActorName, hand, detectionMethod, mediaSourceType, stimulusId, + stimulusName)] + + if (nrow(pairs) == 0) { + warning(paste("No interactive AOI defined for any touch actor on stimulus:", stimulus$name)) + return(NULL) + } + + details <- privateGetTouchActorDetails(study, stimulus, respondent) + + if (is.null(details) || nrow(details) == 0) { + return(NULL) + } + + touchAois <- merge(pairs, details[, c("touchActorId", "aoiId", "fileId", "resultId")], + by = c("touchActorId", "aoiId")) + + if (nrow(touchAois) == 0) { + warning("The contact in/out signals found do not match any touch actor AOI for this respondent/stimulus ", + "combination.") + return(NULL) + } + + # The AOI definition carries name/type/group/area, which the touch actor endpoint does not report and which + # nicely labels the metrics grid - but getAois() only ever reaches the Stimulus/Scene camera's AOI set (it + # predates per-camera AOI models, see AOIHandler.cs/AOICollectionBase on the EmotionTool side). A left join keeps + # every touch actor AOI regardless of camera: a Scene AOI gets the full definition, anything else gets NA there + # instead of being dropped. Metrics computation and upload only need id/fileId/resultId/stimulusId, all already + # set above from the touch actor side, so a missing definition costs display polish, not correctness - the + # in/out signal and its metrics file are written and discovered by fileId alone, camera-agnostic on that side. + aois <- suppressWarnings(getAois(study, stimulus)) + + if (is.null(aois)) { + touchAois[, c("name", "type", "group", "area") := list(NA_character_, NA_character_, NA_character_, + NA_real_)] + } else { + # getAois() has already wrapped its result with createImObject, and merge.data.table joins by evaluating + # `y[x, on = by]` - so an imObject on the right hand side dispatches to `[.imObject`, which forwards `on` + # through `...` where `[.data.table`'s substitute(on) can no longer resolve it. Join on a plain data.table. + class(aois) <- c("data.table", "data.frame") + + touchAois <- merge(touchAois, aois[, c("id", "name", "type", "group", "area")], by.x = "aoiId", by.y = "id", + all.x = TRUE) + } + + # Named `id` so the AOI - not the touch actor - is what an imAOI consumer sees, which is what makes + # uploadAoiMetrics() and addMetricsInfoAoi() usable unchanged. + setnames(touchAois, "aoiId", "id") + setcolorder(touchAois, c("stimulusId", "stimulusName", "id", "name", "type", "group", "area")) + touchAois <- createImObject(touchAois, "AOI") + return(touchAois) +} + + +#' Get the respondents that have contact data for a specific stimulus. +#' +#' \code{\link{getRespondents}} cannot be used with an AOI here: its imAOI method resolves respondents through the gaze +#' in/out endpoint, which returns nothing on a study without eyetracking data - exactly the case contact metrics exist +#' to support. This filters the stimulus's respondents by whether contact in/out signals exist for them instead. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' @param segment Optional - an imSegment object as returned from \code{\link{getSegments}} to filter respondents. +#' +#' @return An imRespondentList object (data.table) with the respondents that have contact data. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' respondents <- imotionsApi::getTouchActorRespondents(study, stimulus) +#' } +getTouchActorRespondents <- function(study, stimulus, segment = NULL) { + assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") + assertValid(hasArg(stimulus), "Please specify a stimulus loaded with `getStimuli()`") + + assertClass(study, "imStudy", "`study` argument is not an imStudy object") + assertClass(stimulus, "imStimulus", "`stimulus` argument is not an imStimulus object") + assertClass(segment, "imSegment", "`segment` argument is not an imSegment object") + + respondents <- getRespondents(study, stimulus = stimulus, segment = segment) + + if (nrow(respondents) == 0) { + return(respondents) + } + + hasContactData <- vapply(seq_len(nrow(respondents)), function(idx) { + details <- suppressWarnings(privateGetTouchActorDetails(study, stimulus, respondents[idx, ])) + return(!is.null(details) && nrow(details) > 0) + }, logical(1)) + + return(respondents[hasContactData, ]) +} + + +#' Get the contact in/out data for a specific (touch actor, AOI)/respondent combination. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param touchAoi One row of \code{\link{getTouchActorAois}}, i.e. an AOI carrying a contact in/out fileId. +#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' +#' @return A list with an inOutContact data.table (change-only rows of Timestamp, IsContactInAOI, HandType, HandId) +#' and an imIntervalList object with the AOI's active fragments. NULL if no in/out file was found. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +#' contactData <- imotionsApi::getAoiRespondentTouchData(study, touchAois[1, ], respondent) +#' +#' # Retrieving list items +#' inOutContact <- contactData$inOutContact +#' intervals <- contactData$intervals +#' } +getAoiRespondentTouchData <- function(study, touchAoi, respondent) { + # set local variable to remove warnings in `devtools::check()` + IsActiveAOI <- IsContactInAOI <- HandType <- NULL + + assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") + assertValid(hasArg(touchAoi), "Please specify a touch actor AOI loaded with `getTouchActorAois()`") + assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") + + assertClass(study, "imStudy", "`study` argument is not an imStudy object") + assertClass(touchAoi, "imAOI", "`touchAoi` argument is not an imAOI object") + assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") + + details <- privateGetTouchActorDetails(study, touchAoi, respondent) + + if (length(details) == 0 || nrow(details) == 0) { + warning(paste("No contact data found for AOI", touchAoi$name, "and respondent", respondent$name)) + return(NULL) + } + + namesInout <- c("IsActiveAOI", "IsContactInAOI") + notActivatedAOI <- FALSE + + if (file.info(details$fileId)$size == 0) { + # An empty placeholder is what the desktop writes when the AOI was never active during the recording. + notActivatedAOI <- TRUE + } else { + data <- read_parquet(details$fileId) + data <- data |> mutate_at(namesInout, as.logical) + setDT(data) + data[, HandType := privateDecodeHandType(HandType)] + } + + if (notActivatedAOI) { + intervals <- data.table(fragments.start = NA_real_, fragments.end = NA_real_) + inOutContact <- data.table(matrix(data = NA_integer_, ncol = 4, nrow = 0)) + names(inOutContact) <- c("Timestamp", "IsContactInAOI", "HandType", "HandId") + } else { + # The file always opens with an activation and closes with a deactivation, so these two are equal in length. + activityChange <- data[data[, .I[1], by = rleid(IsActiveAOI)]$V1, ] + intervals <- data.table(fragments.start = activityChange[(IsActiveAOI), ]$Timestamp, + fragments.end = activityChange[!(IsActiveAOI), ]$Timestamp) + + # Keyed on HandType as well as contact, so a left-to-right handover mid-contact stays visible rather than + # being attributed wholly to the hand that started it. + contactChange <- data[data[, .I[1], by = rleid(IsContactInAOI, HandType)]$V1, ] + inOutContact <- contactChange[, c("Timestamp", "IsContactInAOI", "HandType", "HandId")] + } + + intervals <- intervals[, let(fragments.duration = intervals$fragments.end - intervals$fragments.start, + name = touchAoi$name, type = "AOI", parentId = touchAoi$stimulusId, + parentName = touchAoi$stimulusName, id = touchAoi$id, text = NA_character_, + respondent = list(respondent))] + + intervals[is.na(intervals$fragments.duration), ]$fragments.duration <- 0 + intervals <- createImObject(intervals, "Interval") + return(list(inOutContact = inOutContact, intervals = intervals)) +} + + +#' Get the contact metrics for a specific (touch actor, AOI)/respondent combination. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param touchAoi One row of \code{\link{getTouchActorAois}}, i.e. an AOI carrying a contact in/out fileId. +#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' +#' @return A data.table of one row (imMetrics object) with the contact metrics, or NULL if none were computed yet. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +#' metrics <- imotionsApi::getAoiRespondentTouchMetrics(study, touchAois[1, ], respondent) +#' } +getAoiRespondentTouchMetrics <- function(study, touchAoi, respondent) { + assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") + assertValid(hasArg(touchAoi), "Please specify a touch actor AOI loaded with `getTouchActorAois()`") + assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") + + assertClass(study, "imStudy", "`study` argument is not an imStudy object") + assertClass(touchAoi, "imAOI", "`touchAoi` argument is not an imAOI object") + assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") + + endpoint <- paste0("AOI: ", touchAoi$name, ", Respondent: ", respondent$name) + details <- privateGetTouchActorDetails(study, touchAoi, respondent) + + if (length(details) == 0 || nrow(details) == 0) { + warning(paste("No contact data found for", endpoint)) + return(NULL) + } + + if (is.na(details$resultId)) { + warning(paste0("No contact metrics found for ", endpoint)) + return(NULL) + } + + metrics <- fread(details$resultId) + metrics <- checkDataFormat(metrics) + return(metrics) +} + + +#' Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live for a respondent. +#' +#' Requesting these generates any signal that is missing or older than the contact detection result it derives from, +#' so this is also what makes the files exist. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param imObject An imStimulus object (all touch actors on it) or one row of \code{\link{getTouchActorAois}}. +#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' +#' @return A data.frame with one row per (touch actor, AOI) combination that has an in/out signal. +#' @keywords internal +privateGetTouchActorDetails <- function(study, imObject, respondent) { + endpoint <- paste0(gsub("^im|List", "", class(imObject)[1]), ": ", imObject$name, ", Respondent: ", + respondent$name) + + if (!study$connection$localIM) { + warning(paste("Contact data is only available for local studies, none retrieved for", endpoint)) + return(NULL) + } + + if (exists("fileId", imObject)) { + # in case the in/out file was already generated, we just return its path + return(imObject) + } + + dataUrl <- getTouchActorDetailsUrl(study, imObject, respondent) + details <- getJSON(study$connection, dataUrl, message = paste("Retrieving contact details for", endpoint)) + + if (length(details) == 0) { + warning(paste(endpoint, "has no contact in/out signals, has contact detection been run?")) + return(NULL) + } + + # Filtering out combinations without data if any - a null fileId means detection never ran for that touch actor, + # as opposed to a 0-byte one, which means the AOI was simply never active. + details <- details[!is.na(details$fileId), ] + return(details) +} + + +#' Private function translating the numeric hand codes stored in a contact in/out file into readable labels. +#' +#' @param codes A numeric vector of hand codes as stored in the HandType column. +#' +#' @return A character vector with one label per code. +#' @keywords internal +privateDecodeHandType <- function(codes) { + # Codes are defined by TouchActorSampleMetaData in the desktop application: 0 = none, 1 = left, 2 = right, + # 3 = unknown. Anything unrecognised is reported as unknown rather than dropped, so a new code never silently + # becomes a missing value in the metrics. + labels <- c("None", "Left", "Right", "Unknown") + index <- as.integer(codes) + 1L + + # A negative code (e.g. -1) maps to index 0, which `labels[0]` silently drops instead of returning NA - shrinking + # the result vector rather than producing a value to overwrite below. Routing it through NA first keeps the + # result the same length as `codes`. + index[!is.na(index) & (index < 1L | index > length(labels))] <- NA_integer_ + + decoded <- labels[index] + decoded[is.na(decoded)] <- "Unknown" + return(decoded) +} + + ## Uploading Data ===================================================================================================== #' Create a new sensor for a specific respondent/segment in a study. @@ -2919,6 +3321,63 @@ getAoiDetailsUrl.imStimulus <- function(study, imObject, respondent = NULL) { } +#' Return the path/url to the touch actors defined for a specific stimulus. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulusId The id of the stimulus of interest. +#' +#' @keywords internal +getTouchActorsUrl <- function(study, stimulusId) { + file.path(getStudyBaseUrl(study), "touchactors", study$id, "stimuli", stimulusId) +} + + +#' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imAOI/imStimulus object and a +#' respondent object. +#' +#' Return the path/url to the contact in/out details for one touch actor, or for every touch actor on a stimulus. +#' Contact detection is desktop-only, so this is only ever used for a local study. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param imObject An imStimulus object, or one row of \code{\link{getTouchActorAois}}. +#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' +#' @keywords internal +getTouchActorDetailsUrl <- function(study, imObject, respondent) { + UseMethod("getTouchActorDetailsUrl", object = imObject) +} + + +#' getTouchActorDetailsUrl.imAOI method to return the path/url to one touch actor's contact in/out details. +#' +#' Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports +#' every AOI of the actors it matches in one response. +#' +#' @inheritParams getTouchActorDetailsUrl +#' +#' @keywords internal +#' @exportS3Method getTouchActorDetailsUrl imAOI +getTouchActorDetailsUrl.imAOI <- function(study, imObject, respondent) { + url <- getTouchActorsUrl(study, imObject$stimulusId) + url <- file.path(url, "respondent", respondent$id, imObject$touchActorId) + return(url) +} + + +#' getTouchActorDetailsUrl.imStimulus method to return the path/url to the contact in/out details of every touch actor +#' defined for a stimulus. +#' +#' @inheritParams getTouchActorDetailsUrl +#' +#' @keywords internal +#' @exportS3Method getTouchActorDetailsUrl imStimulus +getTouchActorDetailsUrl.imStimulus <- function(study, imObject, respondent) { + url <- getTouchActorsUrl(study, imObject$id) + url <- file.path(url, "respondent", respondent$id, "*") + return(url) +} + + #' Return the path/url to the scenes of a specific respondent. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. diff --git a/imotionsApi/man/getAoiRespondentTouchData.Rd b/imotionsApi/man/getAoiRespondentTouchData.Rd new file mode 100644 index 0000000..215c419 --- /dev/null +++ b/imotionsApi/man/getAoiRespondentTouchData.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getAoiRespondentTouchData} +\alias{getAoiRespondentTouchData} +\title{Get the contact in/out data for a specific (touch actor, AOI)/respondent combination.} +\usage{ +getAoiRespondentTouchData(study, touchAoi, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{touchAoi}{One row of \code{\link{getTouchActorAois}}, i.e. an AOI carrying a contact in/out fileId.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\value{ +A list with an inOutContact data.table (change-only rows of Timestamp, IsContactInAOI, HandType, HandId) + and an imIntervalList object with the AOI's active fragments. NULL if no in/out file was found. +} +\description{ +Get the contact in/out data for a specific (touch actor, AOI)/respondent combination. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +contactData <- imotionsApi::getAoiRespondentTouchData(study, touchAois[1, ], respondent) + +# Retrieving list items +inOutContact <- contactData$inOutContact +intervals <- contactData$intervals +} +} diff --git a/imotionsApi/man/getAoiRespondentTouchMetrics.Rd b/imotionsApi/man/getAoiRespondentTouchMetrics.Rd new file mode 100644 index 0000000..0803d4d --- /dev/null +++ b/imotionsApi/man/getAoiRespondentTouchMetrics.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getAoiRespondentTouchMetrics} +\alias{getAoiRespondentTouchMetrics} +\title{Get the contact metrics for a specific (touch actor, AOI)/respondent combination.} +\usage{ +getAoiRespondentTouchMetrics(study, touchAoi, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{touchAoi}{One row of \code{\link{getTouchActorAois}}, i.e. an AOI carrying a contact in/out fileId.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\value{ +A data.table of one row (imMetrics object) with the contact metrics, or NULL if none were computed yet. +} +\description{ +Get the contact metrics for a specific (touch actor, AOI)/respondent combination. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +metrics <- imotionsApi::getAoiRespondentTouchMetrics(study, touchAois[1, ], respondent) +} +} diff --git a/imotionsApi/man/getTouchActorAois.Rd b/imotionsApi/man/getTouchActorAois.Rd new file mode 100644 index 0000000..77ca560 --- /dev/null +++ b/imotionsApi/man/getTouchActorAois.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorAois} +\alias{getTouchActorAois} +\title{Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data.} +\usage{ +getTouchActorAois(study, stimulus, respondent, touchActor = NULL) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} + +\item{touchActor}{Optional - an imTouchActor object as returned from \code{\link{getTouchActors}} to only return +that actor's AOIs. Defaults to NULL, meaning every touch actor on the stimulus.} +} +\value{ +An imAOIList object (data.table) with one row per (touch actor, AOI) combination, or NULL if none exist. +} +\description{ +Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This +returns one row per pair, carrying the AOI's own definition (name, type, group, area) so it can be used anywhere an +imAOI is expected, plus the touch actor that produced it and the path to the contact in/out signal. +} +\details{ +Requesting this triggers generation of any in/out signals that are missing or older than the contact detection +result they derive from, which is why a respondent is required. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] +touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) + +print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair +} +} diff --git a/imotionsApi/man/getTouchActorDetailsUrl.Rd b/imotionsApi/man/getTouchActorDetailsUrl.Rd new file mode 100644 index 0000000..cd3ef0b --- /dev/null +++ b/imotionsApi/man/getTouchActorDetailsUrl.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorDetailsUrl} +\alias{getTouchActorDetailsUrl} +\title{Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imAOI/imStimulus object and a +respondent object.} +\usage{ +getTouchActorDetailsUrl(study, imObject, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\description{ +Return the path/url to the contact in/out details for one touch actor, or for every touch actor on a stimulus. +Contact detection is desktop-only, so this is only ever used for a local study. +} +\keyword{internal} diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd new file mode 100644 index 0000000..4dc4183 --- /dev/null +++ b/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorDetailsUrl.imAOI} +\alias{getTouchActorDetailsUrl.imAOI} +\title{getTouchActorDetailsUrl.imAOI method to return the path/url to one touch actor's contact in/out details.} +\usage{ +\method{getTouchActorDetailsUrl}{imAOI}(study, imObject, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\description{ +Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports +every AOI of the actors it matches in one response. +} +\keyword{internal} diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd new file mode 100644 index 0000000..904e581 --- /dev/null +++ b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorDetailsUrl.imStimulus} +\alias{getTouchActorDetailsUrl.imStimulus} +\title{getTouchActorDetailsUrl.imStimulus method to return the path/url to the contact in/out details of every touch actor +defined for a stimulus.} +\usage{ +\method{getTouchActorDetailsUrl}{imStimulus}(study, imObject, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\description{ +getTouchActorDetailsUrl.imStimulus method to return the path/url to the contact in/out details of every touch actor +defined for a stimulus. +} +\keyword{internal} diff --git a/imotionsApi/man/getTouchActorRespondents.Rd b/imotionsApi/man/getTouchActorRespondents.Rd new file mode 100644 index 0000000..3c8596d --- /dev/null +++ b/imotionsApi/man/getTouchActorRespondents.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorRespondents} +\alias{getTouchActorRespondents} +\title{Get the respondents that have contact data for a specific stimulus.} +\usage{ +getTouchActorRespondents(study, stimulus, segment = NULL) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} + +\item{segment}{Optional - an imSegment object as returned from \code{\link{getSegments}} to filter respondents.} +} +\value{ +An imRespondentList object (data.table) with the respondents that have contact data. +} +\description{ +\code{\link{getRespondents}} cannot be used with an AOI here: its imAOI method resolves respondents through the gaze +in/out endpoint, which returns nothing on a study without eyetracking data - exactly the case contact metrics exist +to support. This filters the stimulus's respondents by whether contact in/out signals exist for them instead. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +respondents <- imotionsApi::getTouchActorRespondents(study, stimulus) +} +} diff --git a/imotionsApi/man/getTouchActors.Rd b/imotionsApi/man/getTouchActors.Rd new file mode 100644 index 0000000..38a9051 --- /dev/null +++ b/imotionsApi/man/getTouchActors.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActors} +\alias{getTouchActors} +\title{Get all touch actors defined for a specific stimulus.} +\usage{ +getTouchActors(study, stimulus) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} +} +\value{ +An imTouchActorList object (data.table) with one row per touch actor, or NULL if none are defined. +} +\description{ +A touch actor detects hand-to-object contact on a recorded video and marks a set of AOIs as interactive. Contact +detection runs in the iMotions desktop application only, so this returns NULL for a remote study. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimuli <- imotionsApi::getStimuli(study) +touchActors <- imotionsApi::getTouchActors(study, stimuli[1, ]) +} +} diff --git a/imotionsApi/man/getTouchActorsUrl.Rd b/imotionsApi/man/getTouchActorsUrl.Rd new file mode 100644 index 0000000..52956b7 --- /dev/null +++ b/imotionsApi/man/getTouchActorsUrl.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorsUrl} +\alias{getTouchActorsUrl} +\title{Return the path/url to the touch actors defined for a specific stimulus.} +\usage{ +getTouchActorsUrl(study, stimulusId) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulusId}{The id of the stimulus of interest.} +} +\description{ +Return the path/url to the touch actors defined for a specific stimulus. +} +\keyword{internal} diff --git a/imotionsApi/man/privateDecodeHandType.Rd b/imotionsApi/man/privateDecodeHandType.Rd new file mode 100644 index 0000000..479fb08 --- /dev/null +++ b/imotionsApi/man/privateDecodeHandType.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{privateDecodeHandType} +\alias{privateDecodeHandType} +\title{Private function translating the numeric hand codes stored in a contact in/out file into readable labels.} +\usage{ +privateDecodeHandType(codes) +} +\arguments{ +\item{codes}{A numeric vector of hand codes as stored in the HandType column.} +} +\value{ +A character vector with one label per code. +} +\description{ +Private function translating the numeric hand codes stored in a contact in/out file into readable labels. +} +\keyword{internal} diff --git a/imotionsApi/man/privateGetTouchActorDetails.Rd b/imotionsApi/man/privateGetTouchActorDetails.Rd new file mode 100644 index 0000000..0e4a7b3 --- /dev/null +++ b/imotionsApi/man/privateGetTouchActorDetails.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{privateGetTouchActorDetails} +\alias{privateGetTouchActorDetails} +\title{Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live for a respondent.} +\usage{ +privateGetTouchActorDetails(study, imObject, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object (all touch actors on it) or one row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\value{ +A data.frame with one row per (touch actor, AOI) combination that has an in/out signal. +} +\description{ +Requesting these generates any signal that is missing or older than the contact detection result it derives from, +so this is also what makes the files exist. +} +\keyword{internal} diff --git a/imotionsApi/tests/data/noTouchActors.json b/imotionsApi/tests/data/noTouchActors.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/imotionsApi/tests/data/noTouchActors.json @@ -0,0 +1 @@ +[] diff --git a/imotionsApi/tests/data/touchActorDetails.json b/imotionsApi/tests/data/touchActorDetails.json new file mode 100644 index 0000000..03eaf8a --- /dev/null +++ b/imotionsApi/tests/data/touchActorDetails.json @@ -0,0 +1,26 @@ +[ + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": "../data/AOImetrics.csv", + "fileIdIsEmptyPlaceHolder": false + }, + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "7d3b81e5-4c92-4f07-b6a1-52e8d90c3af6", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorEmptyRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": true + }, + { + "touchActorId": "c8e4a17d-2f60-4b95-a3d8-6e1b70f2c945", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + } +] diff --git a/imotionsApi/tests/data/touchActorDetailsMultiSource.json b/imotionsApi/tests/data/touchActorDetailsMultiSource.json new file mode 100644 index 0000000..21deaa7 --- /dev/null +++ b/imotionsApi/tests/data/touchActorDetailsMultiSource.json @@ -0,0 +1,18 @@ +[ + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": "../data/AOImetrics.csv", + "fileIdIsEmptyPlaceHolder": false + }, + { + "touchActorId": "4f2d6b30-7c44-4d1b-9c19-9c6b9e2a5b60", + "aoiId": "1c9c8b18-3e1d-4b53-9c62-2a6b1a0d7e11", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + } +] diff --git a/imotionsApi/tests/data/touchActorDetails_missingfileId.json b/imotionsApi/tests/data/touchActorDetails_missingfileId.json new file mode 100644 index 0000000..c79da75 --- /dev/null +++ b/imotionsApi/tests/data/touchActorDetails_missingfileId.json @@ -0,0 +1,26 @@ +[ + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": "../data/AOImetrics.csv", + "fileIdIsEmptyPlaceHolder": false + }, + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "7d3b81e5-4c92-4f07-b6a1-52e8d90c3af6", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorEmptyRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": true + }, + { + "touchActorId": "c8e4a17d-2f60-4b95-a3d8-6e1b70f2c945", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": null, + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + } +] diff --git a/imotionsApi/tests/data/touchActorDetails_noMatchingPair.json b/imotionsApi/tests/data/touchActorDetails_noMatchingPair.json new file mode 100644 index 0000000..8bbba3b --- /dev/null +++ b/imotionsApi/tests/data/touchActorDetails_noMatchingPair.json @@ -0,0 +1,10 @@ +[ + { + "touchActorId": "00000000-0000-0000-0000-000000000000", + "aoiId": "00000000-0000-0000-0000-000000000001", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + } +] diff --git a/imotionsApi/tests/data/touchActorEmptyRespondentData.pbin b/imotionsApi/tests/data/touchActorEmptyRespondentData.pbin new file mode 100644 index 0000000..e69de29 diff --git a/imotionsApi/tests/data/touchActorRespondentData.pbin b/imotionsApi/tests/data/touchActorRespondentData.pbin new file mode 100644 index 0000000000000000000000000000000000000000..c2ca1f12caa0a73218cb6cdf047377f5b75d6c11 GIT binary patch literal 2665 zcmb_eO=ufO6rPn7Mc$O6gv=rpA4G6P0*R|#d2KnQM5A9zw$_#`S(eFVwNfR^`l}>c zvQ8%S5OOFXha7q;6iVqKhaP$;rL;*&!9BDMr9J1?Ln(${ilNXqv(kE_8bfIoY3I%N ze!lnKys@=LG9tF&0}i)WuoI(82n9WF^S^%d;UC`w5y#oye=_B;-FrIah}``)`1zlI z|2&913%(d$e*9hhhbh<94}J_jj=vb%e*YC$%h+Y2-!6dF4211du6hk(2>^@-EgbfQ?*{AX@HI;wOPvUx68VXoo*8)BsksE?mJ#I zjd{0>>`u2SKDG!>;TKLgdkFU|Ysqy=7FTnGdLyv*mau^X`Z zMP6cWkr(Gdl;$N-_Vc2TFR49swx<^BUAL3Yb29d&EM4jHn_e%{}z1$l`tVB4PW{!6Ea6a6%r$) zLc$e>g+eds`xJ~C`lUXo=^h>yh3ON7^a&_nr9naks-uP^+Jz+)3fEH0saj#EL=ygR zEh;O+%G@exiQ)Q2F0<{M3)gbPRJyf4S_fbwg=-1wv!BZ5hOqC48<}b;9^Ea)W81}e z?o{1YGg&R>L6;@_N~HyH5>l!b6;plSYRI75ps^r!)a0LAE=Yr_=BGL4e4`vh@D&x( z+E=pa5pLS+@x@dY;$#cU3goWT5(6chT3$`Jb823!YyM2NxJgVr(Ls2pK1}BopSrnK zPv;hsru+s9X(u(GvR70S=@=Ot()VLcA}7%cQ%&l{Vfx&RCIhjKh87ShrTT< zS>QXhk1=0qDcLSGH+);0>|91Y)}RlI-BMoM)%tqf`ca4W=~0I0d9Tu!J}D|lB*KP( z%|m((=8KL)I>o>^)f=M*{&X~=)oQVkNp69-vNy7?gt~Mz0Sb`;yb00hi_H%e*jy2^ z9*^yA#WJ!M&oOY*@DFPf{%n#>{;SkseN%}PCD~Vi{;%idP}a9YNOA>S1B}8qk^d57 zVWluBOlyn2e10T#;tx%L#45B-aAo%*eNsd;!kR>HpWaj^5CS=nka=FHKis2&-Y;s! zsv!iqJZ-h}?rynvLu Date: Fri, 7 Aug 2026 13:37:51 +0200 Subject: [PATCH 02/12] =?UTF-8?q?Replaced=20invisible(lapply(...))=20with?= =?UTF-8?q?=20<<-=20super-assignment=20with=20a=20plain=20for=20loop=20usi?= =?UTF-8?q?ng=20<-=20=E2=80=94=20fixes=20the=20assignment=5Flinter=20error?= =?UTF-8?q?.=20Removed=20one=20space=20from=20the=20NA=5Freal=5F)]=20conti?= =?UTF-8?q?nuation=20to=20match=20the=20expected=2063-space=20hanging=20in?= =?UTF-8?q?dent=20=E2=80=94=20fixes=20the=20indentation=5Flinter=20warning?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imotionsApi/R/imotionsApi.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index 14dc917..b0e1ba0 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -1398,11 +1398,11 @@ convertRecordingTsToIntervals <- function(recordingTs, intervals, keepTs = FALSE } # Converting timestamps to intervals fragments ranges - invisible(lapply(seq_len(nrow(intervals)), function(x) { + for (x in seq_len(nrow(intervals))) { isIn <- timestamps %inrange% intervals[x, c("fragments.start", "fragments.end")] - timestamps[isIn] <<- timestamps[isIn] - intervals[x, ]$fragments.start + + timestamps[isIn] <- timestamps[isIn] - intervals[x, ]$fragments.start + sum(intervals[0:(x - 1), ]$fragments.duration) - })) + } if (inherits(recordingTs, "data.frame")) { recordingTs$Timestamp <- timestamps @@ -1915,7 +1915,7 @@ getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { if (is.null(aois)) { touchAois[, c("name", "type", "group", "area") := list(NA_character_, NA_character_, NA_character_, - NA_real_)] + NA_real_)] } else { # getAois() has already wrapped its result with createImObject, and merge.data.table joins by evaluating # `y[x, on = by]` - so an imObject on the right hand side dispatches to `[.imObject`, which forwards `on` From a02ed6eb42f8eb6dd28b68441a4c34e54f237db1 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 21 Aug 2026 10:59:53 +0200 Subject: [PATCH 03/12] Address remaining review feedback from PR #37 - agrappe: "Do you plan to handle these one? We will need to create export files, this information will be needed." -> Added getAoiRespondentTouchData()/getAoiRespondentTouchMetrics() to expose contact in/out data and metrics beyond the UI. - agrappe: accepting both `stimulus` and an optional `touchActor` allowed contradictory input (e.g. a touch actor from a different stimulus) -> getTouchActorAois() now takes a single `imObject` argument, dispatching on whether it's an imStimulus or an imTouchActor. - agrappe: "when imObject is an imTouchActor, retrieve its stimulus via getStimulus(study, imObject$stimulusId)" -> done; the touch actor's own stimulusId now drives the AOI lookup, with the original touch actor kept aside only to filter pairs down to it afterwards. - agrappe: call privateAoiFiltering() directly instead of getAois(), to avoid manually resetting the class back to data.table before the merge -> done; also removed the now-unneeded class(aois) <- c("data.table", "data.frame") workaround. - agrappe: use unnest(pairs, cols = "aoiId") instead of the manual data.table unlist/by -> done. - agrappe: introduce an imTouchAOI/imTouchAOIList subclass of imAOI(List) so a plain gaze AOI can't be passed to touch-specific functions, and replace getTouchActorDetailsUrl.imAOI with getTouchActorDetailsUrl.imTouchAOI -> done; getTouchActorAois() now returns imTouchAOI(List), and all touch-specific functions assertClass() on it instead of imAOI. - agrappe: introducing imTouchAOI should let getRespondents(study, AOI = touchAoi) use contact details instead of the gaze in/out method; delete getTouchActorRespondents() and add a dedicated privateRespondentFiltering.imTouchAOI S3 method -> done. Without this, getRespondents(study, AOI = touchAoi) silently fell through to the gaze method (imTouchAOI passes assertClass(AOI, "imAOI")) and returned an incorrect, misleadingly empty result on a touch-only study. privateRespondentFiltering.imTouchAOI() resolves the AOI's stimulus, filters to respondents exposed to it, then keeps only those whose contact details contain a matching (touchActorId, aoiId) pair. getTouchActorRespondents() is removed, superseded by this dispatch. - agrappe: assertClass(touchAoi, "imTouchAOI", ...) should be used in every touch-specific function -> done throughout. - Zurisen: replying on keeping getTouchActorAois() flexible to accept either a stimulus or a touch actor -> matches the imObject dispatch implemented above. --- .../man/getTouchActorDetailsUrl.imAOI.Rd | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd deleted file mode 100644 index 4dc4183..0000000 --- a/imotionsApi/man/getTouchActorDetailsUrl.imAOI.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/imotionsApi.R -\name{getTouchActorDetailsUrl.imAOI} -\alias{getTouchActorDetailsUrl.imAOI} -\title{getTouchActorDetailsUrl.imAOI method to return the path/url to one touch actor's contact in/out details.} -\usage{ -\method{getTouchActorDetailsUrl}{imAOI}(study, imObject, respondent) -} -\arguments{ -\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} - -\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} - -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} -} -\description{ -Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports -every AOI of the actors it matches in one response. -} -\keyword{internal} From 71d5812d31a039ea51c5a2076482ef66401c32a0 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 21 Aug 2026 11:00:05 +0200 Subject: [PATCH 04/12] Address remaining review feedback from PR #37 - agrappe: "Do you plan to handle these one? We will need to create export files, this information will be needed." -> Added getAoiRespondentTouchData()/getAoiRespondentTouchMetrics() to expose contact in/out data and metrics beyond the UI. - agrappe: accepting both `stimulus` and an optional `touchActor` allowed contradictory input (e.g. a touch actor from a different stimulus) -> getTouchActorAois() now takes a single `imObject` argument, dispatching on whether it's an imStimulus or an imTouchActor. - agrappe: "when imObject is an imTouchActor, retrieve its stimulus via getStimulus(study, imObject$stimulusId)" -> done; the touch actor's own stimulusId now drives the AOI lookup, with the original touch actor kept aside only to filter pairs down to it afterwards. - agrappe: call privateAoiFiltering() directly instead of getAois(), to avoid manually resetting the class back to data.table before the merge -> done; also removed the now-unneeded class(aois) <- c("data.table", "data.frame") workaround. - agrappe: use unnest(pairs, cols = "aoiId") instead of the manual data.table unlist/by -> done. - agrappe: introduce an imTouchAOI/imTouchAOIList subclass of imAOI(List) so a plain gaze AOI can't be passed to touch-specific functions, and replace getTouchActorDetailsUrl.imAOI with getTouchActorDetailsUrl.imTouchAOI -> done; getTouchActorAois() now returns imTouchAOI(List), and all touch-specific functions assertClass() on it instead of imAOI. - agrappe: introducing imTouchAOI should let getRespondents(study, AOI = touchAoi) use contact details instead of the gaze in/out method; delete getTouchActorRespondents() and add a dedicated privateRespondentFiltering.imTouchAOI S3 method -> done. Without this, getRespondents(study, AOI = touchAoi) silently fell through to the gaze method (imTouchAOI passes assertClass(AOI, "imAOI")) and returned an incorrect, misleadingly empty result on a touch-only study. privateRespondentFiltering.imTouchAOI() resolves the AOI's stimulus, filters to respondents exposed to it, then keeps only those whose contact details contain a matching (touchActorId, aoiId) pair. getTouchActorRespondents() is removed, superseded by this dispatch. - agrappe: assertClass(touchAoi, "imTouchAOI", ...) should be used in every touch-specific function -> done throughout. - Zurisen: replying on keeping getTouchActorAois() flexible to accept either a stimulus or a touch actor -> matches the imObject dispatch implemented above. --- imotionsApi/NAMESPACE | 4 +- imotionsApi/R/imotionsApi.R | 167 ++++++++++-------- imotionsApi/man/getRespondents.Rd | 9 +- imotionsApi/man/getTouchActorAois.Rd | 23 ++- imotionsApi/man/getTouchActorDetailsUrl.Rd | 4 +- .../man/getTouchActorDetailsUrl.imTouchAOI.Rd | 21 +++ imotionsApi/man/getTouchActorRespondents.Rd | 32 ---- .../privateRespondentFiltering.imTouchAOI.Rd | 29 +++ .../tests/testthat/test-getTouchActors.R | 85 +++++---- 9 files changed, 222 insertions(+), 152 deletions(-) create mode 100644 imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd delete mode 100644 imotionsApi/man/getTouchActorRespondents.Rd create mode 100644 imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd diff --git a/imotionsApi/NAMESPACE b/imotionsApi/NAMESPACE index b435a8b..e4b2564 100644 --- a/imotionsApi/NAMESPACE +++ b/imotionsApi/NAMESPACE @@ -6,8 +6,8 @@ S3method(getAoiDetailsUrl,imAOI) S3method(getAoiDetailsUrl,imStimulus) S3method(getSensorsUrl,imRespondent) S3method(getSensorsUrl,imSegment) -S3method(getTouchActorDetailsUrl,imAOI) S3method(getTouchActorDetailsUrl,imStimulus) +S3method(getTouchActorDetailsUrl,imTouchAOI) S3method(getUploadAoiMetricsUrl,imSegment) S3method(getUploadEventsUrl,imRespondent) S3method(getUploadMetricsUrl,imRespondent) @@ -22,6 +22,7 @@ S3method(privateAoiFiltering,imStudy) S3method(privateRespondentFiltering,imAOI) S3method(privateRespondentFiltering,imStimulus) S3method(privateRespondentFiltering,imStudy) +S3method(privateRespondentFiltering,imTouchAOI) S3method(privateUploadAoiMetrics,imRespondent) S3method(privateUploadAoiMetrics,imSegment) export(convertRecordingTsToIntervals) @@ -43,7 +44,6 @@ export(getSensorsMetadata) export(getStimuli) export(getStimulus) export(getTouchActorAois) -export(getTouchActorRespondents) export(getTouchActors) export(imConnection) export(imStudy) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index b0e1ba0..0673e09 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -707,7 +707,9 @@ getAoi <- function(study, AOIId) { #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. #' @param stimulus Optional - An imStimulus object as returned from \code{\link{getStimuli}}. -#' @param AOI Optional - An imAOI object as returned from \code{\link{getAois}}. +#' @param AOI Optional - An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned +#' from \code{\link{getTouchActorAois}} to get the respondents that have contact data for that specific +#' touch actor AOI instead of gaze data. #' @param segment Optional - An imSegment object as returned from \code{\link{getSegments}}. #' @param keepRespondentVariables Optional - A boolean indicating whether respondent variables should be kept (if they #' are available). If this has the default value of FALSE, only the "group" variable is @@ -736,6 +738,11 @@ getAoi <- function(study, AOIId) { #' ## Get all respondents for whom a specific AOI has been defined #' respondents <- imotionsApi::getRespondents(study, AOI = AOIs[1, ]) #' +#' ## Get all respondents that have contact data for a specific touch actor AOI +#' respondent <- imotionsApi::getRespondents(study)[1, ] +#' touchAoi <- imotionsApi::getTouchActorAois(study, stimuli[1, ], respondent)[1, ] +#' respondents <- imotionsApi::getRespondents(study, AOI = touchAoi) +#' #' ## Get all respondents in a specific segment exposed to a specific stimulus #' respondents <- imotionsApi::getRespondents(study, stimulus = stimuli[1, ], segment = segments[1, ]) #' @@ -870,6 +877,42 @@ privateRespondentFiltering.imAOI <- function(study, obj) { } +#' Get respondents that have contact data for a specific touch actor AOI. +#' +#' S3 method to get all respondents with contact in/out data for a specific (touch actor, AOI) pair. This exists +#' because \code{\link{privateRespondentFiltering.imAOI}} resolves respondents through the gaze in/out endpoint, which +#' returns nothing on a study without eyetracking data - exactly the case contact metrics exist to support. +#' +#' Unlike the gaze equivalent, the contact endpoint has no "all respondents" wildcard for a single touch actor AOI +#' (see \code{\link{getTouchActorDetailsUrl.imTouchAOI}}), so this is resolved one respondent at a time: every +#' respondent exposed to the AOI's stimulus is queried (via the stimulus-wide wildcard, one call each) and kept only +#' if its own contact details contain a matching (touchActorId, aoiId) pair. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param obj An imTouchAOI object as returned from \code{\link{getTouchActorAois}} for which you would like to get +#' the respondents. +#' +#' @return A data.table with all respondents that have contact data for this specific touch actor AOI. +#' @keywords internal +#' @exportS3Method privateRespondentFiltering imTouchAOI +privateRespondentFiltering.imTouchAOI <- function(study, obj) { + stimulus <- getStimulus(study, obj$stimulusId) + respondents <- privateRespondentFiltering.imStimulus(study, stimulus) + + hasContactData <- vapply(seq_len(nrow(respondents)), function(idx) { + details <- suppressWarnings(privateGetTouchActorDetails(study, stimulus, respondents[idx, ])) + + if (is.null(details) || nrow(details) == 0) { + return(FALSE) + } + + return(any(details$touchActorId == obj$touchActorId & details$aoiId == obj$id)) + }, logical(1)) + + return(respondents[hasContactData, ]) +} + + #' Get a specific respondent from a study. #' #' Available respondents can be found with \code{\link{getRespondents}}. @@ -1835,12 +1878,14 @@ getTouchActors <- function(study, stimulus) { #' result they derive from, which is why a respondent is required. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. -#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' @param imObject An imStimulus object as returned from \code{\link{getStimuli}} to return every touch actor's AOIs +#' on it, or an imTouchActor object as returned from \code{\link{getTouchActors}} to return only that +#' actor's AOIs. #' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. -#' @param touchActor Optional - an imTouchActor object as returned from \code{\link{getTouchActors}} to only return -#' that actor's AOIs. Defaults to NULL, meaning every touch actor on the stimulus. #' -#' @return An imAOIList object (data.table) with one row per (touch actor, AOI) combination, or NULL if none exist. +#' @return An imTouchAOIList object (data.table, a subclass of imAOIList so shared AOI functions still accept it) +#' with one row per (touch actor, AOI) combination, or NULL if none exist. A single-row result is an +#' imTouchAOI, subclassing imAOI the same way. #' @export #' @examples #' \dontrun{ @@ -1851,16 +1896,27 @@ getTouchActors <- function(study, stimulus) { #' respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] #' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) #' +#' touchActor <- imotionsApi::getTouchActors(study, stimulus)[1, ] +#' touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondent) # only that actor's AOIs +#' #' print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair #' } -getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { - # set local variable to remove warnings in `devtools::check()` - aoiId <- touchActorId <- touchActorName <- hand <- detectionMethod <- mediaSourceType <- stimulusId <- - stimulusName <- NULL - +getTouchActorAois <- function(study, imObject, respondent) { + assertValid(hasArg(imObject), + "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`") assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") - assertClass(touchActor, "imTouchActor", "`touchActor` argument is not an imTouchActor object") + + if (inherits(imObject, "imTouchActor")) { + # The touch actor already carries its parent stimulus id, so that alone can drive the AOI lookup below - + # `touchActor` is kept aside only to filter the pairs down to this one actor further down. + touchActor <- imObject + stimulus <- getStimulus(study, imObject$stimulusId) + } else { + assertClass(imObject, "imStimulus", "`imObject` argument is not an imStimulus or imTouchActor object") + touchActor <- NULL + stimulus <- imObject + } touchActors <- getTouchActors(study, stimulus) @@ -1880,9 +1936,8 @@ getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { mediaSourceType = touchActors$mediaSourceType, stimulusId = touchActors$stimulusId, stimulusName = touchActors$stimulusName, aoiId = touchActors$interactiveAoiIds) - pairs <- pairs[, .(aoiId = unlist(aoiId)), - by = .(touchActorId, touchActorName, hand, detectionMethod, mediaSourceType, stimulusId, - stimulusName)] + pairs <- unnest(pairs, cols = c("aoiId")) + setDT(pairs) if (nrow(pairs) == 0) { warning(paste("No interactive AOI defined for any touch actor on stimulus:", stimulus$name)) @@ -1904,24 +1959,16 @@ getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { return(NULL) } - # The AOI definition carries name/type/group/area, which the touch actor endpoint does not report and which - # nicely labels the metrics grid - but getAois() only ever reaches the Stimulus/Scene camera's AOI set (it - # predates per-camera AOI models, see AOIHandler.cs/AOICollectionBase on the EmotionTool side). A left join keeps - # every touch actor AOI regardless of camera: a Scene AOI gets the full definition, anything else gets NA there - # instead of being dropped. Metrics computation and upload only need id/fileId/resultId/stimulusId, all already - # set above from the touch actor side, so a missing definition costs display polish, not correctness - the - # in/out signal and its metrics file are written and discovered by fileId alone, camera-agnostic on that side. - aois <- suppressWarnings(getAois(study, stimulus)) + # AOI definitions only reach the Stimulus/Scene camera, so a non-Scene touch actor gets NA name/type/group/area + # instead of being dropped (metrics/upload only need id/fileId/resultId, set above). suppressWarnings() is kept + # here because privateAoiFiltering() warns unconditionally when a stimulus has no gaze AOI at all - the normal + # case for a touch-actor-only stimulus. + aois <- suppressWarnings(privateAoiFiltering(study, stimulus)) if (is.null(aois)) { touchAois[, c("name", "type", "group", "area") := list(NA_character_, NA_character_, NA_character_, NA_real_)] } else { - # getAois() has already wrapped its result with createImObject, and merge.data.table joins by evaluating - # `y[x, on = by]` - so an imObject on the right hand side dispatches to `[.imObject`, which forwards `on` - # through `...` where `[.data.table`'s substitute(on) can no longer resolve it. Join on a plain data.table. - class(aois) <- c("data.table", "data.frame") - touchAois <- merge(touchAois, aois[, c("id", "name", "type", "group", "area")], by.x = "aoiId", by.y = "id", all.x = TRUE) } @@ -1931,50 +1978,17 @@ getTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL) { setnames(touchAois, "aoiId", "id") setcolorder(touchAois, c("stimulusId", "stimulusName", "id", "name", "type", "group", "area")) touchAois <- createImObject(touchAois, "AOI") - return(touchAois) -} - -#' Get the respondents that have contact data for a specific stimulus. -#' -#' \code{\link{getRespondents}} cannot be used with an AOI here: its imAOI method resolves respondents through the gaze -#' in/out endpoint, which returns nothing on a study without eyetracking data - exactly the case contact metrics exist -#' to support. This filters the stimulus's respondents by whether contact in/out signals exist for them instead. -#' -#' @param study An imStudy object as returned from \code{\link{imStudy}}. -#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. -#' @param segment Optional - an imSegment object as returned from \code{\link{getSegments}} to filter respondents. -#' -#' @return An imRespondentList object (data.table) with the respondents that have contact data. -#' @export -#' @examples -#' \dontrun{ -#' connection <- imotionsApi::imConnection("xxxxxxxx") -#' studies <- imotionsApi::listStudies(connection) -#' study <- imotionsApi::imStudy(connection, studies$id[1]) -#' stimulus <- imotionsApi::getStimuli(study)[1, ] -#' respondents <- imotionsApi::getTouchActorRespondents(study, stimulus) -#' } -getTouchActorRespondents <- function(study, stimulus, segment = NULL) { - assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") - assertValid(hasArg(stimulus), "Please specify a stimulus loaded with `getStimuli()`") - - assertClass(study, "imStudy", "`study` argument is not an imStudy object") - assertClass(stimulus, "imStimulus", "`stimulus` argument is not an imStimulus object") - assertClass(segment, "imSegment", "`segment` argument is not an imSegment object") - - respondents <- getRespondents(study, stimulus = stimulus, segment = segment) - - if (nrow(respondents) == 0) { - return(respondents) + # Subclassing rather than leaving this as a plain imAOI keeps a regular gaze AOI from being accepted where a + # touch AOI is required (touchActorId is not something a gaze imAOI carries). Prepending onto the class + # createImObject() just set keeps every shared AOI function working unchanged through inheritance. + if (inherits(touchAois, "imAOIList")) { + class(touchAois) <- c("imTouchAOIList", class(touchAois)) + } else { + class(touchAois) <- c("imTouchAOI", class(touchAois)) } - hasContactData <- vapply(seq_len(nrow(respondents)), function(idx) { - details <- suppressWarnings(privateGetTouchActorDetails(study, stimulus, respondents[idx, ])) - return(!is.null(details) && nrow(details) > 0) - }, logical(1)) - - return(respondents[hasContactData, ]) + return(touchAois) } @@ -2010,7 +2024,7 @@ getAoiRespondentTouchData <- function(study, touchAoi, respondent) { assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") assertClass(study, "imStudy", "`study` argument is not an imStudy object") - assertClass(touchAoi, "imAOI", "`touchAoi` argument is not an imAOI object") + assertClass(touchAoi, "imTouchAOI", "`touchAoi` argument is not an imTouchAOI object") assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") details <- privateGetTouchActorDetails(study, touchAoi, respondent) @@ -2084,7 +2098,7 @@ getAoiRespondentTouchMetrics <- function(study, touchAoi, respondent) { assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") assertClass(study, "imStudy", "`study` argument is not an imStudy object") - assertClass(touchAoi, "imAOI", "`touchAoi` argument is not an imAOI object") + assertClass(touchAoi, "imTouchAOI", "`touchAoi` argument is not an imTouchAOI object") assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") endpoint <- paste0("AOI: ", touchAoi$name, ", Respondent: ", respondent$name) @@ -3332,8 +3346,8 @@ getTouchActorsUrl <- function(study, stimulusId) { } -#' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imAOI/imStimulus object and a -#' respondent object. +#' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imStimulus object +#' and a respondent object. #' #' Return the path/url to the contact in/out details for one touch actor, or for every touch actor on a stimulus. #' Contact detection is desktop-only, so this is only ever used for a local study. @@ -3348,16 +3362,17 @@ getTouchActorDetailsUrl <- function(study, imObject, respondent) { } -#' getTouchActorDetailsUrl.imAOI method to return the path/url to one touch actor's contact in/out details. +#' getTouchActorDetailsUrl.imTouchAOI method to return the path/url to one touch actor's contact in/out details. #' #' Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports -#' every AOI of the actors it matches in one response. +#' every AOI of the actors it matches in one response. Dispatching on imTouchAOI rather than imAOI matters here: an +#' ordinary gaze imAOI is not guaranteed to carry touchActorId, which this method relies on. #' #' @inheritParams getTouchActorDetailsUrl #' #' @keywords internal -#' @exportS3Method getTouchActorDetailsUrl imAOI -getTouchActorDetailsUrl.imAOI <- function(study, imObject, respondent) { +#' @exportS3Method getTouchActorDetailsUrl imTouchAOI +getTouchActorDetailsUrl.imTouchAOI <- function(study, imObject, respondent) { url <- getTouchActorsUrl(study, imObject$stimulusId) url <- file.path(url, "respondent", respondent$id, imObject$touchActorId) return(url) diff --git a/imotionsApi/man/getRespondents.Rd b/imotionsApi/man/getRespondents.Rd index 7f8f998..5f3144f 100644 --- a/imotionsApi/man/getRespondents.Rd +++ b/imotionsApi/man/getRespondents.Rd @@ -17,7 +17,9 @@ getRespondents( \item{stimulus}{Optional - An imStimulus object as returned from \code{\link{getStimuli}}.} -\item{AOI}{Optional - An imAOI object as returned from \code{\link{getAois}}.} +\item{AOI}{Optional - An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned +from \code{\link{getTouchActorAois}} to get the respondents that have contact data for that specific +touch actor AOI instead of gaze data.} \item{segment}{Optional - An imSegment object as returned from \code{\link{getSegments}}.} @@ -53,6 +55,11 @@ respondents <- imotionsApi::getRespondents(study, segment = segments[1, ]) ## Get all respondents for whom a specific AOI has been defined respondents <- imotionsApi::getRespondents(study, AOI = AOIs[1, ]) +## Get all respondents that have contact data for a specific touch actor AOI +respondent <- imotionsApi::getRespondents(study)[1, ] +touchAoi <- imotionsApi::getTouchActorAois(study, stimuli[1, ], respondent)[1, ] +respondents <- imotionsApi::getRespondents(study, AOI = touchAoi) + ## Get all respondents in a specific segment exposed to a specific stimulus respondents <- imotionsApi::getRespondents(study, stimulus = stimuli[1, ], segment = segments[1, ]) diff --git a/imotionsApi/man/getTouchActorAois.Rd b/imotionsApi/man/getTouchActorAois.Rd index 77ca560..5e3bb36 100644 --- a/imotionsApi/man/getTouchActorAois.Rd +++ b/imotionsApi/man/getTouchActorAois.Rd @@ -4,25 +4,29 @@ \alias{getTouchActorAois} \title{Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data.} \usage{ -getTouchActorAois(study, stimulus, respondent, touchActor = NULL) +getTouchActorAois(study, imObject, respondent) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} +\item{imObject}{An imStimulus object as returned from \code{\link{getStimuli}} to return every touch actor's AOIs +on it, or an imTouchActor object as returned from \code{\link{getTouchActors}} to return only that +actor's AOIs.} \item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} - -\item{touchActor}{Optional - an imTouchActor object as returned from \code{\link{getTouchActors}} to only return -that actor's AOIs. Defaults to NULL, meaning every touch actor on the stimulus.} } \value{ -An imAOIList object (data.table) with one row per (touch actor, AOI) combination, or NULL if none exist. +An imTouchAOIList object (data.table, a subclass of imAOIList so shared AOI functions still accept it) + with one row per (touch actor, AOI) combination, or NULL if none exist. A single-row result is an + imTouchAOI, subclassing imAOI the same way. } \description{ Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This -returns one row per pair, carrying the AOI's own definition (name, type, group, area) so it can be used anywhere an -imAOI is expected, plus the touch actor that produced it and the path to the contact in/out signal. +returns one row per pair, plus the touch actor that produced it and the path to the contact in/out signal, so it +can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area) when +one is available - which today is only for a touch actor on the Stimulus/Scene camera, since that is the only +camera \code{\link{getAois}} can see. A touch actor on any other media source (e.g. Environment) still gets its +row, with those four columns NA - contact and metrics are unaffected, only their display labelling is. } \details{ Requesting this triggers generation of any in/out signals that are missing or older than the contact detection @@ -37,6 +41,9 @@ stimulus <- imotionsApi::getStimuli(study)[1, ] respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +touchActor <- imotionsApi::getTouchActors(study, stimulus)[1, ] +touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondent) # only that actor's AOIs + print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair } } diff --git a/imotionsApi/man/getTouchActorDetailsUrl.Rd b/imotionsApi/man/getTouchActorDetailsUrl.Rd index cd3ef0b..5917342 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.Rd @@ -2,8 +2,8 @@ % Please edit documentation in R/imotionsApi.R \name{getTouchActorDetailsUrl} \alias{getTouchActorDetailsUrl} -\title{Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imAOI/imStimulus object and a -respondent object.} +\title{Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imStimulus object +and a respondent object.} \usage{ getTouchActorDetailsUrl(study, imObject, respondent) } diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd new file mode 100644 index 0000000..35caf86 --- /dev/null +++ b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorDetailsUrl.imTouchAOI} +\alias{getTouchActorDetailsUrl.imTouchAOI} +\title{getTouchActorDetailsUrl.imTouchAOI method to return the path/url to one touch actor's contact in/out details.} +\usage{ +\method{getTouchActorDetailsUrl}{imTouchAOI}(study, imObject, respondent) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +} +\description{ +Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports +every AOI of the actors it matches in one response. Dispatching on imTouchAOI rather than imAOI matters here: an +ordinary gaze imAOI is not guaranteed to carry touchActorId, which this method relies on. +} +\keyword{internal} diff --git a/imotionsApi/man/getTouchActorRespondents.Rd b/imotionsApi/man/getTouchActorRespondents.Rd deleted file mode 100644 index 3c8596d..0000000 --- a/imotionsApi/man/getTouchActorRespondents.Rd +++ /dev/null @@ -1,32 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/imotionsApi.R -\name{getTouchActorRespondents} -\alias{getTouchActorRespondents} -\title{Get the respondents that have contact data for a specific stimulus.} -\usage{ -getTouchActorRespondents(study, stimulus, segment = NULL) -} -\arguments{ -\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} - -\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} - -\item{segment}{Optional - an imSegment object as returned from \code{\link{getSegments}} to filter respondents.} -} -\value{ -An imRespondentList object (data.table) with the respondents that have contact data. -} -\description{ -\code{\link{getRespondents}} cannot be used with an AOI here: its imAOI method resolves respondents through the gaze -in/out endpoint, which returns nothing on a study without eyetracking data - exactly the case contact metrics exist -to support. This filters the stimulus's respondents by whether contact in/out signals exist for them instead. -} -\examples{ -\dontrun{ -connection <- imotionsApi::imConnection("xxxxxxxx") -studies <- imotionsApi::listStudies(connection) -study <- imotionsApi::imStudy(connection, studies$id[1]) -stimulus <- imotionsApi::getStimuli(study)[1, ] -respondents <- imotionsApi::getTouchActorRespondents(study, stimulus) -} -} diff --git a/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd b/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd new file mode 100644 index 0000000..5810e26 --- /dev/null +++ b/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{privateRespondentFiltering.imTouchAOI} +\alias{privateRespondentFiltering.imTouchAOI} +\title{Get respondents that have contact data for a specific touch actor AOI.} +\usage{ +\method{privateRespondentFiltering}{imTouchAOI}(study, obj) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{obj}{An imTouchAOI object as returned from \code{\link{getTouchActorAois}} for which you would like to get +the respondents.} +} +\value{ +A data.table with all respondents that have contact data for this specific touch actor AOI. +} +\description{ +S3 method to get all respondents with contact in/out data for a specific (touch actor, AOI) pair. This exists +because \code{\link{privateRespondentFiltering.imAOI}} resolves respondents through the gaze in/out endpoint, which +returns nothing on a study without eyetracking data - exactly the case contact metrics exist to support. +} +\details{ +Unlike the gaze equivalent, the contact endpoint has no "all respondents" wildcard for a single touch actor AOI +(see \code{\link{getTouchActorDetailsUrl.imTouchAOI}}), so this is resolved one respondent at a time: every +respondent exposed to the AOI's stimulus is queried (via the stimulus-wide wildcard, one call each) and kept only +if its own contact details contain a matching (touchActorId, aoiId) pair. +} +\keyword{internal} diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index 8d4995a..de807fd 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -139,6 +139,7 @@ test_that("local return - a fileId already present short-circuits the request", touchAoi <- aoiDefinitions()[1, ] touchAoi$fileId <- "../data/touchActorRespondentData.pbin" touchAoi$touchActorId <- TA1 + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) details <- mockedGetTouchActorDetails(study, touchAoi, respondent, expectedCall = 0) @@ -165,15 +166,14 @@ test_that("warning - contact data is not available for a remote study", { # getTouchActorAois =================================================================================================== context("getTouchActorAois()") -mockedGetTouchActorAois <- function(study, stimulus, respondent, touchActor = NULL, - detailsPath = touchActorDetailsPath) { +mockedGetTouchActorAois <- function(study, imObject, respondent, detailsPath = touchActorDetailsPath) { touchActors <- suppressWarnings(mockedGetTouchActors(study, stimulus)) touchAois <- mockr::with_mock( getTouchActors = function(...) touchActors, - getAois = function(...) aoiDefinitions(), + privateAoiFiltering = function(...) aoiDefinitions(), privateGetTouchActorDetails = function(...) jsonlite::fromJSON(detailsPath), { - getTouchActorAois(study, stimulus, respondent, touchActor) + getTouchActorAois(study, imObject, respondent) } ) @@ -181,6 +181,10 @@ mockedGetTouchActorAois <- function(study, stimulus, respondent, touchActor = NU } test_that("error - arguments are missing or not from the good class", { + expect_error(getTouchActorAois(study, respondent = respondent), + "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`", + fixed = TRUE, info = "missing `imObject` param not handled properly") + expect_error(getTouchActorAois(study, stimulus), "Please specify a respondent loaded with `getRespondents()`", fixed = TRUE, info = "missing `respondent` param not handled properly") @@ -188,9 +192,9 @@ test_that("error - arguments are missing or not from the good class", { "`respondent` argument is not an imRespondent object", info = "respondent not being an imRespondent object should throw an error") - expect_error(getTouchActorAois(study, stimulus, respondent, touchActor = "whatever"), - "`touchActor` argument is not an imTouchActor object", - info = "touchActor not being an imTouchActor object should throw an error") + expect_error(getTouchActorAois(study, "whatever", respondent), + "`imObject` argument is not an imStimulus or imTouchActor object", + info = "imObject not being an imStimulus or an imTouchActor object should throw an error") }) test_that("local return - one row per (touch actor, AOI) combination", { @@ -211,6 +215,17 @@ test_that("local return - the AOI definition wins the id/name columns so it can expect_identical(unique(touchAois$stimulusName), "IAAF", "stimulus name should be carried over") }) +test_that("local return - result is an imTouchAOI(List), a subclass of imAOI(List) rather than a plain one", { + touchAois <- mockedGetTouchActorAois(study, stimulus, respondent) + + expect_identical(class(touchAois), c("imTouchAOIList", "imAOIList", "imObjectList", "data.table", "data.frame"), + "wrong class for a multi-row result") + + singleTouchAoi <- touchAois[1, ] + expect_identical(class(singleTouchAoi), c("imTouchAOI", "imAOI", "imObject", "data.table", "data.frame"), + "wrong class for a single-row result") +}) + test_that("local return - the touch actor is kept alongside under its own columns", { touchAois <- mockedGetTouchActorAois(study, stimulus, respondent) @@ -231,7 +246,7 @@ test_that("local return - the fileId of each combination is carried over", { test_that("local return - filtering on a single touch actor", { touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] - touchAois <- mockedGetTouchActorAois(study, stimulus, respondent, touchActor) + touchAois <- mockedGetTouchActorAois(study, touchActor, respondent) expect_equal(nrow(touchAois), 1, info = "only the second actor's single AOI should be returned") expect_identical(touchAois$touchActorId, TA2, "wrong touch actor kept") @@ -245,7 +260,7 @@ test_that("local return - a touch actor on a media source getAois() cannot see k touchAois <- mockr::with_mock( getTouchActors = function(...) touchActorsMulti, - getAois = function(...) aoiDefinitions(), + privateAoiFiltering = function(...) aoiDefinitions(), privateGetTouchActorDetails = function(...) jsonlite::fromJSON("../data/touchActorDetailsMultiSource.json"), { getTouchActorAois(study, stimulus, respondent) } @@ -290,6 +305,7 @@ touchAoiInOut <- function(fileId = "../data/touchActorRespondentData.pbin", resu touchAoi$touchActorId <- TA1 touchAoi$fileId <- fileId touchAoi$resultId <- resultId + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) return(touchAoi) } @@ -306,8 +322,8 @@ test_that("error - arguments are missing or not from the good class", { info = "missing `respondent` param not handled properly") expect_error(getAoiRespondentTouchData(study, touchAoi = "whatever", respondent), - "`touchAoi` argument is not an imAOI object", - info = "touchAoi not being an imAOI object should throw an error") + "`touchAoi` argument is not an imTouchAOI object", + info = "touchAoi not being an imTouchAOI object should throw an error") }) test_that("local return - intervals for a specific (touch actor, AOI)/respondent pair", { @@ -362,8 +378,8 @@ context("getAoiRespondentTouchMetrics()") test_that("error - arguments are missing or not from the good class", { expect_error(getAoiRespondentTouchMetrics(study, touchAoi = "whatever", respondent), - "`touchAoi` argument is not an imAOI object", - info = "touchAoi not being an imAOI object should throw an error") + "`touchAoi` argument is not an imTouchAOI object", + info = "touchAoi not being an imTouchAOI object should throw an error") }) test_that("local return - metrics are read from the resultId", { @@ -383,41 +399,47 @@ test_that("warning - no metrics computed yet for this combination", { }) -# getTouchActorRespondents ============================================================================================ -context("getTouchActorRespondents()") +# privateRespondentFiltering.imTouchAOI =============================================================================== +context("privateRespondentFiltering.imTouchAOI()") -test_that("error - arguments are missing or not from the good class", { - expect_error(getTouchActorRespondents(), "Please specify a study loaded with `imStudy()`", fixed = TRUE, - info = "missing `study` param not handled properly") - - expect_error(getTouchActorRespondents(study), "Please specify a stimulus loaded with `getStimuli()`", fixed = TRUE, - info = "missing `stimulus` param not handled properly") - - expect_error(getTouchActorRespondents(study, stimulus = "whatever"), - "`stimulus` argument is not an imStimulus object", - info = "stimulus not being an imStimulus object should throw an error") -}) +touchAoiForRespondents <- function() { + touchAoi <- aoiDefinitions()[1, ] + touchAoi$touchActorId <- TA1 + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) + return(touchAoi) +} -test_that("local return - only respondents that have contact data are kept", { +test_that("local return - getRespondents() dispatches on imTouchAOI to use contact data, not gaze data", { allRespondents <- getRespondents(study, stimulus = stimulus) - # Only the first respondent of the stimulus has contact signals. + # Only the first respondent of the stimulus has a matching (touchActorId, aoiId) contact pair. respondents <- mockr::with_mock( privateGetTouchActorDetails = function(study, imObject, respondent) { if (respondent$id == allRespondents$id[1]) jsonlite::fromJSON(touchActorDetailsPath) else NULL }, { - getTouchActorRespondents(study, stimulus) + getRespondents(study, AOI = touchAoiForRespondents()) } ) - expect_equal(nrow(respondents), 1, info = "only the respondent with contact data should be kept") + expect_equal(nrow(respondents), 1, info = "only the respondent with a matching contact pair should be kept") expect_identical(respondents$id, allRespondents$id[1], "wrong respondent kept") }) +test_that("local return - a respondent with contact data for another (touch actor, AOI) pair is not kept", { + respondents <- mockr::with_mock( + # This respondent has contact data, but not for the TA1/AOI1 pair being asked about. + privateGetTouchActorDetails = function(...) jsonlite::fromJSON("../data/touchActorDetails_noMatchingPair.json"), { + getRespondents(study, AOI = touchAoiForRespondents()) + } + ) + + expect_equal(nrow(respondents), 0, info = "no respondent should be kept") +}) + test_that("local return - no respondent has contact data", { respondents <- mockr::with_mock( privateGetTouchActorDetails = function(...) NULL, { - getTouchActorRespondents(study, stimulus) + getRespondents(study, AOI = touchAoiForRespondents()) } ) @@ -453,6 +475,7 @@ test_that("url for every touch actor on a stimulus uses the wildcard form", { test_that("url for a single touch actor uses its id - the wildcard sits on the actor, not the AOI", { touchAoi <- aoiDefinitions()[1, ] touchAoi$touchActorId <- TA1 + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) url <- imotionsApi:::getTouchActorDetailsUrl(study, touchAoi, respondent) From d9c2adc127f23ec4e3775cb6bd87dee7b76a8a89 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 21 Aug 2026 12:59:17 +0200 Subject: [PATCH 05/12] Fixed lint max line characters error. --- imotionsApi/tests/testthat/test-getTouchActors.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index de807fd..4ffece0 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -20,6 +20,7 @@ touchActorsPath <- "../data/touchActors.json" noTouchActorsPath <- "../data/noTouchActors.json" touchActorDetailsPath <- "../data/touchActorDetails.json" touchActorDetailsMissingPath <- "../data/touchActorDetails_missingfileId.json" +touchActorDetailsNoMatchPath <- "../data/touchActorDetails_noMatchingPair.json" # The AOI definitions getTouchActorAois() joins against - what getAois() would return for this stimulus. aoiDefinitions <- function() { @@ -428,7 +429,7 @@ test_that("local return - getRespondents() dispatches on imTouchAOI to use conta test_that("local return - a respondent with contact data for another (touch actor, AOI) pair is not kept", { respondents <- mockr::with_mock( # This respondent has contact data, but not for the TA1/AOI1 pair being asked about. - privateGetTouchActorDetails = function(...) jsonlite::fromJSON("../data/touchActorDetails_noMatchingPair.json"), { + privateGetTouchActorDetails = function(...) jsonlite::fromJSON(touchActorDetailsNoMatchPath), { getRespondents(study, AOI = touchAoiForRespondents()) } ) From f233b6ace4b0a9dba37d23bfc7c80ef24f985af8 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 21 Aug 2026 15:38:23 +0200 Subject: [PATCH 06/12] Resolve touch actor AOI names/geometry from every camera, not just Scene getTouchActorAois() joined every (touch actor, AOI) pair against privateAoiFiltering(), which only ever reaches the Stimulus/Scene camera's AOI set. A touch actor whose interactive AOI lives on another camera (e.g. Environment) matched nothing in that join, so its name/type/group/area came back NA even though contact detection and metrics were unaffected. Add privateGetTouchActorAoiDefinitions(), backed by the desktop's new GET /touchactors//stimuli//aois endpoint, which reports AOI definitions across every touch-capable camera. getTouchActorAois() now joins against that instead, resolving names/types/areas regardless of camera - AOI ids are unique per camera's own model, so the join key doesn't need to change. This is shared by the UI grid pipeline (mainContactAggregate.R, processContactRespondentData.R) as well as the export script, so the fix applies to both without touching either. Updated the existing regression test that had asserted the old NA behaviour as correct, added a passing-case test for a non-Scene AOI, and a fallback test for when no AOI definitions are available at all. Verified: full package test suite passes (0 failures). Co-Authored-By: Claude Sonnet 5 --- imotionsApi/R/imotionsApi.R | 66 ++++++++++++++++--- .../tests/testthat/test-getTouchActors.R | 46 ++++++++++--- 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index 0673e09..ab9dfb9 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -1865,14 +1865,49 @@ getTouchActors <- function(study, stimulus) { } +#' Get the AOI definitions of every camera that supports contact, for a stimulus. +#' +#' Sibling of \code{\link{privateAoiFiltering}} for touch actors: that one only ever reaches the Stimulus/Scene +#' camera, while a touch actor's interactive AOIs can live on any camera contact detection supports (e.g. +#' Environment). Used by \code{\link{getTouchActorAois}} to resolve a name/type/group/area for every touch actor AOI, +#' not just the ones on Scene. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' +#' @return A data.table with one row per AOI (id, name, type, group, area, mediaSourceType) across every touch-capable +#' camera, or NULL if none are defined. +#' @keywords internal +privateGetTouchActorAoiDefinitions <- function(study, stimulus) { + endpoint <- paste0("Stimulus: ", stimulus$name) + + if (!study$connection$localIM) { + warning(paste("Contact AOI definitions are only available for local studies, none retrieved for", endpoint)) + return(NULL) + } + + aois <- getJSON(study$connection, getTouchActorAoisUrl(study, stimulus$id), + message = paste("Retrieving contact AOI definitions for", endpoint)) + + if (length(aois) == 0 || nrow(aois) == 0) { + return(NULL) + } + + setDT(aois) + # Renamed by name rather than position: unlike privateAoiFormatting's positional AOIs$aois unnest, this endpoint + # returns a flat, already-scoped-to-one-stimulus list with no nested column to unnest. + setnames(aois, "aoiType", "type") + return(aois) +} + + #' Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data. #' #' Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This #' returns one row per pair, plus the touch actor that produced it and the path to the contact in/out signal, so it -#' can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area) when -#' one is available - which today is only for a touch actor on the Stimulus/Scene camera, since that is the only -#' camera \code{\link{getAois}} can see. A touch actor on any other media source (e.g. Environment) still gets its -#' row, with those four columns NA - contact and metrics are unaffected, only their display labelling is. +#' can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area), +#' resolved from whichever camera the AOI is actually defined on (see \code{\link{privateGetTouchActorAoiDefinitions}} +#' ), so a touch actor on a non-Scene camera (e.g. Environment) is labelled the same as one on Scene. #' #' Requesting this triggers generation of any in/out signals that are missing or older than the contact detection #' result they derive from, which is why a respondent is required. @@ -1959,11 +1994,10 @@ getTouchActorAois <- function(study, imObject, respondent) { return(NULL) } - # AOI definitions only reach the Stimulus/Scene camera, so a non-Scene touch actor gets NA name/type/group/area - # instead of being dropped (metrics/upload only need id/fileId/resultId, set above). suppressWarnings() is kept - # here because privateAoiFiltering() warns unconditionally when a stimulus has no gaze AOI at all - the normal - # case for a touch-actor-only stimulus. - aois <- suppressWarnings(privateAoiFiltering(study, stimulus)) + # Fetched across every touch-capable camera (not just Stimulus/Scene, unlike privateAoiFiltering), so a + # non-Scene touch actor's AOI resolves to its real name/type/group/area instead of NA. AOI ids are unique per + # camera's own model, so joining on id alone (without also matching mediaSourceType) is safe. + aois <- privateGetTouchActorAoiDefinitions(study, stimulus) if (is.null(aois)) { touchAois[, c("name", "type", "group", "area") := list(NA_character_, NA_character_, NA_character_, @@ -3346,6 +3380,20 @@ getTouchActorsUrl <- function(study, stimulusId) { } +#' Return the path/url to the AOI definitions of every camera that supports contact, for a specific stimulus. +#' +#' Unlike \code{\link{getAoisUrl}}, which only ever reaches the Stimulus/Scene camera, this reports one row per AOI +#' across every touch-capable camera (e.g. Environment), tagged with mediaSourceType. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulusId The id of the stimulus of interest. +#' +#' @keywords internal +getTouchActorAoisUrl <- function(study, stimulusId) { + file.path(getTouchActorsUrl(study, stimulusId), "aois") +} + + #' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imStimulus object #' and a respondent object. #' diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index 4ffece0..6026684 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -22,7 +22,8 @@ touchActorDetailsPath <- "../data/touchActorDetails.json" touchActorDetailsMissingPath <- "../data/touchActorDetails_missingfileId.json" touchActorDetailsNoMatchPath <- "../data/touchActorDetails_noMatchingPair.json" -# The AOI definitions getTouchActorAois() joins against - what getAois() would return for this stimulus. +# The AOI definitions getTouchActorAois() joins against - what privateGetTouchActorAoiDefinitions() would return for +# this stimulus. aoiDefinitions <- function() { aois <- data.table(stimulusId = "1002", stimulusName = "IAAF", id = c(AOI1, AOI2), name = c("New Aoi", "Second Aoi"), type = "Static", group = NA_character_, @@ -172,7 +173,7 @@ mockedGetTouchActorAois <- function(study, imObject, respondent, detailsPath = t touchAois <- mockr::with_mock( getTouchActors = function(...) touchActors, - privateAoiFiltering = function(...) aoiDefinitions(), + privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), privateGetTouchActorDetails = function(...) jsonlite::fromJSON(detailsPath), { getTouchActorAois(study, imObject, respondent) } @@ -253,15 +254,23 @@ test_that("local return - filtering on a single touch actor", { expect_identical(touchAois$touchActorId, TA2, "wrong touch actor kept") }) -test_that("local return - a touch actor on a media source getAois() cannot see keeps its row, AOI columns NA", { +test_that("local return - a touch actor on a non-Scene media source resolves its AOI name too", { TA_ENV <- "4f2d6b30-7c44-4d1b-9c19-9c6b9e2a5b60" AOI_ENV <- "1c9c8b18-3e1d-4b53-9c62-2a6b1a0d7e11" touchActorsMulti <- mockedGetTouchActors(study, stimulus, "../data/touchActorsMultiSource.json") + # privateGetTouchActorAoiDefinitions() reaches every touch-capable camera (unlike privateAoiFiltering(), which is + # Scene-only), so the mock here carries the Environment AOI's own definition alongside the Scene ones. + aoiDefinitionsMultiSource <- function() { + return(rbind(aoiDefinitions(), data.table(stimulusId = "1002", stimulusName = "IAAF", id = AOI_ENV, + name = "Env Aoi", type = "Static", group = NA_character_, + area = 4000))) + } + touchAois <- mockr::with_mock( getTouchActors = function(...) touchActorsMulti, - privateAoiFiltering = function(...) aoiDefinitions(), + privateGetTouchActorAoiDefinitions = function(...) aoiDefinitionsMultiSource(), privateGetTouchActorDetails = function(...) jsonlite::fromJSON("../data/touchActorDetailsMultiSource.json"), { getTouchActorAois(study, stimulus, respondent) } @@ -274,18 +283,35 @@ test_that("local return - a touch actor on a media source getAois() cannot see k envRow <- touchAois[touchAois$touchActorId == TA_ENV, ] expect_identical(sceneRow$id, AOI1, "wrong AOI kept for the Scene touch actor") - expect_identical(sceneRow$name, "New Aoi", info = "the Scene AOI is still enriched from getAois() as before") + expect_identical(sceneRow$name, "New Aoi", info = "the Scene AOI is still resolved as before") - expect_identical(envRow$id, AOI_ENV, info = "the AOI id itself comes from the touch actor side, never dropped") - expect_true(is.na(envRow$name), info = "an AOI on a camera getAois() can't see gets NA, not a dropped row") - expect_true(is.na(envRow$type), info = "type should be NA for the same reason") - expect_true(is.na(envRow$area), info = "area should be NA for the same reason") + expect_identical(envRow$id, AOI_ENV, info = "the AOI id itself comes from the touch actor side") + expect_identical(envRow$name, "Env Aoi", info = "an AOI on a non-Scene camera now resolves its real name too") + expect_identical(envRow$type, "Static", info = "type should resolve the same way") + expect_equal(envRow$area, 4000, info = "area should resolve the same way") expect_false(is.na(envRow$fileId), info = "the contact in/out file should still be resolved for this row") expect_identical(envRow$stimulusId, "1002", - info = "stimulusId should come from the touch actor, not the (Scene-only) AOI join") + info = "stimulusId should come from the touch actor, not the AOI join") expect_identical(envRow$mediaSourceType, "Environment", "wrong media source kept for the environment actor") }) +test_that("local return - an AOI genuinely absent from every camera's definitions keeps its row, columns NA", { + touchActors <- suppressWarnings(mockedGetTouchActors(study, stimulus)) + + touchAois <- mockr::with_mock( + getTouchActors = function(...) touchActors, + privateGetTouchActorAoiDefinitions = function(...) NULL, + privateGetTouchActorDetails = function(...) jsonlite::fromJSON(touchActorDetailsPath), { + getTouchActorAois(study, stimulus, respondent) + } + ) + + expect_true(all(is.na(touchAois$name)), info = "no AOI definitions available should leave every name NA") + expect_true(all(is.na(touchAois$type)), info = "no AOI definitions available should leave every type NA") + expect_true(all(is.na(touchAois$area)), info = "no AOI definitions available should leave every area NA") + expect_false(any(is.na(touchAois$fileId)), info = "contact in/out resolution is unaffected") +}) + test_that("warning - contact in/out signals found do not match any touch actor pair", { expect_warning( touchAois <- mockedGetTouchActorAois(study, stimulus, respondent, From 5b22c66a0d322083c7dde2e829c3bc92a1a17f19 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Tue, 25 Aug 2026 13:26:50 +0200 Subject: [PATCH 07/12] Make respondent optional throughout the touch actor contact-details chain getTouchActorAois() previously required a respondent up front, unlike getAois() and friends, which resolve respondents via the API instead. This mirrors that pattern: respondent is now optional across getTouchActorAois(), privateGetTouchActorDetails(), and every getTouchActorDetailsUrl.* method, so callers can list touch actor AOI definitions first and use getRespondents(study, AOI = touchAoi) to discover who has contact data for a given (touch actor, AOI) pair - resolving the circular dependency where getting a touchAoi previously needed an already-known respondent. Also addresses the remaining PR #37 review comments: - getTouchActorAois() reuses an imTouchActor argument directly instead of re-fetching and filtering every touch actor on the stimulus. - privateGetTouchActorDetails() is now called with the actor-scoped imObject rather than the whole stimulus, so contact detection only runs for the requested touch actor instead of every one on it - via a new getTouchActorDetailsUrl.imTouchActor method. --- imotionsApi/NAMESPACE | 1 + imotionsApi/R/imotionsApi.R | 179 +++++++++++------- imotionsApi/man/getTouchActorAois.Rd | 35 ++-- imotionsApi/man/getTouchActorDetailsUrl.Rd | 12 +- .../man/getTouchActorDetailsUrl.imStimulus.Rd | 5 +- .../man/getTouchActorDetailsUrl.imTouchAOI.Rd | 5 +- .../getTouchActorDetailsUrl.imTouchActor.Rd | 24 +++ .../man/privateGetTouchActorDetails.Rd | 14 +- .../privateRespondentFiltering.imTouchAOI.Rd | 8 +- .../touchActorDetailsMultiRespondent.json | 26 +++ .../tests/testthat/test-getTouchActors.R | 88 +++++++-- 11 files changed, 290 insertions(+), 107 deletions(-) create mode 100644 imotionsApi/man/getTouchActorDetailsUrl.imTouchActor.Rd create mode 100644 imotionsApi/tests/data/touchActorDetailsMultiRespondent.json diff --git a/imotionsApi/NAMESPACE b/imotionsApi/NAMESPACE index e4b2564..39cd467 100644 --- a/imotionsApi/NAMESPACE +++ b/imotionsApi/NAMESPACE @@ -8,6 +8,7 @@ S3method(getSensorsUrl,imRespondent) S3method(getSensorsUrl,imSegment) S3method(getTouchActorDetailsUrl,imStimulus) S3method(getTouchActorDetailsUrl,imTouchAOI) +S3method(getTouchActorDetailsUrl,imTouchActor) S3method(getUploadAoiMetricsUrl,imSegment) S3method(getUploadEventsUrl,imRespondent) S3method(getUploadMetricsUrl,imRespondent) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index ab9dfb9..7de6fc7 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -883,10 +883,10 @@ privateRespondentFiltering.imAOI <- function(study, obj) { #' because \code{\link{privateRespondentFiltering.imAOI}} resolves respondents through the gaze in/out endpoint, which #' returns nothing on a study without eyetracking data - exactly the case contact metrics exist to support. #' -#' Unlike the gaze equivalent, the contact endpoint has no "all respondents" wildcard for a single touch actor AOI -#' (see \code{\link{getTouchActorDetailsUrl.imTouchAOI}}), so this is resolved one respondent at a time: every -#' respondent exposed to the AOI's stimulus is queried (via the stimulus-wide wildcard, one call each) and kept only -#' if its own contact details contain a matching (touchActorId, aoiId) pair. +#' Resolved with a single stimulus-wide, respondent-less call to \code{\link{privateGetTouchActorDetails}} (see +#' \code{\link{getTouchActorDetailsUrl.imStimulus}}), which returns contact details for every respondent exposed to +#' the stimulus in one response - kept are only the respondents whose own contact details contain a matching +#' (touchActorId, aoiId) pair. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. #' @param obj An imTouchAOI object as returned from \code{\link{getTouchActorAois}} for which you would like to get @@ -899,17 +899,14 @@ privateRespondentFiltering.imTouchAOI <- function(study, obj) { stimulus <- getStimulus(study, obj$stimulusId) respondents <- privateRespondentFiltering.imStimulus(study, stimulus) - hasContactData <- vapply(seq_len(nrow(respondents)), function(idx) { - details <- suppressWarnings(privateGetTouchActorDetails(study, stimulus, respondents[idx, ])) + details <- suppressWarnings(privateGetTouchActorDetails(study, stimulus)) - if (is.null(details) || nrow(details) == 0) { - return(FALSE) - } - - return(any(details$touchActorId == obj$touchActorId & details$aoiId == obj$id)) - }, logical(1)) + if (is.null(details) || nrow(details) == 0) { + return(respondents[0, ]) + } - return(respondents[hasContactData, ]) + matchingRespIds <- details[details$touchActorId == obj$touchActorId & details$aoiId == obj$id, ]$respId + return(respondents[respondents$id %in% matchingRespIds, ]) } @@ -1901,22 +1898,25 @@ privateGetTouchActorAoiDefinitions <- function(study, stimulus) { } -#' Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data. +#' Get the interactive AOIs of a stimulus's touch actors, optionally paired with their contact in/out data. #' #' Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This -#' returns one row per pair, plus the touch actor that produced it and the path to the contact in/out signal, so it -#' can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area), -#' resolved from whichever camera the AOI is actually defined on (see \code{\link{privateGetTouchActorAoiDefinitions}} -#' ), so a touch actor on a non-Scene camera (e.g. Environment) is labelled the same as one on Scene. +#' returns one row per pair, plus the touch actor that produced it, so it can be used anywhere an imAOI is expected. +#' It also carries the AOI's own definition (name, type, group, area), resolved from whichever camera the AOI is +#' actually defined on (see \code{\link{privateGetTouchActorAoiDefinitions}}), so a touch actor on a non-Scene camera +#' (e.g. Environment) is labelled the same as one on Scene. #' -#' Requesting this triggers generation of any in/out signals that are missing or older than the contact detection -#' result they derive from, which is why a respondent is required. +#' Providing a respondent additionally attaches that respondent's contact in/out fileId/resultId to each row, +#' triggering generation of any signal that is missing or older than the contact detection result it derives from. +#' Without one, only the AOI/touch actor definitions are returned - use \code{\link{getRespondents}} (e.g. +#' \code{getRespondents(study, AOI = touchAoi)}) to find which respondents have contact data for a given row. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. #' @param imObject An imStimulus object as returned from \code{\link{getStimuli}} to return every touch actor's AOIs #' on it, or an imTouchActor object as returned from \code{\link{getTouchActors}} to return only that #' actor's AOIs. -#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}} to attach that +#' respondent's contact in/out fileId/resultId to each row. #' #' @return An imTouchAOIList object (data.table, a subclass of imAOIList so shared AOI functions still accept it) #' with one row per (touch actor, AOI) combination, or NULL if none exist. A single-row result is an @@ -1928,39 +1928,39 @@ privateGetTouchActorAoiDefinitions <- function(study, stimulus) { #' studies <- imotionsApi::listStudies(connection) #' study <- imotionsApi::imStudy(connection, studies$id[1]) #' stimulus <- imotionsApi::getStimuli(study)[1, ] -#' respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] -#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) +#' +#' ## List the touch actor AOIs defined for a stimulus, without triggering signal generation +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus) +#' +#' ## Get the respondents that have contact data for one of them +#' respondents <- imotionsApi::getRespondents(study, AOI = touchAois[1, ]) +#' +#' ## Attach the contact in/out file for a specific respondent +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondents[1, ]) #' #' touchActor <- imotionsApi::getTouchActors(study, stimulus)[1, ] -#' touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondent) # only that actor's AOIs +#' touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondents[1, ]) # only that actor's AOIs #' #' print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair #' } -getTouchActorAois <- function(study, imObject, respondent) { +getTouchActorAois <- function(study, imObject, respondent = NULL) { assertValid(hasArg(imObject), "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`") - assertValid(hasArg(respondent), "Please specify a respondent loaded with `getRespondents()`") assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") if (inherits(imObject, "imTouchActor")) { - # The touch actor already carries its parent stimulus id, so that alone can drive the AOI lookup below - - # `touchActor` is kept aside only to filter the pairs down to this one actor further down. - touchActor <- imObject + # Already a single touch actor row (e.g. from getTouchActors()) - reuse it directly rather than fetching + # every touch actor on the stimulus again just to filter back down to this one. + touchActors <- imObject stimulus <- getStimulus(study, imObject$stimulusId) } else { assertClass(imObject, "imStimulus", "`imObject` argument is not an imStimulus or imTouchActor object") - touchActor <- NULL stimulus <- imObject - } - - touchActors <- getTouchActors(study, stimulus) - - if (is.null(touchActors)) { - return(NULL) - } + touchActors <- getTouchActors(study, stimulus) - if (!is.null(touchActor)) { - touchActors <- touchActors[touchActors$id %in% touchActor$id, ] + if (is.null(touchActors)) { + return(NULL) + } } # One row per (touch actor, AOI): interactiveAoiIds is a list column holding each actor's own AOI ids. @@ -1979,19 +1979,26 @@ getTouchActorAois <- function(study, imObject, respondent) { return(NULL) } - details <- privateGetTouchActorDetails(study, stimulus, respondent) + if (is.null(respondent)) { + touchAois <- pairs + } else { + # imObject is never reassigned above, so it still carries whichever class the caller passed in + # (imTouchActor or imStimulus) - passing it straight through lets dispatch scope the fetch to just that + # actor when one was requested, rather than triggering generation for every touch actor on the stimulus. + details <- privateGetTouchActorDetails(study, imObject, respondent) - if (is.null(details) || nrow(details) == 0) { - return(NULL) - } + if (is.null(details) || nrow(details) == 0) { + return(NULL) + } - touchAois <- merge(pairs, details[, c("touchActorId", "aoiId", "fileId", "resultId")], - by = c("touchActorId", "aoiId")) + touchAois <- merge(pairs, details[, c("touchActorId", "aoiId", "fileId", "resultId")], + by = c("touchActorId", "aoiId")) - if (nrow(touchAois) == 0) { - warning("The contact in/out signals found do not match any touch actor AOI for this respondent/stimulus ", - "combination.") - return(NULL) + if (nrow(touchAois) == 0) { + warning("The contact in/out signals found do not match any touch actor AOI for this respondent/stimulus ", + "combination.") + return(NULL) + } } # Fetched across every touch-capable camera (not just Stimulus/Scene, unlike privateAoiFiltering), so a @@ -2154,20 +2161,27 @@ getAoiRespondentTouchMetrics <- function(study, touchAoi, respondent) { } -#' Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live for a respondent. +#' Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live. #' #' Requesting these generates any signal that is missing or older than the contact detection result it derives from, #' so this is also what makes the files exist. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. -#' @param imObject An imStimulus object (all touch actors on it) or one row of \code{\link{getTouchActorAois}}. -#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' @param imObject An imStimulus object (all touch actors on it), an imTouchActor object as returned from +#' \code{\link{getTouchActors}} (that actor's AOIs only), or one row of \code{\link{getTouchActorAois}} +#' (that specific (touch actor, AOI) pair only). +#' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +#' details for every respondent exposed to the stimulus are returned in a single response, +#' disambiguated by the `respId` column. #' -#' @return A data.frame with one row per (touch actor, AOI) combination that has an in/out signal. +#' @return A data.frame with one row per (touch actor, AOI[, respondent]) combination that has an in/out signal. #' @keywords internal -privateGetTouchActorDetails <- function(study, imObject, respondent) { - endpoint <- paste0(gsub("^im|List", "", class(imObject)[1]), ": ", imObject$name, ", Respondent: ", - respondent$name) +privateGetTouchActorDetails <- function(study, imObject, respondent = NULL) { + endpoint <- paste0(gsub("^im|List", "", class(imObject)[1]), ": ", imObject$name) + + if (!is.null(respondent)) { + endpoint <- paste0(endpoint, ", Respondent: ", respondent$name) + } if (!study$connection$localIM) { warning(paste("Contact data is only available for local studies, none retrieved for", endpoint)) @@ -3394,22 +3408,47 @@ getTouchActorAoisUrl <- function(study, stimulusId) { } -#' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imStimulus object -#' and a respondent object. +#' Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imTouchActor/ +#' imStimulus object and, optionally, a respondent object. #' #' Return the path/url to the contact in/out details for one touch actor, or for every touch actor on a stimulus. #' Contact detection is desktop-only, so this is only ever used for a local study. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. -#' @param imObject An imStimulus object, or one row of \code{\link{getTouchActorAois}}. -#' @param respondent An imRespondent object as returned from \code{\link{getRespondents}}. +#' @param imObject An imStimulus object, an imTouchActor object as returned from \code{\link{getTouchActors}}, or one +#' row of \code{\link{getTouchActorAois}}. +#' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +#' the url targets every respondent exposed to the stimulus in a single response. #' #' @keywords internal -getTouchActorDetailsUrl <- function(study, imObject, respondent) { +getTouchActorDetailsUrl <- function(study, imObject, respondent = NULL) { UseMethod("getTouchActorDetailsUrl", object = imObject) } +#' getTouchActorDetailsUrl.imTouchActor method to return the path/url to one touch actor's contact in/out details, +#' across every AOI it marks interactive. +#' +#' Produces the same url as \code{\link{getTouchActorDetailsUrl.imTouchAOI}} for the same actor - the endpoint is +#' scoped per touch actor either way, so which of the two dispatches only depends on whether the caller already +#' narrowed down to one (touch actor, AOI) pair or still has the bare touch actor. +#' +#' @inheritParams getTouchActorDetailsUrl +#' +#' @keywords internal +#' @exportS3Method getTouchActorDetailsUrl imTouchActor +getTouchActorDetailsUrl.imTouchActor <- function(study, imObject, respondent = NULL) { + url <- getTouchActorsUrl(study, imObject$stimulusId) + + if (!is.null(respondent)) { + url <- file.path(url, "respondent", respondent$id) + } + + url <- file.path(url, imObject$id) + return(url) +} + + #' getTouchActorDetailsUrl.imTouchAOI method to return the path/url to one touch actor's contact in/out details. #' #' Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports @@ -3420,9 +3459,14 @@ getTouchActorDetailsUrl <- function(study, imObject, respondent) { #' #' @keywords internal #' @exportS3Method getTouchActorDetailsUrl imTouchAOI -getTouchActorDetailsUrl.imTouchAOI <- function(study, imObject, respondent) { +getTouchActorDetailsUrl.imTouchAOI <- function(study, imObject, respondent = NULL) { url <- getTouchActorsUrl(study, imObject$stimulusId) - url <- file.path(url, "respondent", respondent$id, imObject$touchActorId) + + if (!is.null(respondent)) { + url <- file.path(url, "respondent", respondent$id) + } + + url <- file.path(url, imObject$touchActorId) return(url) } @@ -3434,9 +3478,14 @@ getTouchActorDetailsUrl.imTouchAOI <- function(study, imObject, respondent) { #' #' @keywords internal #' @exportS3Method getTouchActorDetailsUrl imStimulus -getTouchActorDetailsUrl.imStimulus <- function(study, imObject, respondent) { +getTouchActorDetailsUrl.imStimulus <- function(study, imObject, respondent = NULL) { url <- getTouchActorsUrl(study, imObject$id) - url <- file.path(url, "respondent", respondent$id, "*") + + if (!is.null(respondent)) { + url <- file.path(url, "respondent", respondent$id) + } + + url <- file.path(url, "*") return(url) } diff --git a/imotionsApi/man/getTouchActorAois.Rd b/imotionsApi/man/getTouchActorAois.Rd index 5e3bb36..af249ad 100644 --- a/imotionsApi/man/getTouchActorAois.Rd +++ b/imotionsApi/man/getTouchActorAois.Rd @@ -2,9 +2,9 @@ % Please edit documentation in R/imotionsApi.R \name{getTouchActorAois} \alias{getTouchActorAois} -\title{Get the interactive AOIs of a stimulus's touch actors, paired with their contact in/out data.} +\title{Get the interactive AOIs of a stimulus's touch actors, optionally paired with their contact in/out data.} \usage{ -getTouchActorAois(study, imObject, respondent) +getTouchActorAois(study, imObject, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} @@ -13,7 +13,8 @@ getTouchActorAois(study, imObject, respondent) on it, or an imTouchActor object as returned from \code{\link{getTouchActors}} to return only that actor's AOIs.} -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}} to attach that +respondent's contact in/out fileId/resultId to each row.} } \value{ An imTouchAOIList object (data.table, a subclass of imAOIList so shared AOI functions still accept it) @@ -22,15 +23,16 @@ An imTouchAOIList object (data.table, a subclass of imAOIList so shared AOI func } \description{ Each touch actor marks one or more AOIs as interactive, and contact is recorded per (touch actor, AOI) pair. This -returns one row per pair, plus the touch actor that produced it and the path to the contact in/out signal, so it -can be used anywhere an imAOI is expected. It also carries the AOI's own definition (name, type, group, area) when -one is available - which today is only for a touch actor on the Stimulus/Scene camera, since that is the only -camera \code{\link{getAois}} can see. A touch actor on any other media source (e.g. Environment) still gets its -row, with those four columns NA - contact and metrics are unaffected, only their display labelling is. +returns one row per pair, plus the touch actor that produced it, so it can be used anywhere an imAOI is expected. +It also carries the AOI's own definition (name, type, group, area), resolved from whichever camera the AOI is +actually defined on (see \code{\link{privateGetTouchActorAoiDefinitions}}), so a touch actor on a non-Scene camera +(e.g. Environment) is labelled the same as one on Scene. } \details{ -Requesting this triggers generation of any in/out signals that are missing or older than the contact detection -result they derive from, which is why a respondent is required. +Providing a respondent additionally attaches that respondent's contact in/out fileId/resultId to each row, +triggering generation of any signal that is missing or older than the contact detection result it derives from. +Without one, only the AOI/touch actor definitions are returned - use \code{\link{getRespondents}} (e.g. +\code{getRespondents(study, AOI = touchAoi)}) to find which respondents have contact data for a given row. } \examples{ \dontrun{ @@ -38,11 +40,18 @@ connection <- imotionsApi::imConnection("xxxxxxxx") studies <- imotionsApi::listStudies(connection) study <- imotionsApi::imStudy(connection, studies$id[1]) stimulus <- imotionsApi::getStimuli(study)[1, ] -respondent <- imotionsApi::getRespondents(study, stimulus = stimulus)[1, ] -touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondent) + +## List the touch actor AOIs defined for a stimulus, without triggering signal generation +touchAois <- imotionsApi::getTouchActorAois(study, stimulus) + +## Get the respondents that have contact data for one of them +respondents <- imotionsApi::getRespondents(study, AOI = touchAois[1, ]) + +## Attach the contact in/out file for a specific respondent +touchAois <- imotionsApi::getTouchActorAois(study, stimulus, respondents[1, ]) touchActor <- imotionsApi::getTouchActors(study, stimulus)[1, ] -touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondent) # only that actor's AOIs +touchAois <- imotionsApi::getTouchActorAois(study, touchActor, respondents[1, ]) # only that actor's AOIs print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair } diff --git a/imotionsApi/man/getTouchActorDetailsUrl.Rd b/imotionsApi/man/getTouchActorDetailsUrl.Rd index 5917342..c4d43ec 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.Rd @@ -2,17 +2,19 @@ % Please edit documentation in R/imotionsApi.R \name{getTouchActorDetailsUrl} \alias{getTouchActorDetailsUrl} -\title{Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imStimulus object -and a respondent object.} +\title{Generic getTouchActorDetailsUrl function that takes as parameter a study object, an imTouchAOI/imTouchActor/ +imStimulus object and, optionally, a respondent object.} \usage{ -getTouchActorDetailsUrl(study, imObject, respondent) +getTouchActorDetailsUrl(study, imObject, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} +\item{imObject}{An imStimulus object, an imTouchActor object as returned from \code{\link{getTouchActors}}, or one +row of \code{\link{getTouchActorAois}}.} -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +the url targets every respondent exposed to the stimulus in a single response.} } \description{ Return the path/url to the contact in/out details for one touch actor, or for every touch actor on a stimulus. diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd index 904e581..19ac6ba 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd @@ -5,14 +5,15 @@ \title{getTouchActorDetailsUrl.imStimulus method to return the path/url to the contact in/out details of every touch actor defined for a stimulus.} \usage{ -\method{getTouchActorDetailsUrl}{imStimulus}(study, imObject, respondent) +\method{getTouchActorDetailsUrl}{imStimulus}(study, imObject, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} \item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +the url targets every respondent exposed to the stimulus in a single response.} } \description{ getTouchActorDetailsUrl.imStimulus method to return the path/url to the contact in/out details of every touch actor diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd index 35caf86..7aa5317 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd @@ -4,14 +4,15 @@ \alias{getTouchActorDetailsUrl.imTouchAOI} \title{getTouchActorDetailsUrl.imTouchAOI method to return the path/url to one touch actor's contact in/out details.} \usage{ -\method{getTouchActorDetailsUrl}{imTouchAOI}(study, imObject, respondent) +\method{getTouchActorDetailsUrl}{imTouchAOI}(study, imObject, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} \item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +the url targets every respondent exposed to the stimulus in a single response.} } \description{ Unlike the gaze equivalent the wildcard sits on the touch actor rather than the AOI, because the endpoint reports diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imTouchActor.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imTouchActor.Rd new file mode 100644 index 0000000..8909980 --- /dev/null +++ b/imotionsApi/man/getTouchActorDetailsUrl.imTouchActor.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorDetailsUrl.imTouchActor} +\alias{getTouchActorDetailsUrl.imTouchActor} +\title{getTouchActorDetailsUrl.imTouchActor method to return the path/url to one touch actor's contact in/out details, +across every AOI it marks interactive.} +\usage{ +\method{getTouchActorDetailsUrl}{imTouchActor}(study, imObject, respondent = NULL) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{imObject}{An imStimulus object, an imTouchActor object as returned from \code{\link{getTouchActors}}, or one +row of \code{\link{getTouchActorAois}}.} + +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +the url targets every respondent exposed to the stimulus in a single response.} +} +\description{ +Produces the same url as \code{\link{getTouchActorDetailsUrl.imTouchAOI}} for the same actor - the endpoint is +scoped per touch actor either way, so which of the two dispatches only depends on whether the caller already +narrowed down to one (touch actor, AOI) pair or still has the bare touch actor. +} +\keyword{internal} diff --git a/imotionsApi/man/privateGetTouchActorDetails.Rd b/imotionsApi/man/privateGetTouchActorDetails.Rd index 0e4a7b3..b27b680 100644 --- a/imotionsApi/man/privateGetTouchActorDetails.Rd +++ b/imotionsApi/man/privateGetTouchActorDetails.Rd @@ -2,19 +2,23 @@ % Please edit documentation in R/imotionsApi.R \name{privateGetTouchActorDetails} \alias{privateGetTouchActorDetails} -\title{Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live for a respondent.} +\title{Private function returning where a stimulus's or a touch actor AOI's contact in/out signals live.} \usage{ -privateGetTouchActorDetails(study, imObject, respondent) +privateGetTouchActorDetails(study, imObject, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{imObject}{An imStimulus object (all touch actors on it) or one row of \code{\link{getTouchActorAois}}.} +\item{imObject}{An imStimulus object (all touch actors on it), an imTouchActor object as returned from +\code{\link{getTouchActors}} (that actor's AOIs only), or one row of \code{\link{getTouchActorAois}} +(that specific (touch actor, AOI) pair only).} -\item{respondent}{An imRespondent object as returned from \code{\link{getRespondents}}.} +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, +details for every respondent exposed to the stimulus are returned in a single response, +disambiguated by the `respId` column.} } \value{ -A data.frame with one row per (touch actor, AOI) combination that has an in/out signal. +A data.frame with one row per (touch actor, AOI[, respondent]) combination that has an in/out signal. } \description{ Requesting these generates any signal that is missing or older than the contact detection result it derives from, diff --git a/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd b/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd index 5810e26..50fd553 100644 --- a/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd +++ b/imotionsApi/man/privateRespondentFiltering.imTouchAOI.Rd @@ -21,9 +21,9 @@ because \code{\link{privateRespondentFiltering.imAOI}} resolves respondents thro returns nothing on a study without eyetracking data - exactly the case contact metrics exist to support. } \details{ -Unlike the gaze equivalent, the contact endpoint has no "all respondents" wildcard for a single touch actor AOI -(see \code{\link{getTouchActorDetailsUrl.imTouchAOI}}), so this is resolved one respondent at a time: every -respondent exposed to the AOI's stimulus is queried (via the stimulus-wide wildcard, one call each) and kept only -if its own contact details contain a matching (touchActorId, aoiId) pair. +Resolved with a single stimulus-wide, respondent-less call to \code{\link{privateGetTouchActorDetails}} (see +\code{\link{getTouchActorDetailsUrl.imStimulus}}), which returns contact details for every respondent exposed to +the stimulus in one response - kept are only the respondents whose own contact details contain a matching +(touchActorId, aoiId) pair. } \keyword{internal} diff --git a/imotionsApi/tests/data/touchActorDetailsMultiRespondent.json b/imotionsApi/tests/data/touchActorDetailsMultiRespondent.json new file mode 100644 index 0000000..e66291c --- /dev/null +++ b/imotionsApi/tests/data/touchActorDetailsMultiRespondent.json @@ -0,0 +1,26 @@ +[ + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "09bd22e6-29b6-4a8a-8cc1-4780a5163e63", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": "../data/AOImetrics.csv", + "fileIdIsEmptyPlaceHolder": false + }, + { + "touchActorId": "5b1f0c42-9d6e-4a3b-8f21-0c7d5e9a1b34", + "aoiId": "09a234fc-00ad-4257-b7e1-da5754986c9d", + "respId": "750ed075-1c8d-4aff-91b1-ed6c9e052808", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + }, + { + "touchActorId": "c8e4a17d-2f60-4b95-a3d8-6e1b70f2c945", + "aoiId": "7d3b81e5-4c92-4f07-b6a1-52e8d90c3af6", + "respId": "846041b3-1485-4e56-9d73-829601dcfe20", + "fileId": "../data/touchActorRespondentData.pbin", + "resultId": null, + "fileIdIsEmptyPlaceHolder": false + } +] diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index 6026684..eb11467 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -21,6 +21,7 @@ noTouchActorsPath <- "../data/noTouchActors.json" touchActorDetailsPath <- "../data/touchActorDetails.json" touchActorDetailsMissingPath <- "../data/touchActorDetails_missingfileId.json" touchActorDetailsNoMatchPath <- "../data/touchActorDetails_noMatchingPair.json" +touchActorDetailsMultiRespondentPath <- "../data/touchActorDetailsMultiRespondent.json" # The AOI definitions getTouchActorAois() joins against - what privateGetTouchActorAoiDefinitions() would return for # this stimulus. @@ -130,6 +131,16 @@ test_that("local return - details for every touch actor on a stimulus", { expect_identical(unique(details$respId), respondent$id, "details should all be for the requested respondent") }) +test_that("local return - respondent is optional, details for every respondent are returned in one call", { + details <- mockedGetTouchActorDetails(study, stimulus, respondent = NULL, + jsonPath = touchActorDetailsMultiRespondentPath) + + expect_equal(nrow(details), 3, info = "3 (touch actor, AOI, respondent) combinations should be returned") + expect_named(details, expectedDetailNames, info = "touch actor details infos not matching") + expect_setequal(details$respId, c("09bd22e6-29b6-4a8a-8cc1-4780a5163e63", "750ed075-1c8d-4aff-91b1-ed6c9e052808", + "846041b3-1485-4e56-9d73-829601dcfe20")) +}) + test_that("local return - combinations without a fileId are filtered out", { details <- mockedGetTouchActorDetails(study, stimulus, respondent, touchActorDetailsMissingPath) @@ -187,9 +198,6 @@ test_that("error - arguments are missing or not from the good class", { "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`", fixed = TRUE, info = "missing `imObject` param not handled properly") - expect_error(getTouchActorAois(study, stimulus), "Please specify a respondent loaded with `getRespondents()`", - fixed = TRUE, info = "missing `respondent` param not handled properly") - expect_error(getTouchActorAois(study, stimulus, respondent = "whatever"), "`respondent` argument is not an imRespondent object", info = "respondent not being an imRespondent object should throw an error") @@ -207,6 +215,15 @@ test_that("local return - one row per (touch actor, AOI) combination", { expect_equal(sum(touchAois$id == AOI2), 1, info = "AOI2 is referenced by one touch actor") }) +test_that("local return - without a respondent, only the AOI/touch actor definitions are returned", { + touchAois <- mockedGetTouchActorAois(study, stimulus, respondent = NULL) + + expect_equal(nrow(touchAois), 3, info = "3 (touch actor, AOI) combinations should still be returned") + expect_false("fileId" %in% names(touchAois), info = "no contact in/out details should be attached") + expect_false("resultId" %in% names(touchAois), info = "no contact in/out details should be attached") + expect_s3_class(touchAois, "imTouchAOIList") +}) + test_that("local return - the AOI definition wins the id/name columns so it can stand in for an imAOI", { touchAois <- mockedGetTouchActorAois(study, stimulus, respondent) @@ -254,6 +271,25 @@ test_that("local return - filtering on a single touch actor", { expect_identical(touchAois$touchActorId, TA2, "wrong touch actor kept") }) +test_that("local return - contact details are fetched scoped to the requested actor, not the whole stimulus", { + touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] + + touchAois <- mockr::with_mock( + getTouchActors = function(...) stop("getTouchActors() should not be called - imObject is already a touch actor"), + privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), + privateGetTouchActorDetails = function(study, imObject, respondent) { + expect_s3_class(imObject, "imTouchActor") + expect_identical(imObject$id, TA2, + "privateGetTouchActorDetails should be scoped to the requested touch actor") + jsonlite::fromJSON(touchActorDetailsPath) + }, { + getTouchActorAois(study, touchActor, respondent) + } + ) + + expect_equal(nrow(touchAois), 1, info = "only the second actor's single AOI should be returned") +}) + test_that("local return - a touch actor on a non-Scene media source resolves its AOI name too", { TA_ENV <- "4f2d6b30-7c44-4d1b-9c19-9c6b9e2a5b60" AOI_ENV <- "1c9c8b18-3e1d-4b53-9c62-2a6b1a0d7e11" @@ -437,19 +473,16 @@ touchAoiForRespondents <- function() { } test_that("local return - getRespondents() dispatches on imTouchAOI to use contact data, not gaze data", { - allRespondents <- getRespondents(study, stimulus = stimulus) - - # Only the first respondent of the stimulus has a matching (touchActorId, aoiId) contact pair. + # A single, respondent-less call returns contact details across every respondent exposed to the stimulus - + # only Wendy and Quilana have a matching (touchActorId, aoiId) pair here, Olana's is for a different pair. respondents <- mockr::with_mock( - privateGetTouchActorDetails = function(study, imObject, respondent) { - if (respondent$id == allRespondents$id[1]) jsonlite::fromJSON(touchActorDetailsPath) else NULL - }, { + privateGetTouchActorDetails = function(...) jsonlite::fromJSON(touchActorDetailsMultiRespondentPath), { getRespondents(study, AOI = touchAoiForRespondents()) } ) - expect_equal(nrow(respondents), 1, info = "only the respondent with a matching contact pair should be kept") - expect_identical(respondents$id, allRespondents$id[1], "wrong respondent kept") + expect_equal(nrow(respondents), 2, info = "both respondents with a matching contact pair should be kept") + expect_setequal(respondents$id, c("09bd22e6-29b6-4a8a-8cc1-4780a5163e63", "750ed075-1c8d-4aff-91b1-ed6c9e052808")) }) test_that("local return - a respondent with contact data for another (touch actor, AOI) pair is not kept", { @@ -499,6 +532,13 @@ test_that("url for every touch actor on a stimulus uses the wildcard form", { "wrong url for all touch actors") }) +test_that("url for every touch actor on a stimulus, without a respondent, omits the respondent segment", { + url <- imotionsApi:::getTouchActorDetailsUrl(study, stimulus) + + expect_identical(url, file.path("http://localhost:8086/touchactors", study$id, "stimuli", stimulus$id, "*"), + "wrong url for all touch actors, all respondents") +}) + test_that("url for a single touch actor uses its id - the wildcard sits on the actor, not the AOI", { touchAoi <- aoiDefinitions()[1, ] touchAoi$touchActorId <- TA1 @@ -510,3 +550,29 @@ test_that("url for a single touch actor uses its id - the wildcard sits on the a "respondent", respondent$id, TA1), "wrong url for a single touch actor") }) + +test_that("url for a single touch actor, without a respondent, omits the respondent segment", { + touchAoi <- aoiDefinitions()[1, ] + touchAoi$touchActorId <- TA1 + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) + + url <- imotionsApi:::getTouchActorDetailsUrl(study, touchAoi) + + expect_identical(url, file.path("http://localhost:8086/touchactors", study$id, "stimuli", "1002", TA1), + "wrong url for a single touch actor, all respondents") +}) + +test_that("url for a bare imTouchActor matches its imTouchAOI equivalent for the same actor", { + touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] + + urlWithRespondent <- imotionsApi:::getTouchActorDetailsUrl(study, touchActor, respondent) + urlAllRespondents <- imotionsApi:::getTouchActorDetailsUrl(study, touchActor) + + expect_identical(urlWithRespondent, file.path("http://localhost:8086/touchactors", study$id, "stimuli", "1002", + "respondent", respondent$id, TA2), + "wrong url for a bare touch actor, one respondent") + + expect_identical(urlAllRespondents, file.path("http://localhost:8086/touchactors", study$id, "stimuli", "1002", + TA2), + "wrong url for a bare touch actor, all respondents") +}) From 3c37eef65978b968da2c536566e3623b97927dc6 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Tue, 25 Aug 2026 13:38:28 +0200 Subject: [PATCH 08/12] fixed lint error --- imotionsApi/tests/testthat/test-getTouchActors.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index eb11467..29fd7c6 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -275,7 +275,9 @@ test_that("local return - contact details are fetched scoped to the requested ac touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] touchAois <- mockr::with_mock( - getTouchActors = function(...) stop("getTouchActors() should not be called - imObject is already a touch actor"), + getTouchActors = function(...) { + stop("getTouchActors() should not be called - imObject is already a touch actor") + }, privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), privateGetTouchActorDetails = function(study, imObject, respondent) { expect_s3_class(imObject, "imTouchActor") From af75d288697603546d9b8e6e8e3b0b595574ddf4 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Mon, 31 Aug 2026 11:27:58 +0200 Subject: [PATCH 09/12] Address review feedback from PR #37 - Scope privateGetTouchActorDetails() down to the requested (touch actor, AOI) pair when given an imTouchAOI, instead of returning every interactive AOI of that touch actor. - Make privateUploadAoiMetrics.imRespondent() dispatch explicitly to privateGetTouchActorDetails() for touch AOIs, rather than relying on incidental shape overlap with privateGetAoiDetails(). - Add the missing `study` argument validation to getTouchActorAois(). - Document imTouchAOI as an accepted imObject in privateGetTouchActorDetails()'s roxygen, matching the other two accepted classes, and mention it as an accepted AOI input in uploadAoiMetrics()/privateUploadAoiMetrics(). --- imotionsApi/R/imotionsApi.R | 28 +++++++++++++++---- .../man/privateGetTouchActorDetails.Rd | 4 +-- imotionsApi/man/privateUploadAoiMetrics.Rd | 3 +- .../privateUploadAoiMetrics.imRespondent.Rd | 3 +- .../man/privateUploadAoiMetrics.imSegment.Rd | 3 +- imotionsApi/man/uploadAOIMetrics.Rd | 3 +- .../tests/testthat/test-getTouchActors.R | 22 +++++++++++++++ .../tests/testthat/test-uploadAOIMetrics.R | 24 ++++++++++++++++ 8 files changed, 79 insertions(+), 11 deletions(-) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index 7de6fc7..d697060 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -1944,8 +1944,11 @@ privateGetTouchActorAoiDefinitions <- function(study, stimulus) { #' print(touchAois$fileId) # path to the contact in/out file for each (touch actor, AOI) pair #' } getTouchActorAois <- function(study, imObject, respondent = NULL) { + assertValid(hasArg(study), "Please specify a study loaded with `imStudy()`") assertValid(hasArg(imObject), "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`") + + assertClass(study, "imStudy", "`study` argument is not an imStudy object") assertClass(respondent, "imRespondent", "`respondent` argument is not an imRespondent object") if (inherits(imObject, "imTouchActor")) { @@ -2168,8 +2171,8 @@ getAoiRespondentTouchMetrics <- function(study, touchAoi, respondent) { #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. #' @param imObject An imStimulus object (all touch actors on it), an imTouchActor object as returned from -#' \code{\link{getTouchActors}} (that actor's AOIs only), or one row of \code{\link{getTouchActorAois}} -#' (that specific (touch actor, AOI) pair only). +#' \code{\link{getTouchActors}} (that actor's AOIs only), or an imTouchAOI object as returned from +#' \code{\link{getTouchActorAois}} (that specific (touch actor, AOI) pair only). #' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, #' details for every respondent exposed to the stimulus are returned in a single response, #' disambiguated by the `respId` column. @@ -2204,6 +2207,13 @@ privateGetTouchActorDetails <- function(study, imObject, respondent = NULL) { # Filtering out combinations without data if any - a null fileId means detection never ran for that touch actor, # as opposed to a 0-byte one, which means the AOI was simply never active. details <- details[!is.na(details$fileId), ] + + if (inherits(imObject, "imTouchAOI")) { + # Narrow back down to the single (touch actor, AOI) pair, + # so a multi-AOI touch actor doesn't leak its other AOIs' data. + details <- details[details$touchActorId == imObject$touchActorId & details$aoiId == imObject$id, ] + } + return(details) } @@ -2327,7 +2337,8 @@ uploadSensorData <- function(params, study, data, target, sensorName, scriptName #' Upload metrics for a specific respondent and AOI in a study. #' #' @param study An imStudy object as returned from imStudy() -#' @param AOI An imAOI object as returned from \code{\link{getAois}}. +#' @param AOI An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +#' \code{\link{getTouchActorAois}} to upload metrics for that specific touch actor AOI instead. #' @param target The target respondent/segment for the sensor (an imRespondent/imSegment object as returned from #' \code{\link{getRespondents}} or \code{\link{getSegments}}). #' @param metrics A data.table containing the metrics to upload. @@ -2374,7 +2385,8 @@ uploadAoiMetrics <- function(study, AOI, target, metrics) { #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. #' @param obj An imRespondent or imSegment object of interest. -#' @param AOI An imAOI object as returned from \code{\link{getAois}}. +#' @param AOI An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +#' \code{\link{getTouchActorAois}}. #' @param metrics A data.table containing the metrics to upload. #' #' @keywords internal @@ -2392,7 +2404,13 @@ privateUploadAoiMetrics <- function(study, obj, AOI, metrics) { #' @keywords internal #' @exportS3Method privateUploadAoiMetrics imRespondent privateUploadAoiMetrics.imRespondent <- function(study, obj, AOI, metrics) { - AOIDetails <- privateGetAoiDetails(study, AOI, obj) + # A touch AOI happens to carry enough of the same shape (fileId included) that privateGetAoiDetails() would + # "work" on it too, but only incidentally - dispatch explicitly so that overlap isn't relied upon. + AOIDetails <- if (inherits(AOI, "imTouchAOI")) { + privateGetTouchActorDetails(study, AOI, obj) + } else { + privateGetAoiDetails(study, AOI, obj) + } if (length(AOIDetails) == 0) { warning(paste("AOI", AOI$name, "was not found for respondent", obj$name)) diff --git a/imotionsApi/man/privateGetTouchActorDetails.Rd b/imotionsApi/man/privateGetTouchActorDetails.Rd index b27b680..5039239 100644 --- a/imotionsApi/man/privateGetTouchActorDetails.Rd +++ b/imotionsApi/man/privateGetTouchActorDetails.Rd @@ -10,8 +10,8 @@ privateGetTouchActorDetails(study, imObject, respondent = NULL) \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} \item{imObject}{An imStimulus object (all touch actors on it), an imTouchActor object as returned from -\code{\link{getTouchActors}} (that actor's AOIs only), or one row of \code{\link{getTouchActorAois}} -(that specific (touch actor, AOI) pair only).} +\code{\link{getTouchActors}} (that actor's AOIs only), or an imTouchAOI object as returned from +\code{\link{getTouchActorAois}} (that specific (touch actor, AOI) pair only).} \item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, details for every respondent exposed to the stimulus are returned in a single response, diff --git a/imotionsApi/man/privateUploadAoiMetrics.Rd b/imotionsApi/man/privateUploadAoiMetrics.Rd index 8c9a6a1..e547e28 100644 --- a/imotionsApi/man/privateUploadAoiMetrics.Rd +++ b/imotionsApi/man/privateUploadAoiMetrics.Rd @@ -12,7 +12,8 @@ privateUploadAoiMetrics(study, obj, AOI, metrics) \item{obj}{An imRespondent or imSegment object of interest.} -\item{AOI}{An imAOI object as returned from \code{\link{getAois}}.} +\item{AOI}{An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +\code{\link{getTouchActorAois}}.} \item{metrics}{A data.table containing the metrics to upload.} } diff --git a/imotionsApi/man/privateUploadAoiMetrics.imRespondent.Rd b/imotionsApi/man/privateUploadAoiMetrics.imRespondent.Rd index 00b17bd..d37c287 100644 --- a/imotionsApi/man/privateUploadAoiMetrics.imRespondent.Rd +++ b/imotionsApi/man/privateUploadAoiMetrics.imRespondent.Rd @@ -11,7 +11,8 @@ \item{obj}{An imRespondent or imSegment object of interest.} -\item{AOI}{An imAOI object as returned from \code{\link{getAois}}.} +\item{AOI}{An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +\code{\link{getTouchActorAois}}.} \item{metrics}{A data.table containing the metrics to upload.} } diff --git a/imotionsApi/man/privateUploadAoiMetrics.imSegment.Rd b/imotionsApi/man/privateUploadAoiMetrics.imSegment.Rd index 63f7ff2..2f8ca9d 100644 --- a/imotionsApi/man/privateUploadAoiMetrics.imSegment.Rd +++ b/imotionsApi/man/privateUploadAoiMetrics.imSegment.Rd @@ -11,7 +11,8 @@ \item{obj}{An imRespondent or imSegment object of interest.} -\item{AOI}{An imAOI object as returned from \code{\link{getAois}}.} +\item{AOI}{An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +\code{\link{getTouchActorAois}}.} \item{metrics}{A data.table containing the metrics to upload.} } diff --git a/imotionsApi/man/uploadAOIMetrics.Rd b/imotionsApi/man/uploadAOIMetrics.Rd index ba2ce2d..3140ccd 100644 --- a/imotionsApi/man/uploadAOIMetrics.Rd +++ b/imotionsApi/man/uploadAOIMetrics.Rd @@ -9,7 +9,8 @@ uploadAoiMetrics(study, AOI, target, metrics) \arguments{ \item{study}{An imStudy object as returned from imStudy()} -\item{AOI}{An imAOI object as returned from \code{\link{getAois}}.} +\item{AOI}{An imAOI object as returned from \code{\link{getAois}}, or an imTouchAOI object as returned from +\code{\link{getTouchActorAois}} to upload metrics for that specific touch actor AOI instead.} \item{target}{The target respondent/segment for the sensor (an imRespondent/imSegment object as returned from \code{\link{getRespondents}} or \code{\link{getSegments}}).} diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index 29fd7c6..dec18c5 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -148,6 +148,20 @@ test_that("local return - combinations without a fileId are filtered out", { expect_false(TA2 %in% details$touchActorId, "the touch actor without contact detection should be gone") }) +test_that("local return - passing an imTouchAOI scopes details down to that (touch actor, AOI) pair", { + # TA1 has 2 interactive AOIs (AOI1, AOI2) - the endpoint reports both since the wildcard sits on the touch + # actor, not the AOI (see getTouchActorDetailsUrl.imTouchAOI). Only the (TA1, AOI1) pair should survive. + touchAoi <- aoiDefinitions()[1, ] + touchAoi$touchActorId <- TA1 + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) + + details <- mockedGetTouchActorDetails(study, touchAoi, respondent) + + expect_equal(nrow(details), 1, info = "only the requested (touch actor, AOI) pair should be kept") + expect_identical(details$touchActorId, TA1) + expect_identical(details$aoiId, AOI1) +}) + test_that("local return - a fileId already present short-circuits the request", { touchAoi <- aoiDefinitions()[1, ] touchAoi$fileId <- "../data/touchActorRespondentData.pbin" @@ -194,10 +208,18 @@ mockedGetTouchActorAois <- function(study, imObject, respondent, detailsPath = t } test_that("error - arguments are missing or not from the good class", { + expect_error(getTouchActorAois(imObject = stimulus, respondent = respondent), + "Please specify a study loaded with `imStudy()`", fixed = TRUE, + info = "missing `study` param not handled properly") + expect_error(getTouchActorAois(study, respondent = respondent), "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`", fixed = TRUE, info = "missing `imObject` param not handled properly") + expect_error(getTouchActorAois(study = "whatever", stimulus, respondent), + "`study` argument is not an imStudy object", + info = "study not being an imStudy object should throw an error") + expect_error(getTouchActorAois(study, stimulus, respondent = "whatever"), "`respondent` argument is not an imRespondent object", info = "respondent not being an imRespondent object should throw an error") diff --git a/imotionsApi/tests/testthat/test-uploadAOIMetrics.R b/imotionsApi/tests/testthat/test-uploadAOIMetrics.R index 274eac8..190145e 100644 --- a/imotionsApi/tests/testthat/test-uploadAOIMetrics.R +++ b/imotionsApi/tests/testthat/test-uploadAOIMetrics.R @@ -75,6 +75,30 @@ test_that("local check - should call privateGetAoiDetails and fwrite for a speci expectCallDetails = 1, expectCallsfwrite = 1) }) +test_that("local check - a touch AOI dispatches to privateGetTouchActorDetails rather than privateGetAoiDetails", { + touchAoi <- AOI + class(touchAoi) <- c("imTouchAOI", class(touchAoi)) + + expectedFilepath <- paste0(tools::file_path_sans_ext(AOIDetailsFile$fileId), "metrics.csv") + + privateGetAoiDetails_Stub <- mock() + privateGetTouchActorDetails_Stub <- mock(AOIDetailsFile) + fwrite_Stub <- mock() + + mockr::with_mock(privateGetAoiDetails = privateGetAoiDetails_Stub, + privateGetTouchActorDetails = privateGetTouchActorDetails_Stub, + fwrite = fwrite_Stub, { + privateUploadAoiMetrics(study, respondent, touchAoi, metrics) + }) + + expect_called(privateGetAoiDetails_Stub, 0) + expect_called(privateGetTouchActorDetails_Stub, 1) + expect_args(privateGetTouchActorDetails_Stub, 1, study = study, imObject = touchAoi, respondent = respondent) + + expect_called(fwrite_Stub, 1) + expect_args(fwrite_Stub, 1, x = metrics, file = expectedFilepath, col.names = TRUE, row.names = FALSE) +}) + test_that("remote warning - should throw a warning and exit if no local path was set for a specific respondent", { expect_warning(mockPrivateUploadAoiMetrics(study_cloud, respondent, AOI_cloud, metrics, AOIDetailsFile, expectCallDetails = 1), fixed = TRUE, From 8e449941b794a942b166f4985e727a187d765954 Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 11 Sep 2026 14:09:51 +0200 Subject: [PATCH 10/12] Remove None hand type. Added getTouchActor and getTouchActorAoi single utility functions --- imotionsApi/NAMESPACE | 2 + imotionsApi/R/imotionsApi.R | 129 +++++++++++++++-- imotionsApi/man/getTouchActor.Rd | 35 +++++ imotionsApi/man/getTouchActorAoi.Rd | 39 +++++ imotionsApi/man/getTouchActorAoisUrl.Rd | 18 +++ .../man/getTouchActorDetailsUrl.imStimulus.Rd | 3 +- .../man/getTouchActorDetailsUrl.imTouchAOI.Rd | 3 +- imotionsApi/man/privateDecodeHandType.Rd | 4 +- .../man/privateGetTouchActorAoiDefinitions.Rd | 24 ++++ .../tests/testthat/test-getTouchActors.R | 133 +++++++++++++++++- 10 files changed, 371 insertions(+), 19 deletions(-) create mode 100644 imotionsApi/man/getTouchActor.Rd create mode 100644 imotionsApi/man/getTouchActorAoi.Rd create mode 100644 imotionsApi/man/getTouchActorAoisUrl.Rd create mode 100644 imotionsApi/man/privateGetTouchActorAoiDefinitions.Rd diff --git a/imotionsApi/NAMESPACE b/imotionsApi/NAMESPACE index 39cd467..8c64900 100644 --- a/imotionsApi/NAMESPACE +++ b/imotionsApi/NAMESPACE @@ -44,6 +44,8 @@ export(getSensors) export(getSensorsMetadata) export(getStimuli) export(getStimulus) +export(getTouchActor) +export(getTouchActorAoi) export(getTouchActorAois) export(getTouchActors) export(imConnection) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index d697060..202b947 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -1862,6 +1862,50 @@ getTouchActors <- function(study, stimulus) { } +#' Get a specific touch actor from a stimulus. +#' +#' Available touch actors can be found with \code{\link{getTouchActors}}. Passing the result on to +#' \code{\link{getTouchActorAois}} (instead of the whole stimulus) scopes the underlying contact detail fetch to just +#' this actor - see \code{getTouchActorDetailsUrl.imTouchActor} - rather than triggering signal generation for every +#' touch actor on the stimulus. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' @param touchActorId The id of the touch actor you would like to retrieve. +#' +#' @return An imTouchActor object (data.table) containing the touch actor of interest, or NULL if none is defined +#' for this stimulus or none matches touchActorId. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' touchActors <- imotionsApi::getTouchActors(study, stimulus) +#' touchActor <- imotionsApi::getTouchActor(study, stimulus, touchActors$id[1]) +#' } +getTouchActor <- function(study, stimulus, touchActorId) { + assertValid(hasArg(touchActorId), + "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`") + + touchActors <- getTouchActors(study, stimulus) + + if (is.null(touchActors)) { + return(NULL) + } + + touchActor <- touchActors[touchActors$id == touchActorId, ] + + if (nrow(touchActor) == 0) { + warning(paste("No touch actor found matching id:", touchActorId)) + return(NULL) + } + + return(touchActor) +} + + #' Get the AOI definitions of every camera that supports contact, for a stimulus. #' #' Sibling of \code{\link{privateAoiFiltering}} for touch actors: that one only ever reaches the Stimulus/Scene @@ -2036,6 +2080,62 @@ getTouchActorAois <- function(study, imObject, respondent = NULL) { } +#' Get a specific (touch actor, AOI) combination from a stimulus. +#' +#' Available combinations can be found with \code{\link{getTouchActorAois}}. Both a touchActorId and an aoiId are +#' required - unlike a gaze AOI, more than one touch actor can share the same interactive AOI, so the aoiId alone +#' would not uniquely identify one combination. +#' +#' @param study An imStudy object as returned from \code{\link{imStudy}}. +#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. +#' @param touchActorId The id of the touch actor you would like to retrieve. +#' @param aoiId The id of the AOI you would like to retrieve. +#' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}} to attach that +#' respondent's contact in/out fileId/resultId to the result. +#' +#' @return An imTouchAOI object (data.table) containing the (touch actor, AOI) combination of interest, or NULL if +#' touchActorId itself doesn't match, or matches but has no AOI matching aoiId. +#' @export +#' @examples +#' \dontrun{ +#' connection <- imotionsApi::imConnection("xxxxxxxx") +#' studies <- imotionsApi::listStudies(connection) +#' study <- imotionsApi::imStudy(connection, studies$id[1]) +#' stimulus <- imotionsApi::getStimuli(study)[1, ] +#' touchAois <- imotionsApi::getTouchActorAois(study, stimulus) +#' touchAoi <- imotionsApi::getTouchActorAoi(study, stimulus, touchAois$touchActorId[1], touchAois$id[1]) +#' } +getTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respondent = NULL) { + assertValid(hasArg(touchActorId), + "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`") + assertValid(hasArg(aoiId), + "Please specify an aoiId. Available touch actor AOIs can be found with `getTouchActorAois()`") + + touchActor <- getTouchActor(study, stimulus, touchActorId) + + if (is.null(touchActor)) { + return(NULL) + } + + # Passing the resolved touch actor rather than the whole stimulus scopes the underlying contact detail fetch to + # just this actor, instead of triggering signal generation for every touch actor on the stimulus. + touchAois <- getTouchActorAois(study, touchActor, respondent) + + if (is.null(touchAois)) { + return(NULL) + } + + touchAoi <- touchAois[touchAois$id == aoiId, ] + + if (nrow(touchAoi) == 0) { + warning(paste("No touch actor AOI found matching touchActorId:", touchActorId, "and aoiId:", aoiId)) + return(NULL) + } + + return(touchAoi) +} + + #' Get the contact in/out data for a specific (touch actor, AOI)/respondent combination. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. @@ -2222,22 +2322,27 @@ privateGetTouchActorDetails <- function(study, imObject, respondent = NULL) { #' #' @param codes A numeric vector of hand codes as stored in the HandType column. #' -#' @return A character vector with one label per code. +#' @return A character vector with one label per code. A code with no value at all (no touch on this row, so hand +#' type does not apply) stays \code{NA} rather than getting a label of its own - only a code that carries +#' an actual value but isn't a recognised one falls back to \code{"Unknown"}. #' @keywords internal privateDecodeHandType <- function(codes) { - # Codes are defined by TouchActorSampleMetaData in the desktop application: 0 = none, 1 = left, 2 = right, - # 3 = unknown. Anything unrecognised is reported as unknown rather than dropped, so a new code never silently - # becomes a missing value in the metrics. - labels <- c("None", "Left", "Right", "Unknown") - index <- as.integer(codes) + 1L - - # A negative code (e.g. -1) maps to index 0, which `labels[0]` silently drops instead of returning NA - shrinking - # the result vector rather than producing a value to overwrite below. Routing it through NA first keeps the - # result the same length as `codes`. - index[!is.na(index) & (index < 1L | index > length(labels))] <- NA_integer_ + # Codes are defined by TouchActorSampleMetaData in the desktop application: 1 = left, 2 = right, 3 = unknown. + # A row with no contact carries no HandType value at all rather than a dedicated code for it, so that stays NA + # here rather than getting a label of its own. Anything else unrecognised is reported as unknown rather than + # dropped, so a bad code never silently becomes a missing value in the metrics. + labels <- c("Left", "Right", "Unknown") + index <- as.integer(codes) + + # A merely missing `codes` entry is already NA and so never out of range here, leaving it to resolve to NA via + # `labels[NA]` below rather than getting relabelled - only a code that carries an actual but unrecognised value + # (e.g. a negative one, which would otherwise silently map to `labels[0]` and shrink the result instead of + # producing a value to overwrite) falls back to "Unknown". + outOfRange <- !is.na(index) & (index < 1L | index > length(labels)) + index[outOfRange] <- NA_integer_ decoded <- labels[index] - decoded[is.na(decoded)] <- "Unknown" + decoded[outOfRange] <- "Unknown" return(decoded) } diff --git a/imotionsApi/man/getTouchActor.Rd b/imotionsApi/man/getTouchActor.Rd new file mode 100644 index 0000000..8c4abf6 --- /dev/null +++ b/imotionsApi/man/getTouchActor.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActor} +\alias{getTouchActor} +\title{Get a specific touch actor from a stimulus.} +\usage{ +getTouchActor(study, stimulus, touchActorId) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} + +\item{touchActorId}{The id of the touch actor you would like to retrieve.} +} +\value{ +An imTouchActor object (data.table) containing the touch actor of interest, or NULL if none is defined + for this stimulus or none matches touchActorId. +} +\description{ +Available touch actors can be found with \code{\link{getTouchActors}}. Passing the result on to +\code{\link{getTouchActorAois}} (instead of the whole stimulus) scopes the underlying contact detail fetch to just +this actor - see \code{getTouchActorDetailsUrl.imTouchActor} - rather than triggering signal generation for every +touch actor on the stimulus. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +touchActors <- imotionsApi::getTouchActors(study, stimulus) +touchActor <- imotionsApi::getTouchActor(study, stimulus, touchActors$id[1]) +} +} diff --git a/imotionsApi/man/getTouchActorAoi.Rd b/imotionsApi/man/getTouchActorAoi.Rd new file mode 100644 index 0000000..c57f8e4 --- /dev/null +++ b/imotionsApi/man/getTouchActorAoi.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorAoi} +\alias{getTouchActorAoi} +\title{Get a specific (touch actor, AOI) combination from a stimulus.} +\usage{ +getTouchActorAoi(study, stimulus, touchActorId, aoiId, respondent = NULL) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} + +\item{touchActorId}{The id of the touch actor you would like to retrieve.} + +\item{aoiId}{The id of the AOI you would like to retrieve.} + +\item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}} to attach that +respondent's contact in/out fileId/resultId to the result.} +} +\value{ +An imTouchAOI object (data.table) containing the (touch actor, AOI) combination of interest, or NULL if + touchActorId itself doesn't match, or matches but has no AOI matching aoiId. +} +\description{ +Available combinations can be found with \code{\link{getTouchActorAois}}. Both a touchActorId and an aoiId are +required - unlike a gaze AOI, more than one touch actor can share the same interactive AOI, so the aoiId alone +would not uniquely identify one combination. +} +\examples{ +\dontrun{ +connection <- imotionsApi::imConnection("xxxxxxxx") +studies <- imotionsApi::listStudies(connection) +study <- imotionsApi::imStudy(connection, studies$id[1]) +stimulus <- imotionsApi::getStimuli(study)[1, ] +touchAois <- imotionsApi::getTouchActorAois(study, stimulus) +touchAoi <- imotionsApi::getTouchActorAoi(study, stimulus, touchAois$touchActorId[1], touchAois$id[1]) +} +} diff --git a/imotionsApi/man/getTouchActorAoisUrl.Rd b/imotionsApi/man/getTouchActorAoisUrl.Rd new file mode 100644 index 0000000..c99e65a --- /dev/null +++ b/imotionsApi/man/getTouchActorAoisUrl.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{getTouchActorAoisUrl} +\alias{getTouchActorAoisUrl} +\title{Return the path/url to the AOI definitions of every camera that supports contact, for a specific stimulus.} +\usage{ +getTouchActorAoisUrl(study, stimulusId) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulusId}{The id of the stimulus of interest.} +} +\description{ +Unlike \code{\link{getAoisUrl}}, which only ever reaches the Stimulus/Scene camera, this reports one row per AOI +across every touch-capable camera (e.g. Environment), tagged with mediaSourceType. +} +\keyword{internal} diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd index 19ac6ba..4dc19d3 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.imStimulus.Rd @@ -10,7 +10,8 @@ defined for a stimulus.} \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} +\item{imObject}{An imStimulus object, an imTouchActor object as returned from \code{\link{getTouchActors}}, or one +row of \code{\link{getTouchActorAois}}.} \item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, the url targets every respondent exposed to the stimulus in a single response.} diff --git a/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd index 7aa5317..2d28f07 100644 --- a/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd +++ b/imotionsApi/man/getTouchActorDetailsUrl.imTouchAOI.Rd @@ -9,7 +9,8 @@ \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{imObject}{An imStimulus object, or one row of \code{\link{getTouchActorAois}}.} +\item{imObject}{An imStimulus object, an imTouchActor object as returned from \code{\link{getTouchActors}}, or one +row of \code{\link{getTouchActorAois}}.} \item{respondent}{Optional - An imRespondent object as returned from \code{\link{getRespondents}}. Without one, the url targets every respondent exposed to the stimulus in a single response.} diff --git a/imotionsApi/man/privateDecodeHandType.Rd b/imotionsApi/man/privateDecodeHandType.Rd index 479fb08..67fa41a 100644 --- a/imotionsApi/man/privateDecodeHandType.Rd +++ b/imotionsApi/man/privateDecodeHandType.Rd @@ -10,7 +10,9 @@ privateDecodeHandType(codes) \item{codes}{A numeric vector of hand codes as stored in the HandType column.} } \value{ -A character vector with one label per code. +A character vector with one label per code. A code with no value at all (no touch on this row, so hand + type does not apply) stays \code{NA} rather than getting a label of its own - only a code that carries + an actual value but isn't a recognised one falls back to \code{"Unknown"}. } \description{ Private function translating the numeric hand codes stored in a contact in/out file into readable labels. diff --git a/imotionsApi/man/privateGetTouchActorAoiDefinitions.Rd b/imotionsApi/man/privateGetTouchActorAoiDefinitions.Rd new file mode 100644 index 0000000..9e03f29 --- /dev/null +++ b/imotionsApi/man/privateGetTouchActorAoiDefinitions.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/imotionsApi.R +\name{privateGetTouchActorAoiDefinitions} +\alias{privateGetTouchActorAoiDefinitions} +\title{Get the AOI definitions of every camera that supports contact, for a stimulus.} +\usage{ +privateGetTouchActorAoiDefinitions(study, stimulus) +} +\arguments{ +\item{study}{An imStudy object as returned from \code{\link{imStudy}}.} + +\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} +} +\value{ +A data.table with one row per AOI (id, name, type, group, area, mediaSourceType) across every touch-capable + camera, or NULL if none are defined. +} +\description{ +Sibling of \code{\link{privateAoiFiltering}} for touch actors: that one only ever reaches the Stimulus/Scene +camera, while a touch actor's interactive AOIs can live on any camera contact detection supports (e.g. +Environment). Used by \code{\link{getTouchActorAois}} to resolve a name/type/group/area for every touch actor AOI, +not just the ones on Scene. +} +\keyword{internal} diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index dec18c5..c9f0ac0 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -103,6 +103,52 @@ test_that("warning - touch actors are not available for a remote study", { }) +# getTouchActor ======================================================================================================== +context("getTouchActor()") + +mockedGetTouchActor <- function(study, stimulus, touchActorId, jsonPath = touchActorsPath, expectedCall = 1) { + getJSON_Stub <- mock(jsonlite::fromJSON(jsonPath)) + + touchActor <- mockr::with_mock(getJSON = getJSON_Stub, { + getTouchActor(study, stimulus, touchActorId) + }) + + expect_called(getJSON_Stub, expectedCall) + return(touchActor) +} + +test_that("error - touchActorId is missing", { + expect_error(getTouchActor(study, stimulus), + "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`", + fixed = TRUE, info = "missing `touchActorId` param not handled properly") +}) + +test_that("warning - no touch actor defined for this stimulus", { + expect_warning(touchActor <- mockedGetTouchActor(study, stimulus, TA1, noTouchActorsPath), + "No touch actor defined for Stimulus: IAAF", + info = "no touch actor defined should throw a warning") + + expect_null(touchActor, info = "result should be null") +}) + +test_that("warning - wrong touchActorId is provided", { + expect_warning(touchActor <- mockedGetTouchActor(study, stimulus, "wrong-id"), + "No touch actor found matching id: wrong-id", + info = "wrong touchActorId not handled properly") + + expect_null(touchActor, info = "result should be null") +}) + +test_that("local return - specific touch actor from a stimulus", { + touchActor <- mockedGetTouchActor(study, stimulus, TA2) + + expect_s3_class(touchActor, "imTouchActor") + expect_equal(nrow(touchActor), 1, info = "should only contain a single touch actor") + expect_identical(touchActor$id, TA2, "wrong touch actor id") + expect_identical(touchActor$hand, "Left", "wrong hand") +}) + + # privateGetTouchActorDetails ========================================================================================= context("privateGetTouchActorDetails()") @@ -384,6 +430,80 @@ test_that("warning - contact in/out signals found do not match any touch actor p }) +# getTouchActorAoi ===================================================================================================== +context("getTouchActorAoi()") + +mockedGetTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respondent = NULL, + detailsPath = touchActorDetailsPath) { + touchActors <- suppressWarnings(mockedGetTouchActors(study, stimulus)) + + touchAoi <- mockr::with_mock( + getTouchActors = function(...) touchActors, + privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), + privateGetTouchActorDetails = function(...) jsonlite::fromJSON(detailsPath), { + getTouchActorAoi(study, stimulus, touchActorId, aoiId, respondent) + } + ) + + return(touchAoi) +} + +test_that("error - touchActorId or aoiId are missing", { + expect_error(getTouchActorAoi(study, stimulus), + "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`", + fixed = TRUE, info = "missing `touchActorId` param not handled properly") + + expect_error(getTouchActorAoi(study, stimulus, TA1), + "Please specify an aoiId. Available touch actor AOIs can be found with `getTouchActorAois()`", + fixed = TRUE, info = "missing `aoiId` param not handled properly") +}) + +test_that("warning - no touch actor matches touchActorId", { + expect_warning(touchAoi <- mockedGetTouchActorAoi(study, stimulus, "wrong-id", AOI1), + "No touch actor found matching id: wrong-id", + info = "wrong touchActorId not handled properly") + + expect_null(touchAoi, info = "result should be null") +}) + +test_that("warning - touch actor matches but has no AOI matching aoiId", { + # AOI2 is only ever referenced by TA1 (see "interactiveAoiIds is kept as a list column" above) - TA2's own AOI + # list never includes it, regardless of respondent/contact data, so this should fail before any detail is fetched. + expect_warning(touchAoi <- mockedGetTouchActorAoi(study, stimulus, TA2, AOI2), + paste("No touch actor AOI found matching touchActorId:", TA2, "and aoiId:", AOI2), + info = "wrong aoiId not handled properly") + + expect_null(touchAoi, info = "result should be null") +}) + +test_that("local return - specific (touch actor, AOI) combination, scoped to the requested actor", { + touchAoi <- mockr::with_mock( + getTouchActors = function(...) suppressWarnings(mockedGetTouchActors(study, stimulus)), + privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), + privateGetTouchActorDetails = function(study, imObject, respondent) { + expect_s3_class(imObject, "imTouchActor") + expect_identical(imObject$id, TA2, + "privateGetTouchActorDetails should be scoped to the requested touch actor") + jsonlite::fromJSON(touchActorDetailsPath) + }, { + getTouchActorAoi(study, stimulus, TA2, AOI1, respondent) + } + ) + + expect_s3_class(touchAoi, "imTouchAOI") + expect_equal(nrow(touchAoi), 1, info = "should only contain a single (touch actor, AOI) combination") + expect_identical(touchAoi$touchActorId, TA2, "wrong touch actor id") + expect_identical(touchAoi$id, AOI1, "wrong AOI id") +}) + +test_that("local return - without a respondent, only the AOI/touch actor definition is returned", { + touchAoi <- mockedGetTouchActorAoi(study, stimulus, TA2, AOI1, respondent = NULL) + + expect_equal(nrow(touchAoi), 1, info = "should only contain a single (touch actor, AOI) combination") + expect_false("fileId" %in% names(touchAoi), info = "no contact in/out details should be attached") +}) + + # getAoiRespondentTouchData =========================================================================================== context("getAoiRespondentTouchData()") @@ -438,7 +558,7 @@ test_that("local return - inOutContact is compressed on contact and hand", { test_that("local return - a hand handover mid-contact stays visible", { inOutContact <- getAoiRespondentTouchData(study, touchAoiInOut(), respondent)$inOutContact - expect_identical(inOutContact$HandType, c("None", "Left", "Right", "None", "Right", "None"), + expect_identical(inOutContact$HandType, c("Unknown", "Left", "Right", "Unknown", "Right", "Unknown"), "hand codes should be decoded and the handover kept as its own row") expect_equal(inOutContact[inOutContact$HandType == "Left", ]$Timestamp, 9500, 1e-2, @@ -535,15 +655,20 @@ test_that("local return - no respondent has contact data", { context("privateDecodeHandType()") test_that("hand codes are decoded to their labels", { - expect_identical(imotionsApi:::privateDecodeHandType(c(0, 1, 2, 3)), c("None", "Left", "Right", "Unknown"), + expect_identical(imotionsApi:::privateDecodeHandType(c(1, 2, 3)), c("Left", "Right", "Unknown"), "wrong labels for the documented hand codes") }) -test_that("an unrecognised or missing code is reported as unknown rather than dropped", { - expect_identical(imotionsApi:::privateDecodeHandType(c(9, NA, -1)), rep("Unknown", 3), +test_that("an unrecognised but present code is reported as unknown rather than dropped", { + expect_identical(imotionsApi:::privateDecodeHandType(c(9, -1, 0)), rep("Unknown", 3), "unrecognised codes should not become missing values") }) +test_that("a genuinely missing code stays missing rather than becoming unknown", { + expect_identical(imotionsApi:::privateDecodeHandType(NA), NA_character_, + "a missing hand type means no touch occurred at all, not an unrecognised code") +}) + # Touch actor urls ==================================================================================================== context("getTouchActorDetailsUrl()") From 93f54360750d221dcd6f4cf17de4bca13f3f524e Mon Sep 17 00:00:00 2001 From: Carlos Marcos Torrejon Date: Fri, 11 Sep 2026 16:26:39 +0200 Subject: [PATCH 11/12] Modify getTouchActorAoi overload to include imObject following getTouchActorAois pattern. --- imotionsApi/R/imotionsApi.R | 39 ++++++-------- imotionsApi/man/getTouchActorAoi.Rd | 24 +++++---- .../tests/testthat/test-getTouchActors.R | 52 +++++++++++++------ 3 files changed, 67 insertions(+), 48 deletions(-) diff --git a/imotionsApi/R/imotionsApi.R b/imotionsApi/R/imotionsApi.R index 202b947..021ca13 100644 --- a/imotionsApi/R/imotionsApi.R +++ b/imotionsApi/R/imotionsApi.R @@ -2080,21 +2080,22 @@ getTouchActorAois <- function(study, imObject, respondent = NULL) { } -#' Get a specific (touch actor, AOI) combination from a stimulus. +#' Get the touch actor AOI(s) matching a specific aoiId. #' -#' Available combinations can be found with \code{\link{getTouchActorAois}}. Both a touchActorId and an aoiId are -#' required - unlike a gaze AOI, more than one touch actor can share the same interactive AOI, so the aoiId alone -#' would not uniquely identify one combination. +#' Calls \code{\link{getTouchActorAois}} and filters the result down to aoiId. Passing an imTouchActor pins the +#' search to that one actor, so the result is a single imTouchAOI row. Passing an imStimulus can still return more +#' than one row (an imTouchAOIList) if several touch actors share that interactive AOI. #' #' @param study An imStudy object as returned from \code{\link{imStudy}}. -#' @param stimulus An imStimulus object as returned from \code{\link{getStimuli}}. -#' @param touchActorId The id of the touch actor you would like to retrieve. +#' @param imObject An imStimulus object as returned from \code{\link{getStimuli}} to look across every touch actor on +#' it, or an imTouchActor object as returned from \code{\link{getTouchActor}}/ +#' \code{\link{getTouchActors}} to only look at that one actor. #' @param aoiId The id of the AOI you would like to retrieve. #' @param respondent Optional - An imRespondent object as returned from \code{\link{getRespondents}} to attach that #' respondent's contact in/out fileId/resultId to the result. #' -#' @return An imTouchAOI object (data.table) containing the (touch actor, AOI) combination of interest, or NULL if -#' touchActorId itself doesn't match, or matches but has no AOI matching aoiId. +#' @return An imTouchAOI object (data.table) if imObject narrows the match to a single (touch actor, AOI) +#' combination, an imTouchAOIList if more than one touch actor shares aoiId, or NULL if none match. #' @export #' @examples #' \dontrun{ @@ -2103,23 +2104,17 @@ getTouchActorAois <- function(study, imObject, respondent = NULL) { #' study <- imotionsApi::imStudy(connection, studies$id[1]) #' stimulus <- imotionsApi::getStimuli(study)[1, ] #' touchAois <- imotionsApi::getTouchActorAois(study, stimulus) -#' touchAoi <- imotionsApi::getTouchActorAoi(study, stimulus, touchAois$touchActorId[1], touchAois$id[1]) +#' +#' touchActor <- imotionsApi::getTouchActor(study, stimulus, touchAois$touchActorId[1]) +#' touchAoi <- imotionsApi::getTouchActorAoi(study, touchActor, touchAois$id[1]) #' } -getTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respondent = NULL) { - assertValid(hasArg(touchActorId), - "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`") +getTouchActorAoi <- function(study, imObject, aoiId, respondent = NULL) { + assertValid(hasArg(imObject), + "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`") assertValid(hasArg(aoiId), "Please specify an aoiId. Available touch actor AOIs can be found with `getTouchActorAois()`") - touchActor <- getTouchActor(study, stimulus, touchActorId) - - if (is.null(touchActor)) { - return(NULL) - } - - # Passing the resolved touch actor rather than the whole stimulus scopes the underlying contact detail fetch to - # just this actor, instead of triggering signal generation for every touch actor on the stimulus. - touchAois <- getTouchActorAois(study, touchActor, respondent) + touchAois <- getTouchActorAois(study, imObject, respondent) if (is.null(touchAois)) { return(NULL) @@ -2128,7 +2123,7 @@ getTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respondent = touchAoi <- touchAois[touchAois$id == aoiId, ] if (nrow(touchAoi) == 0) { - warning(paste("No touch actor AOI found matching touchActorId:", touchActorId, "and aoiId:", aoiId)) + warning(paste("No touch actor AOI found matching aoiId:", aoiId)) return(NULL) } diff --git a/imotionsApi/man/getTouchActorAoi.Rd b/imotionsApi/man/getTouchActorAoi.Rd index c57f8e4..b1d0a09 100644 --- a/imotionsApi/man/getTouchActorAoi.Rd +++ b/imotionsApi/man/getTouchActorAoi.Rd @@ -2,16 +2,16 @@ % Please edit documentation in R/imotionsApi.R \name{getTouchActorAoi} \alias{getTouchActorAoi} -\title{Get a specific (touch actor, AOI) combination from a stimulus.} +\title{Get the touch actor AOI(s) matching a specific aoiId.} \usage{ -getTouchActorAoi(study, stimulus, touchActorId, aoiId, respondent = NULL) +getTouchActorAoi(study, imObject, aoiId, respondent = NULL) } \arguments{ \item{study}{An imStudy object as returned from \code{\link{imStudy}}.} -\item{stimulus}{An imStimulus object as returned from \code{\link{getStimuli}}.} - -\item{touchActorId}{The id of the touch actor you would like to retrieve.} +\item{imObject}{An imStimulus object as returned from \code{\link{getStimuli}} to look across every touch actor on +it, or an imTouchActor object as returned from \code{\link{getTouchActor}}/ +\code{\link{getTouchActors}} to only look at that one actor.} \item{aoiId}{The id of the AOI you would like to retrieve.} @@ -19,13 +19,13 @@ getTouchActorAoi(study, stimulus, touchActorId, aoiId, respondent = NULL) respondent's contact in/out fileId/resultId to the result.} } \value{ -An imTouchAOI object (data.table) containing the (touch actor, AOI) combination of interest, or NULL if - touchActorId itself doesn't match, or matches but has no AOI matching aoiId. +An imTouchAOI object (data.table) if imObject narrows the match to a single (touch actor, AOI) + combination, an imTouchAOIList if more than one touch actor shares aoiId, or NULL if none match. } \description{ -Available combinations can be found with \code{\link{getTouchActorAois}}. Both a touchActorId and an aoiId are -required - unlike a gaze AOI, more than one touch actor can share the same interactive AOI, so the aoiId alone -would not uniquely identify one combination. +Calls \code{\link{getTouchActorAois}} and filters the result down to aoiId. Passing an imTouchActor pins the +search to that one actor, so the result is a single imTouchAOI row. Passing an imStimulus can still return more +than one row (an imTouchAOIList) if several touch actors share that interactive AOI. } \examples{ \dontrun{ @@ -34,6 +34,8 @@ studies <- imotionsApi::listStudies(connection) study <- imotionsApi::imStudy(connection, studies$id[1]) stimulus <- imotionsApi::getStimuli(study)[1, ] touchAois <- imotionsApi::getTouchActorAois(study, stimulus) -touchAoi <- imotionsApi::getTouchActorAoi(study, stimulus, touchAois$touchActorId[1], touchAois$id[1]) + +touchActor <- imotionsApi::getTouchActor(study, stimulus, touchAois$touchActorId[1]) +touchAoi <- imotionsApi::getTouchActorAoi(study, touchActor, touchAois$id[1]) } } diff --git a/imotionsApi/tests/testthat/test-getTouchActors.R b/imotionsApi/tests/testthat/test-getTouchActors.R index c9f0ac0..5534d27 100644 --- a/imotionsApi/tests/testthat/test-getTouchActors.R +++ b/imotionsApi/tests/testthat/test-getTouchActors.R @@ -433,7 +433,7 @@ test_that("warning - contact in/out signals found do not match any touch actor p # getTouchActorAoi ===================================================================================================== context("getTouchActorAoi()") -mockedGetTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respondent = NULL, +mockedGetTouchActorAoi <- function(study, imObject, aoiId, respondent = NULL, detailsPath = touchActorDetailsPath) { touchActors <- suppressWarnings(mockedGetTouchActors(study, stimulus)) @@ -441,41 +441,52 @@ mockedGetTouchActorAoi <- function(study, stimulus, touchActorId, aoiId, respond getTouchActors = function(...) touchActors, privateGetTouchActorAoiDefinitions = function(...) aoiDefinitions(), privateGetTouchActorDetails = function(...) jsonlite::fromJSON(detailsPath), { - getTouchActorAoi(study, stimulus, touchActorId, aoiId, respondent) + getTouchActorAoi(study, imObject, aoiId, respondent) } ) return(touchAoi) } -test_that("error - touchActorId or aoiId are missing", { - expect_error(getTouchActorAoi(study, stimulus), - "Please specify a touchActorId. Available touch actors can be found with `getTouchActors()`", - fixed = TRUE, info = "missing `touchActorId` param not handled properly") +test_that("error - imObject or aoiId are missing", { + expect_error(getTouchActorAoi(study), + "Please specify a stimulus loaded with `getStimuli()` or a touch actor loaded with `getTouchActors()`", + fixed = TRUE, info = "missing `imObject` param not handled properly") - expect_error(getTouchActorAoi(study, stimulus, TA1), + expect_error(getTouchActorAoi(study, stimulus), "Please specify an aoiId. Available touch actor AOIs can be found with `getTouchActorAois()`", fixed = TRUE, info = "missing `aoiId` param not handled properly") }) -test_that("warning - no touch actor matches touchActorId", { - expect_warning(touchAoi <- mockedGetTouchActorAoi(study, stimulus, "wrong-id", AOI1), - "No touch actor found matching id: wrong-id", - info = "wrong touchActorId not handled properly") +test_that("warning - imObject is a stimulus with no touch actor matching aoiId", { + expect_warning(touchAoi <- mockedGetTouchActorAoi(study, stimulus, "wrong-id"), + "No touch actor AOI found matching aoiId: wrong-id", + info = "wrong aoiId not handled properly") expect_null(touchAoi, info = "result should be null") }) test_that("warning - touch actor matches but has no AOI matching aoiId", { + touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] # TA2 + # AOI2 is only ever referenced by TA1 (see "interactiveAoiIds is kept as a list column" above) - TA2's own AOI # list never includes it, regardless of respondent/contact data, so this should fail before any detail is fetched. - expect_warning(touchAoi <- mockedGetTouchActorAoi(study, stimulus, TA2, AOI2), - paste("No touch actor AOI found matching touchActorId:", TA2, "and aoiId:", AOI2), + expect_warning(touchAoi <- mockedGetTouchActorAoi(study, touchActor, AOI2), + paste("No touch actor AOI found matching aoiId:", AOI2), info = "wrong aoiId not handled properly") expect_null(touchAoi, info = "result should be null") }) +test_that("local return - imObject is a stimulus and aoiId matches more than one touch actor", { + # AOI1 is referenced by both TA1 and TA2, so a bare stimulus intentionally returns both as an imTouchAOIList. + touchAois <- mockedGetTouchActorAoi(study, stimulus, AOI1, respondent) + + expect_s3_class(touchAois, "imTouchAOIList") + expect_equal(nrow(touchAois), 2, info = "both touch actors sharing AOI1 should be returned") + expect_setequal(touchAois$touchActorId, c(TA1, TA2)) +}) + test_that("local return - specific (touch actor, AOI) combination, scoped to the requested actor", { touchAoi <- mockr::with_mock( getTouchActors = function(...) suppressWarnings(mockedGetTouchActors(study, stimulus)), @@ -486,7 +497,8 @@ test_that("local return - specific (touch actor, AOI) combination, scoped to the "privateGetTouchActorDetails should be scoped to the requested touch actor") jsonlite::fromJSON(touchActorDetailsPath) }, { - getTouchActorAoi(study, stimulus, TA2, AOI1, respondent) + touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] # TA2 + getTouchActorAoi(study, touchActor, AOI1, respondent) } ) @@ -496,8 +508,18 @@ test_that("local return - specific (touch actor, AOI) combination, scoped to the expect_identical(touchAoi$id, AOI1, "wrong AOI id") }) +test_that("local return - a stimulus resolves fine as long as aoiId is unambiguous", { + # AOI2 is only ever referenced by TA1, so passing the whole stimulus is not ambiguous here. + touchAoi <- mockedGetTouchActorAoi(study, stimulus, AOI2, respondent) + + expect_equal(nrow(touchAoi), 1, info = "should only contain a single (touch actor, AOI) combination") + expect_identical(touchAoi$touchActorId, TA1, "wrong touch actor id") + expect_identical(touchAoi$id, AOI2, "wrong AOI id") +}) + test_that("local return - without a respondent, only the AOI/touch actor definition is returned", { - touchAoi <- mockedGetTouchActorAoi(study, stimulus, TA2, AOI1, respondent = NULL) + touchActor <- suppressWarnings(mockedGetTouchActors(study, stimulus))[2, ] # TA2 + touchAoi <- mockedGetTouchActorAoi(study, touchActor, AOI1, respondent = NULL) expect_equal(nrow(touchAoi), 1, info = "should only contain a single (touch actor, AOI) combination") expect_false("fileId" %in% names(touchAoi), info = "no contact in/out details should be attached") From b1d8edb3579cc10fa6d89c08c0afee3ac1428f4c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:41:18 +0000 Subject: [PATCH 12/12] Update release documentation for v2.9.4.2 --- documentation/imotionsApi_2.9.4.2.pdf | Bin 0 -> 142655 bytes documentation/imotionsApi_2.9.5.pdf | Bin 128943 -> 0 bytes imotionsApi/DESCRIPTION | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 documentation/imotionsApi_2.9.4.2.pdf delete mode 100644 documentation/imotionsApi_2.9.5.pdf diff --git a/documentation/imotionsApi_2.9.4.2.pdf b/documentation/imotionsApi_2.9.4.2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed4ad182e3dd5564c62a1c0d9c000fc92b652335 GIT binary patch literal 142655 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%0D&nZk1P6( z+M$6iO#^&zTR>3xP^_Y&P+oROUU#y*Oz8b}^f6cnA4F6=n$iVtSI9_bqD|(+6lsFufXn7i#EhDP9t$fFscyw4^akJkzp-ub?7KCE$IUEb^? z=hVw)wM5)kA73>u)AjN{t@vJDg-9ZB>r|w@MeNUv4iDbAT^w3pdgG+b_cqQe3y~50 z_j;1Oc7MxuSv_1TT6@RBRFY%-0<<^4$s>uXFt0u@+tVOFvoOjAL4k+UofhKnxjG-Z zH%zXN_GHE~NCq5j;(GY*JhAaRx0#f^tyMjz{pkGoz&kyMYa^5tMk$hW00yDvM5v&+ zLnLGD`8fqvAeQqsXf5pfl21hzP}~4>@I514EV<(K(k;sy?3qaWMc20P5R{;qP*goU+KMYX<=*n^sDJ9cmf7ry zh6Yvl&ybid)Q9jj!f_$y_!T=%Y&w-lZsu(+!YsmhSH+XCvv9q?d&@wHXM=2LB$9mRPld|JA2ZwkyEnKM{1iJ+xeq3ZV&X?5EZ z#YTu87QdxB_ao~Vi-vCE(A7rLI79dw`bi(nbLABMsGye$CAqYyEnWOl=R8Jnn}K7#Rs!=6QU0c@S6rf#eG zJ4)ZCRC|>8@AKHVq!`fWs2VnUbrdAR9H3GP zz*4nuSbE+1($K`JBVHHSMv{54looN6J}&~k!3f76qJ8lZ30))Z`DHJ9^^(9d3^a$;I+EI|4<8cV+f5S4U9*;u`oBNwlh>NW)hadte=Ah^%%84LDH>i%NbO_E!nrBX+S+CM8vN^PtHvU*jF$ z_Q6w?1?KBFKuC(~!#~8F|Bu4sKY23jKcjH|-AevaMIvUN0j29$O`RDBDa^xaIV=G& z8HgEzg`gLO&KS;ozsZk;PQ&E&nWJf*>{JMP&sW4VwE4O7xf9h7RA49S(ZNdlH#0m4 z!%ZmokfSf6zwjC05#b3OB!-xt0lB@xRw%>XthL53M*58Q+x7@cdNWAHK*D>{vUr02 zx3Hi{yw@e$PTZ7X;J!0vTBb4F$ctZp?<#1x=02|nS*`Q+Ap?O&fPh($HHJ)$Y3jOQ ztv$&VIrX0?9Ki;Dxny*$g_a^Sev&nN;G(^y-`9;Xia zE;)|yU_VuH>xnCxAQ)CqqBGIR+2;3qQO0=4Ha$=*{LfeX!E^bFAWC;|2I+h{5G6{#_tP z{F#nf*Db5im>NWursT+tu41CjGjMpfaI^S#rp!-Q#FpN@4AaXV$RI>w@K3}Sm!mB^ zq9wUCa&qt+6-_vqb2>L+f7ZG2*mz-Rcs@+G2h6-mAAGVoxwALq(JU*x?wuX$(rYWT z9bz4Ss3QFxReOb>N<1+}ORuVSxhp-`8+LIXAB|}F%Uzweu5Mh!6yD^u^wkaBigVY+ zpcQCma7H8QMNq|fEwK3mPeeXs*E+RxY#Nl)a^NwxU1_Z~!Vev{;(Win!pDED%0{H3 zy!NrbuMFtM14dqwAkLgas&W(;D6S)M#}4CVN03(ra8Ug(GZ17;Bj1$_Fso%-lvdp{ z1z4i|2#<^2QiDTSt&PGP$|}2}iP&xO_zVtxzvmVTFuQXC1!+-moepw_iu)BzDy?Z8 z;L$I_O<4FAC?#=BzCo2S(o9Lqo?yOsJ)e2v2o1dICefj|sJ+e+*m7~!b=cF^k$F4j z+rHA0G{0t6=q4`n?oI54ve5d$QzeDx8h*1x(Im z1ssf7?)nYF5t01^tL@a&@8h0sesGkAKO&0NA;Et>W=@9HU52vFFeoDaVW%Tu?m<8lSm5JJ z47*EgsU}m4`fE}Q!GmJIq$oN>5&xlVUiW-RZzL5!nr6A)zxuo=PqJLJqkM2P|OrJXWdyS&j7x{Fb@uREJ-a;UcdT<)Fl$Hzh-Va0rZ1C!f2mh}&qeN7psDfKB;N^X8|pk{AHYF^K#6Y72* zuf>eL@LPI}$8bNS>_%#sf`a!+OzB^bS9EC^yLD}l_TcrN%Jeo5?+w0=iH>B@>lpLk z+$g6D@;WaQ#SAEm+nKQfsuu*L?C}9*M>y^w@WgeCkx9u;pWiprm_D}ws_XHM^l}|2 ziE(Bjz;7xR;h&rBrRd;(?^?7E09;qC$}l0kW_B7Gykjt=&k@Dlzf{HtU7Bd8rb7_p z!@TbLKQdQDw$v=`@MmAGti}IgykbfY$I`jc!NbI@5{GD6r1&K$ylmI~N-^Ra4P|?T z^jSY{;=L1qc-IK;iMxr4Q*BHcsQ-L*T zE6ht6?VT9goP&2FCIH(*Kqv$j>O(n#3WNEZ7TN|wJe(pvjyvAy0Lc0~$vW}yYayZz z!V7CCHnIX$-mWr9TMAM$sjTBLmlXLq5>qA-zYA9|Z(cNmaTTCo$6F!k>7$B{Ak6SS zdM4OvkP^appmLDbvH&!2C7)#0rC(B~fqLy=%ti?4*}{4$-GkeQvD7d~VSyvhI27A*oj}@fq(91{*VGYth88Z zKK~*q^|?#cCrPUNZ2ItG{9{jpXxLWjpy?&1&MlBOqFB8v+yxf6h#N{ySZ23|Eypf} z7GLMrj-5gOK*nv84d0lJ(}y3SjM>EF8{cZ5m;TnsoL(1|9~#PJpE70OHrfoJHaw&T}T(HMVJG1aBe`w6W#R>iR~^XNRm|s z`^h!yNk{S9^5j>sIF);3_Q|un?u*q5M_v3K`&E2UKjqloR!I9~XKkiOY;wPe19w1c zF;gb1t!<{&t4E`5$Z_C&vWkUOG8*#EH3hU@*=%^Zp!&|rc112 zQ92w1x**~6yGZzMCD99FM}2kNNx}= z{0m;gZ>s~F8(9D#xFb$lb`;Gfe=bf&X>_4aONCL`V-B>I-^(I1 zP@4i!L!gBjx|;Ho&s&L>Y3O^gnYMGc9FzPugFXW2(Rd5C1KslQY>73}g;p5MQW}Lw z)CBugeu5*zrV>ys!+a~HD9TP-g`+sM!7zz|)=+5(n!LlFzsk-tb83bXSNkg4iIo%;1#P3qDoQw(SSgj?3RKwMU3?AcU-6 zvF@*lYRxq7V;*WLN2JhW=8xz$d5g? zoIlKZO1PXzbA)wF5-Ci-7T@D3Ucxm`_9nBr^V5@ElvC7Ce-V49yenaNX3o-czJwB(J1b*GK$1AoR zv5kG`jNWZm;raD(a&y!6q`Q#RKWs_1{|OQNKZ5-awe|mA|2v6wP*p1CKj!8Am}tww zBOy?Fi6=Ig!P%U_BC$Yfu9KU>Yf8133&E?!*RTHB#*FuPjk5_ydHi+M!NI&eOi0;E zp4gH3S(nw>mV_9#A?_ftW1hQ{Lb|mE!Y+58YEfI|oWFL7?cFKayD0Ixp~W12G~x0+$&y=#qT*4w z4E4Ub@$yyGd1boM^fy@wmGa;wh0%atmq=H2IaWpQO0jA@TRYc!vxdr4BgnJ#eZg#b zOVcmCLJtLjla|Ue@_c4C+5)1IN2j6vnSwCJvWMrcZG6W9GVap)esQ?rOljNSix2gY zu}n_hM}OdnSpxc*VUlo+x{B*xoKHqU?g8IVDIvmuFCsg{+ig+obKoQZy#-)qk9}Bj zV$uM;l_?(-tdy2=9nX(PR-tFMVqq%H|hAT6@#5 zD^hKp=hk)#?T^4rtL)e?XP`^)2zT|cgY3+W!3ar{88{GT2;T}^2Ng2B54MuJE2o zo9zL1R|Ptaz;K5wNYc^kEWHy}uvllJn=68jJ=S!y6uR2c>r?*pmzF+Pjlz%zevBRQ z3#=WES>fTbUhoj#C#g)YXNlywQ7GM3mII&e#rm#YLzc{0!-g+F`_fM_2m@44ejkXGiUWMa*{T(!jNv27+??o9j+fP8+&pLZ z)ulDycbmTl|Ix4hJ^_ud8T3il=5vSgH`m!9Rf+ks@55AIR6P8Q!D81VUF_v&bM6ds z!^tTVK=E%_kTG??e~3Ik(%OH~+cGjU|Jw|UPV`Zm{U7t}Y6K?U5rKlxHC8kDQ)xwM zMw!_G$Gd}`k;r^iB$c=<>94LBuS6Pmg}pqpNZ;{w{B5#nO|7iQ@r&cZi#@Ke%85w> z{wA~-v|Ao_2t(>HUUn!i%i6l6ry@#DZEf%Lgb|ZQl>7I=YV>7$wj5~QJu*s$MG&7n zd6O(e;FeQ>WyX={>=JI0R;%NI`sMU8MQ%Fd@E zUD+$ij~lnd({yFrGP&>{yK+fV8%lnb;|E2Rt59+=wAG@4x}75df9i-G3i83JhHPR3 zhnBYaWvDS+p}+*89O#Y}jDVx~T&TbV^Hh{wwNMu&%0oYPkBd~x2X>xZxay$Ja+@ZSG59DlT78IBWx;AJYduazI^B^|o+Br$c*K^Ezf`e3v zk~_Q?v1Eui!}}qIy$6l74*E`VBNtQTl=oy=Xz05cz|-c5T-~TH;%Cf=9Y$+ z|cKrp>Q8w`hn4GP(7^mmy6hb2L*EfknfGF zH$-Irtkazp;j1l!KFozno=LvRGw~dEBsG*octn|c{aUfw*VuIU&A6kjG%B`+STO-9 zAzxp9-C!ZfrkyBORMbNQ_r8}QWFH;3-0tc~e#i43EVa>){^p&{fHxo>9;zn;tFL&2 zb?f6~M@v;jH)yQX@kdt~--87;!*qLcTSG0@vuU-76Gd;#KFgT!0M~#r=~cc*A&EXg z^2yp@`~n9tii;nmoV1mn44`c=v9HL1`l}CuYorLbV3?#?5bsess;kWYbW-k9gC-0R zk2MFrCs!G_D~7f*#fNi%(3JS8Yu7603yuY1_(l(g+}BQ;6z0#(x^2lipfGrFs`E}S zulnMTOYW=uoj6zYd$~uU2yB0MHf|MKeYdH|GU42`zWzb0PrSN2tJaq15|nSx25jAe z$5P2(R3U4bK7gk}XZH7fGmA5QTOKYysl8ZreS{VgnBo2{KOu0B$e|K~hYR>ioHg$J zIc4lkh**q>)+@ZSrG2Ketg;8oyQy030Gxyqm;kUd*_Y9fWl&_@xjY ztD}p#g$z;{Lx1cFEaUY}`l60{Ni0FP*nfo9HR`80U@*K+rKqV! zL-uZ`Ddqaw8~bT%+ebb|^A3g_da_hKz}#GB&@Wi0!DluLS9pgHkdHrPcRqWvYZ2+G z{VT1mi2(hcZbCd++`d$gE`92i^g;V-r0x>Fvx?PwEwwB&N*KyX$0Y&5jqjrq)sv)e z0QTxk#(xOGKLq!G4Z*C8|9K$$-;2M^|L$ca;+0@V5WXZ8^A?0{nitDzXj6SFP%fvQmd^RPUEKFy8SHYyM_+$5yx6z9d1hH2MDx@EGKL$OjR&KlSD^D;lRWkqHgKC_QE;;ike)%YN=QpfJ;u>5U8`_egrFlT|I&u+~i z+aiO`U?toli=H)P_{eGUoOLv(z0Hc1X2fMB$&yoC=;;z4#Wx?+8Dizw!Fso$JzXqm z9k%7SsZ~K}_sl4{O-2pVHtyE+v;xDqPy=}hsp~Nx-e{9I%^9!rqEwfhxn!^M%4g| zmwseSyS5wjEdyw#nf%+0msD*OPn`~d3ynk%`}pbw0Pf~q;UfcW43@@3ALV@drfnbu zT3OKV+n|>XPKP2CC~)=$sN@cyr3?rVK-z6~u3Ua*FYfk$W1jCQ+fl zQr}e9Tp8^u&scr4C|F;-nFufFf-|Mty-8!V_x9(?0|$bzH zv*pJfl-!Q?_>bYmqYp^}0Dbq__S_3w_~wb?0z7E4hLf_%X!{pbX~D>bs-5z|euSu` zeTLsYcx9h!BYy5{wDkIqBK2OY300yST3Ll#OQ^V3DvcH5lV^{++$Hlz3$!< z{F=#=hE2k}`q)x5&2#||?loGiUS+&MhPaN2DSISnNj>Hspb4KZ6u+<1VfJN%Qbbb#kg;x$EGcpG5rWAUN6;MZmk4 zL=`dIG|J8!rrumZw;;!gheCNbgdE7ElHaaUtdDR^l!k~EytEzd9QFjN*vc4Rl0y7& z=hWIw_=nxTu9nN|)9lkRdto8Z{c}!-4 zaY8!V%S^Ph<`-!|QaJDWVkzZ>@Ex+Pma1E|c~&*|TaV5*C%#;nL{NN4z$DU4h*HnQ zU#5VVBKv3n=~s% zTd;cOTq1`JfJIsw3?;?svqtjtjWx@9N? zK~j+KB?jdmh0KV^6Estb-z?$^57;(eg z3c@QplNx--GSds6xQGbxD@ck%fm&tgL`f+tL}R2$WvutlWXR9m3V^NCSDP{1<8}M>m+it3 zGYMwgQIZL%H=6tdB54vbUA%@0*;7t5zi&zr$Z*n30Bp5J0I*0;yDwH&;bCWx0SpGf zunwcbPshao1P6WqB?inOTmhJICA89A4)*t|CqNZyz8<3uLqUq=oG&A~)>O(WwvCP> zB8-<;V-*@ZMY$swr%Zp$z8)95YLE)Ei-yvzjc|VmHVbqbvESBT0UV)#aBmJ0SWaMI zM)RT7*t7rxHHPq6I|*f$m1pQPWm0sAV0epR!^+agrY6z-X8mmiN-v20ZJ%#oB=Ops z7`eEbxzp9r(c#&0wdVll!ARyMP?MsPO!W#9vP&Zc2;}`6SHF5alawPYH&Zt4z{*O7 zEyhQ~7M!MlOY+v1UJZhai@TyWn1c^6Zn2e!dqy}dzTSiV=lj*&DE}SX<1X#`~EQ3+q(1R(b?PH^VQ{=>={BC z1F(Il@ueq3TkaG?s1i5zmvG7rIi0k;#$F^7QlTX@H`ncXI?sk}j#IMewZ=gZ>8`> z|H13V?p`h49pc0@u>U1RV%M;cXNs0VC>}^UPDzvj)Xb~y#2)!4?Q#<6X+H%1kIeq9 zX@y5PWwhx${-zGLe!^b^VHl;PlyJ{JD7jDo0?>-FOe@)FIrR33`uzRT)1wiBiD7>j zs8oT6-vJ4~M4Izh9cn#k_NBWj@9bceE?w2jSETSkIz8zYK~EIeXL#rmN@Wd8v9yYuBDL?38cCwT0%N zg`SOXE#4oe&eWamRHDRwlsp!b(;yxTi^wnL2ph@6cX;@jT@n{ReCGbx>WV{D`#C*@ zr~;iqq^zt(f+MJmHrt^Zh=F{_z3P=l<3c_^zxr|6yQde>#nlT|1IpNun%JwBFCtW# zVu02j0~h#e%*N}#uq9Z3{|8={?X-!R2-6}QT8E-APpt{JqseqwZNWx!+*`n1U`b<% zEFQ;N#^l?nMpJlcm8%z&sYrH;;vCHL$q%vcLrWArWizl4KBA9{iWj;C18P8)*%aiP zq!BrT_v!?CT%mO<9IgUB46cr(v(2OF%ds~6)5f75t|D|sSqeWTj#JWd8c-Ib^jSZG z1cka0J|n$YeGSq?cxiy126)y%%1}~nA?3&?s?wl(gOX614_tk#g)Gt0v=@lI7%nZn&tndy7bn|9pv;E-_S5iMd^7C!^&yN@t1f-Mk%W)fmsHlf>(4A)lSDL3%77>1%Jd0URnE-t7LiZ^{&9n6-?V3Uwix$vI#e+nmtFjS--9~C zJE^+Evx}*3{#dSmE&M}91}i;oktn$C3_qsdDLgo`*F18r5pV4%(7;SIJIok>3(I*002% zmp}Fq55V@h#SIKZ0sX0^LT7)fsa)&$5O*IA_i=B3+rRM6m`oAcYn6aPB5lluj7QG< zY4pL*V^$)Q_@#S{_T3`ahVk%Rvn6IjiRwA;{my1nT>Z-Uf+eIm|I^NcFz-Jmv$O(zO+eT};Z)2R{dox9`J& z2*qBv1_n}?rMtRsUi+E=c)5WV~T zZ4iOlDnkr1g5ub4T3AX#yMQM2sg<*^;HUW?IZ*#%g)${AWq+V#!yF^$kSau&>5Jk-2gkS(VqsJ zwg0zYL@G&{i9ipz9{U*KJ#g{bs0$(uk&$DZo0L@7!)1~Bs)OPrXP&swLiGmiF2PNaIQ|0u%K9$j$^G% zg4!qbJUaK3LOZbjbGFu$W-NT$oB-M`OM~NYObOU?v7zfYJqvS#Y*vI9XF8BpDRPjD z?WRR}b~h@3(?$S|O2M8?BuM8zPW5Jdk?$PbVG#L4qOhYi{pYNsLJN33cO@cN0E!6E zi$&ljszO%5Z(lI1M5sy;)W7*<;~^#dIa3`=S$Zefbu8T zi%iS4%Y{FX(luJbPDb)XU$`k}HmS5&SD_;GWztijCJ1Fy=sUk7wU99>UxQ0L6 zPxnvmJaufTJwCLJ4wRt!_UuG50nRALJnlt1*EFLOY|N&_bRk~iPX)}dDE58n=RPlX zMl3q~B51k!O&{0eqyenF)%c~}o2XSgI8#RQ0+AcWSk|6+^5xhlmvf0&oO0f1n~q- zLmN=?5A-GEoJXMs7z`5HJ=J)KD7=Db1bSFGecnu8Cf{7<0?Q`1tk^qSSF`xz1!c8a_t>rl{o^dg7H>vtg^-{3%%>~jm z7^1PrSyWXiRGP#&gc)#vyv^MJ@zS@NX|(45 zZJ=wb^WTil)A*I}7fD3+Fx5E45BHS)Jc+%b&hjh~I!-NJt>@-<=Vlpm=dg$04ToDS zq^hL9Z(>O2*bmzG7LtKY$B}6|_Umuji26%yd3uvB)mb9yATr`*Q)&BT6M168$1~O? zRVa|uAItO1U+!$Tkzpo}IOERBY(8jK{V{L*GyL-zDX*qka3@ISP&|7wleLDh)Pv=Q zN%4#xPN3dCPPxXD!OioefAbI0Vk!=X=@S57FC0d-f}0I!R^I4Yygoj5`;S;H1_15neo$OVo3!0E5{YXWeg|T2 z%6*3LMFI3bsazenSRM9aoP@+Sdg-2(em-hbwhY*<)@bBgbNBuMPA@1VXt?2$1-*Y zgS%IpZhdwJxN;J0sS5@W_g!fHSc?uk3)yJF`OkxR;$Eal#2Lqj#hny4`@hvYnX;qK zzljrff;@w!2>c)9f0#!bw=(Xk9X?Ct!}E?5Af}1i@95af8*=cP)Ba6)cit=Yyo(ZuE!7&|vr=F!gB8f$i4RafI;PrVAN#XBKrD~mE&96EaoK9I4y3|@Gn21+@9cH&`6?`-C!ix1 zfIzB}Bm#@~uaCa1BPyO~uVp@<`|Ez~hclvz?sqDV;GR9cNY%b-F3MDkm5812PXd0* zaiARyHYg}MUrIX2Ix7O7`OboPnhlT8u>{T~tm<3B(VZ2vXC<==2$-c*%|`Jsk&9;*>Fg=kYEB*63KJ;gRj6sn~63wcO5 z=IoFp0Vr9eO?FpD$@n9S)A2Tp59)QhGusX^1DSEdn(2Dr2W;u>uB4fIJk2cmSDFCo zMGrL{t@LC>25TZ%o)0t0*&*LY;c%ca%QCr?Rv4W>2$V@lRXzfbVf`^wC2?-D*B|RvmV4@^D z5eW;OvNeF*17V68Nzs?u)5$&%t~kLyN+UK;DaoIy$KL~TQhhhOn!G3~Wrq1PN-dpP zFz^j%kTSn0Kz3|@l7Mqlf%F_Y2j&Qd<=vlD6lS~AYvb$3GfD;zp3cL#nC1eop*(K(KBO! z0gb!6zaX&88qm=Ox**Ev1SungCJDN=V@bv7Bz@)+7cH=|48Ix9B7LVn9#S#p(HByQ zZexatcih@m{z^7*t_5iLi_`Q|bE7oroQpbrt-xSEuEdXKHy3i|T}2?;8m@Bm*JD1= z;X~RF(DQOfJ)@DTz|8tM>Z7B=q|n3-jcAJ!q2d#dBWf0rr^zijUO;kbJvcp+`A#X| zYWx1J8}#*SD3J_FgF|dZf$7*bQCd2%mtVKdqo>oat+bLYV)_?xOEh5+O9vg{X1}Pj zR$X}-Wqo=uKQd#x8fKmdu7`qiY`kW66?<`W_izZ?hr!cgcDA&C^5XAq*1B!!?ZXakdIJjqAwGmP`ojP*G9QC*R2=at)Z7#A*31QO-O604%8{{?1G&_ z^|zlE)pXP?HM@E5o1nLx`Ab#D_v+a1^%brJ2xr{aI83R_O?YR{UK74;;y%mCxRlyq zVS*5_Y-wZ9doCtRvn&lZFTM;60yTzZV=4#lTtvSQXow4GDE=o7;t;|G;#h^Rr|m-D zQv_+`Qs~;>!fvKBiGJP#uO?wl$lD4@se|uYM8FMjvh>p>=REhd8VbKd^Ary$A1~lG zj5Ni$h+Cj+!Cyx&h*?2Wb56tNH}WXigBKmNs|&Elxw994yH>D0F#b-#U3gM3j)|As zE%nJ+*fEd7h>n;>-uqRg0x5d%lodWX;zi#ucx8%1feq$7ko$4KoGR>*vcmQ0iF56oq>;}l~a*Gl_3$!GXdFuKE!!z00XhmlRD0j%Wn^gZl?7alGgW4aM!LA~(ALC2fs2B#-)FK=a%qjO4R`h)V|6niX^L%bPj|Gackh5fFM)IT&kS{ zFnMD$iJh##6jn=OFgXJawdgc1Tfb9bL64?yq+cs!1)!3B$R&sqwQ>87d_BObDxl$x zkWi%tyP}?4DF*I|N;}{h6oz}cQJLE&M;vCaiPpp&jDr=Lq28)Rgp35Els4_%Rbij=~XXc{B8Av)}gDbkzPp^2naRhBFN-dV-kTHuo2+Chv|M)hCI4 z5jCHWy5DR^wLQTqq)Z5Ow%gr*8ehNO$+?pYY7Jv=GwTb?ia1J`lX%cBqQEn=b+xww zO{e>wIMG6PFy}3&Cuh97{J0fVx)Iw;9oZYTc{c%U-^U*p)9W{7IN;ZHeSGkm=v}+F z1C2|P|9EZe;#Y59vaM$`TwL89A-jyQjG4R}JfEIDy-i-tlSs|y|GC=I>G--md$!Ax zhW3oY?7&j8`a~7=^oE77;um|_y}N@7Jx+kbBApksrTIn zQCqfkU7i;|U3{`#@3#HJReUR`6MG~U*0H|XGlpMHx1Dx+ zeb1PD`Z#6mkyFV2oeCE^$8?)^CNN{|)QjD)C%lmc6VA6V2;ZoL ze*?2@Sa-K=+YEga(Q?l!W#ak~fz7nt6(3Bgw`ksmFm@o^aHc8LU6>9_<57Z%9Ub3h zTi2^8pSFVANsRx5`Ce8q+cgAE z9;5QNoMFiaW|Uwcr*k*E`(8h;Ul#%=g=0nQmph;j0?h{Vx*C>P7(aWo;uqHb2C^Q= zLc-3`K_#?YZ&<-meTOQF3ad;oN7)TM;`c8TI7}H|9tAWa@)M+IYEKv zD&)=*W7*>tY1?l#6W`u9m)wePUR~d#_0;M_wOw34s@#v;M~s3YVKR_y#Ni$WD{5T| z^_uVCI(j<9cp+x9rvdKQ-3<+#E`vcFA|G7cq**5~V87!4#S_o9n?Qgwx~SC>1Yr_> zFOxbD>njZt#>J2*MDny&qOx#zXLD5dm_wjnaELDy$clWO#|_CKXzrL21alZ6WwY7~ z5(WehU7!l#iv`~3cGu9`>v3MgE5`{1i(j#w3<@YH;eb))G{QSYSV54lqGBy7%>oxL z!2~GqYNWgHni8F9C z+p*EF*k~m+ph4x8z+t|g4(jjVU*?E>fH>pmew;#(l5dqHirLPF4&w|}Csi00LxhG5 z7RNCNB^E)12A^(Pl8B77rtTX{yB4PqA;R5B=8TFlZaFmDPJpye{F~aMWR)oA34hi?)IRE}0)Y08 zkt~Oz_*%;7XvPrud8GHZUtE|)M0o%@EF))S4xXTQ-}2|nWNbdA2RI`+dtJ50-U#(j zg~eepssW)P=|HNJGAfhujG4epIoO8meVot~m(B^oDi(6X#f}5N>V?xV9WeHqP&y%YP&z^Cg|RX6K|gl^>V*t!6?*O5f2l+tR9)d{6OHp{LQ;*vm{vFPgLc88Q`m;kJNwmIUVJ2 z@*Tokdr=NyPW(+_1skRqm_X@(tC!4;qVJzTc~VJH0rU1kG%?v>O<{#1F2{F-G%4Ca zO;Lg3;#s7P#Noe>KSPs1*z=&WzvDe6IZ}50J22CDqwGq!TYAL>iG|;TdI3irF-iEl zS3z@4iM5qD&<+|Bes4)4@m6p{y05>*8BWUMkzYgN_tw7_T?_{Rm6`>z06#lk-1Wh5tLLFrx`nIZLLAG_qZ|hJc=~cM}q8WAk#5mII`D z=j!ST#PvTe@{=3q?JFX=gmlu;(Kk@pK-Uxib z^+g?V$@K+7$pHkY;87bek_JH3g^rA^Dh8emOmylG=h})rV8JAe%%fitz%M0lZY=_w z)Yz!X^32q*QegC*?Q8%^;j$P3Ft)WAGcqh+|E@|(0jLuru!gS~07*k;ZclJaZ)$?f z!Y_XQt~B-2bd5R8HFbsA4_in~%~bYH^dbZlTq$U*G&p zAN8mJg?~T!`MS8U*05&*qi{-3zWQaxCJ@Z5;aPw<4#LOCw{;yO@t{)s30Y*UMe`0BU2Rkzt zfF=VS0|O&~;jf>6e`$Y=!pO$j()EwK%*Sv6^a4`f1Vn_t{0}Pnx3i$2jSJuh1Avy1 zogKi+zzN`BW(9csXHq$Rv;QK+@F!5*+Sms0FY-o?w*P9t>7T*_Q2s-BRDl0XC1d08 zF+%|5pIy^pU}Z4;_{I1?$mkyq|0nhQ75jG?{5|2nWb`lT{KNKd_52?r|C@~dC7r)~ z{=0hq3Zc{bsPli*&0jwMZ6ajH5FLe1!aWPgUSQiT_WD6#p(%aR>bmRsz;0mj7NdvllgU0UF7f zIT)G(jP)(;f&W}r{;L^FGi#unjlJ1l7v;y1U}gAkHYHOtLknx5y*=Q+Oh9X+|3*OM zgT0ZNwF!WUl?|Y8XQ%H9$MA8OnOIo?KNtaKADLVLK$nl&^mNuX4j&-^TSo_vj|tkr z{dJ1iSU-;LUrYZ)Yyf(}KZqSbFZ2g-0O*DPAWi_i$iERg1At!i4`Kw+fBS=&0rcX3 z&_@NSKj@=^^dIz5LFNzos37}q#PLxr0p9254;e);5zY*(4GD927 zk4^s93Jc3$D^^y2>N7HYv}p8i$oxUo$j0)o%kz)N2Mgezq#qu@|0v4#m;Jlr$NBpc z@-ZpnKOrACH{0)8#=MQ7Hk11IGrT9Pgk5O9vfgf)G{hv}FuLr%gqm{v5uYk$l z7%+Z}!sZXhj}$i6z`vP4`m+6F{zz%7ZwIvgkG*AK{IAvj+*y{7W^93WW;RBDOZPFf z?|(Rb%;&qK&BtSH@VA}#_>YJFZ$o7KApWOGmXDFxf84aDe{=Y#^QY>^BSG(AY6tw= z)_st6aJKndz()?pKLY&7|BnmP-q6PG@11{4+v#ucV=~TvAk#-um%qV}s;+-XeuTOK z?fzNvKW-sIN4t+XIsD^o{x|DazyMAf&Yv}etwk=m*_8*m^0MD7pKmu+D~3)NiN%Gi}9!`uVH?}WzO2EAJ23<>+- zOXSmxvc{k=!HbEQ?m@x#Nz*S6@Q62qnm%iO#$L8>g2%yK@vX`rNlhx&#DUxq9^bO- zyJ7T$Y#!*41KLM367_<*le+JjUL&pD3bZDDK@`(RiUsUS`RSx4ev)5;=fRlN^ywuv zFeHny6cTDbWc;as6F+p4t4CbW1pFK#yVs54sxH_=gfkSvMV?B$WtsXqaiaYLTRhz; zBNY>$h?O@kN%V3?R8JyMJl@2&5KBX-w54^_Lp5KMx3@BXu|%QjS=BCgO|3G2lMYvC zp@EgNxYQvC43p6ZF}sR+PbRyPO+)yq1MrsjFrJLRute~d@)C{1N^v)n$mSVxhq(O; z$)=(e7Mfd*xsvDDSx=0~2~mvL0tyTF6@zwSrs=ncK!Alpyu+!1Y%_jj->xYwMjY-# zidtQvp}bHLRUudrY5$Wpii-hkyd`@+3}zWkLhbC-=ob}>F=Dz`u=->zeJtE!9KWQ% zWrRI&HEY)jUPBoOy_qm+M)N0qYeh1ms7;@($EBaa3MejzJ)39g)ZbH%us+2whisu*Jv5QncL*kmIq12Vd#Mw6G2=uZiYJL7Jy>LG6=^Bil<&>9tnz%GZ0u(n2yxN##1 zPwJ+)jCXiBuNgZplK*f$MXa$dWU>EBueVxyG9|!o4dI`K4o=l5_@_@zS~#_?=fBco068s|>pgHzOFWXj^9MQ~R}I;6-3F74y%Gy7Dg>Gt~;09Cs&ZOtXBn6@oWBOFT~LzX_pn zP=B_CV?y~5dC;MDljajIgf50}7F;VcGI(Y6j3tJjit$R1tzmJ*4L88sV|!{g^@+j1 zfW3%ZSCb-82{1nxxLtH|kYHFrvkot?F+H9qB6gnS@zU7B;cGunx#o1F7L2H2FVL(- z?a@As7{x2Ovhl2SNMR6892Ms*@Z!$QJUb=dW=U#7hqpV~rJD&QnDPpc^@lWGt~Up@ z7Q{j_zgHgANH86>1r@OwfT-H!BXaMC_4)!oO#;F_QBQPI3yG*Umi7a@vLaa4&+iFk z=Ui;EknLm*a2`bLy;mA@YXGByHHtn~&^%I~^ zLs(KqmhYKHrYN0O*vC4`0W*}#E;S6A3-4>j)3HMD8P^HaKuE2X+86j1mj>AD;OeXd zgvnXlO75rTH)noW&Ahp+-+G>8tBfphXO-4eo56W&9hGhfk=)ywc?3sj;*3sOn_-0R z&hxnGTTn)~9q8MQkjXYM+(rqzE;=eP8d4r>*5pvG_Owzx&tvG~43hL2y>oqz*oQ>O z-Tee|CF+5f(pc?YmwA2}>Y8ctZdpZaJ26pNE`u8WAS|rKs7Xd4ad<{k)Xmt=g5S)_ zQTw>hU}`^b-5MX zS$7t!bapFtEc|G$Wx6Xu_BmO5-^m^eNw}5$N#%ej6GoS26o~%K+L2qO9L|rY`a)IZ ztJ+2YsAObw1qUI4i63NqAxXm ztGH3y{`9#I?KmeBu_zx74IEX=<-+VLyOJT#1*vK03P=2+qAJ;MhX>v%ewy4tcK}?_;2#=?KPy?>K`P zG&9C@r3jI_TvXBU7h#jRV(JZv@;28;PtnmA(v0X(O0LDdC}X;7b2DjLSuaeBO)8La ziOu{d_1j{4$mz>BIMO*SjB$i49^UVrjKu@e5=9uiZfwn26Pk^xJ#0WIWuXj*nsZW= zDIr~S#6J<9fy^77o@#;G2cQ#;yTT+~oJYO%Kr6*Kbj74dpVA2vO#s@ zgd^R6tZK2N2M~5y@|HIcN~~8OMNPWT`CiC!$ND-+x0{{uL7QgYf#~bff7S9QseW={ z{;B=?ThC?oxz6WG)2{XWD~fb#y`mgW%__IAsv~iW>QY_Z{zJy-$|fF(wAO?2{Y@e% zY{&@l;hpKm>S7Gv_R+j@)$dW8sRvCFBq|Hley=x*LNEt@ah^b8|dW45lC7@t&6{MATbeo_5etgX(AWX}$&3e1jd_ zoMm+^ylV^aO3|I*NDH8ie?Jq(26gk+u5~q%H*Bs4){{_$S~5o-(`3TIdBArV_h#w^ z)@3AkW{QH>boo)G^Q~qasl0bZ-ngN0jB`AgSJ|j45XI2c`sflatm>Y)CqU=nbM*`U z7s1*j_}F`y5}miqtK4ESyvTTI;uS9yATDtABe7m4K>=cNdyuGmSuWNEP4ABA zYIOeri_Pz@G|q0>Ou#H^-CAR67lg4#6sbmfN+^dx2P?!p(Rtn#^gS!OVV0TEI&$Te06bDGfu&NfkxN5E+ihw}#{u$4~qCV3%Q?qzarO>N+O5#(qt=xL4!N z3rQwRo`pZQDmQ4hv(ZGxakI}JrQcQxmC-1GqaEXbN&BX>y;6dIGnTOf;ywr*7RJ1E9_jN8wimnOTU3C`_U zie8B=KZ&qR=Y*`uRu8MljRFDx&EB697MMkQ^+n8t!d7>$hLg;`L7%H~zGhMia1paa zC?Ly-SL4ymLa*E&a!AMoC-^T{Ay86V!o11wBmLfcDhNWMRMt_EXAudd#E;0*HnG@C zZQo8t8dr_5P#((e5<+*~4Nr}w67Z-?qFv)ex;37Kx8i^;ybcenM`xGc?Na)tj6R-< zwH0^%#5gtQ&hbk*uH5uoQ<2=ffMd1I8P5sQ0GWaZW6ye-E+Rktwli&Tbcvu&{h12@}qtAFI;C za9-hq*lc3TH`>_?Cp3}Oes#-T`z>&GPfyYIk0Cctr1BGAjw00nZN!&uJk{IXzA#{f zTQ@w94r_j&i7{6Tnmrd;ZzeddF8sVWmcLK?90!L>dNbE1*Qj@B7^@%DNefBtOUoG@N)x7;-HaK=xt88J6rtP9uj?T$vH#OU+|NGV8br zxY)>09N53I3?)>7{zaQtAK>fYiUoHF1Fmu^ns?wR&D~U^*;GtL$wmaOP>4z5_3EZ} zjNrz(Uh?j66R6de{>*TzHNSrc8yz&HCqvI#dy#q$GsHHv!bXC4&6YCZd1SOi3md$c zf~w1WrauGsxCMR#TAum%J|P*tG;ZfvEv_Z}no{9O90Eqfn0632wJj0)bGT7PxeNV- z*m~tjuTp4W#vb*_OyfEVeBl)XUYo~d%+{P_c^tQ{noD|{j1U4K9V~~jW?}({bv$~S zqjG=9DpNL6p(Z0giow)(E90l1q}B_9p&0SBXTNmqDu(*YAV$9^ldou35tO7 zB+|t}18iNiDQ?dxbYwQaGdd>-iQ&=zQ}7#x6(re)ZY^G-Y)_s0BUFH_-1^?Vb(`ix z-GPT(|!z4sR@0Dbvslm1|&#KS=DxHkF_x z`LK8}sJL8>w7mFO)Ax3=p!0t|t<{<7fH zVF>JITeQ#O=RX^%3#!?a<3UCWR-%1LD|7w4T&qm??*fQLBU%eBH?$%2_bSzcfr3`IK+e)<-oB*QbZfp z%>uyq$t?EC$AH?AnK(+O2!cF z0izJn%A@0KPuHAUzl(x%5HRDJBTrMNu&64psmy77i{ES=se7VOZ3zo`0hOp2SbX}q zdXQT&X9y6VzvDqmq(Nr8gNln>27Fs-f_%@CULAgP0A=S0d{2Fo3*&M`QDwAzyLY=G#_0r zH(62UVBX+~_Z>>3Cx`Na`FeGk@=}>c%}zX7lnriP4_3;OSJ9g-%S&1l`~4)@v^a0?deXbBZX#y49kJ0-^0-g*>1=vd?}*QZ zyz6frQ&jj~uxry`28|f*-Np*zdb;8>v#nbOFl7cp38D*4B~D0Y?|5Js`C3{&*_NyA z*9nv^EH^v9`}inj)gg^gpXajHwQV|D6RtQN&mtx!ZAW->x2@xx#6M$zm2zn-QIXzu zXv(sX_xEqn!Ju=FwSBc}*_=AHm`a>}?t#PCGun>-0rH7qtGDVULej_4mjCoa``%CR zp%~@R#VPJ(dfWnyOB|SKe&pV78=4~($C1}yV)e<32inB}vONzKfEqfxyiXpCKtZj# zgFXkthAr!FW;YW`uI{Cx_;^KN=#uqLLRmcA(xP!&c2 zhng2haeFJsa;_X{BEGq4S`aAK#VxL+7VW%un+u+KI~n5Y)!;a)-&#bXRI)|xg8 z7HG?#%bN{`%zBYD=1lHXI>b#(wn`FtekhA=0~1#e#TzBJ*l4Nl7wEd-uCJ-gyrngQ zq%K%pKVvd9j((fd`(}q%AaJ1oe)HbdH}84CuNlmGIGt#XkC7;0BioerQ^p~33ZCej z{jAL;$YszK;x=>y))QP{KB$w5GoPDFZ-?X4>z2&ns;snmAtYN{gz;NR(KrWb<;4RS zEljg;lV>wqAO{mWpSBjS{QSz2#F|)Zr3tf^e#3Q5z0v@(qV2Zoj9`he0)OLG8-k1r zr^0XNYtJP|@GXGotz}_Yuro+!8j;+4reH!GjNO|^#FYhPc?J@W-N`k4acUy39}g%i z3!mNB^Bx78WHz$H%c~KLXW^tN$#hv*e#Gb?Rv4A)-*|J!DwammcU5$V)Z*Z>t7C3n zCj^~AB|I4)`nh|TX(I6Oj%`8i zdGcFNq0M3V0%BT0#dyQ_;8V;8ZGKWuj0JLRYPG%1laoG&iT{wzKq#h%>JJRT80-_( zI@Ml`A|s1BFNk!-{NAZibI`pP*F4BPMZp}s7qVZM&hehU$XA9-DzuIz9QGA6hpEhM zgeel7&8H=b8wTaGV8TMnHwf0n2?fNdf=9nZS$rrrc{2%};hsG7TmKdW=*;#qZ+Jf3 zjaDwFwj}MJI&E<;u#VvkX?EcL`oT7rC*73iwcE6pb6{BxbesYeP>siWI1FVi^C*Fi4aS|EYV;Y4fhyp z=a4C;r5~W13Bjw24^Mot##wiHgOwjM+rmNE>X%Dqo4{t_PPXUkA~OVHyca7FrN7hM z1fYoo;RPDqIfSGz+w8LDa24_F-9)uWVtUi5u3;P~@SN4ef0MjIY`H}fD+e*l=M0#S z^QrY~pvQED66T^(N1n%eud{)Yz%)kSs{|7X($c!<4M$!)Jk?2^rg+xNe+a6%lM_es zFbIk6paKBfsY!_FitqsPYMDd5H@O};bAxwo%(S2+Q;IzT!@$l~ezwYcwen@K~ zP5oro&%TYuT3b-(^0fTZJqaYvHBQ-*i|y*g*taQ=JN>;JypR?PqSV!;AF|#)dwi-R-l^UlSk6g-whQB>wIgHZ zus-nO!7ddBgJ6=xlBA&wtsrPBW#0E<-iX;=Kdy5WjN1+}mW{A|4=2FF(-0j6iJ9;g zI#v9|8+CHRq6`vboQ+=A2TpSr^O58@Ny@DsT7io@q+>4CGDhoM%GKDm)SU3=*(ee;?cY zO5Qcj0G<|@pB$wFnB(F9cEGV<^{{Gdq)iLCo7(i7MBNu=0?pm&UGsY-#2tft2cn(Yfyg)?{u7Yu=>eHwTxI}G&L-PAJHIXW3zmDULN$8d z3~MXV=wLR7q=6jCM~1+J!ur|(c@VTIi(MHwbO&DA#$}i*<}Xa@ru-;Cp%y!TfosDb zPQAhNQykq9*XuON5W_h;b8pL{rzN@EUZ8j=uV+GrR#*dhE{kfPYbg2EsGn<+0_!$F zw>;RbnrJ5M)mLFr24biI!Qm`uWBixEnX`qJd3Z^D<9kP&9!~`F0BdmxYB5Njg3$$` z4ZhHTE&hC}s-(S1RYtaaQ=*1u@BO^!K+ zQQ=?>QIL@_0~TaXzN_itU@w)eT2|;RT#qi)ml25GJCCYRvp+Dz(wSl)jBnYr4IW1H zBA^?CWvt5xaEoVH>p{{{`m#fw#H9skxhJ3)g^p=Tb1vt19?70iqN7~^w`dKnbb zFPq)(@2^vWYZa;IDcLDf5ObQ9<5yqLb+TX>yKTsy*q$;#naIJ0!CBLleOGSS=t@C< z^KJ%a-vRO7S4Ns!3f}d!(PSFKnPVaFr+-0jbv_1Z4-OVD@@)Bug;peqfm;7?0rv>& zT3f9&)(0Vdxe6#;`eLDw4xN^I(fo<;{EI4nK$dkg93fr`f-#_qk`3NEjW(JV#8E^9 zX-IE4M#I0oUa)E@CkkenGKD<4E@a9=1Ld*jMuOsoy;6 zI%9F_ilEg{70fCTyy3*!vg6HYR)VrC8#PxDM}F?{fKNc(4>sP=#s_%FXI^LfeZVIj zmYxZ>YCh;%58We6gFSVxjlYM8#iatX{Z`;r9$^F+lL$A~kT1;*>nK>zoTV{wr0|)A zA-p68ME93XU-)=v?fK_7h&s(j`cJBwUYSYt6v@yWUxY#RahFRt2ANG6!@d@M?SPl@ zIN}&X{)P=Kyd2aL6&6ubp(Hv8S5L(l4k|=87BunWO>XNQwJxi<+T~v4E0!7sXyjx! z=vTAi)-rFlfx0NPa^)hwt1i&OYh0&**;0f~eW#9fyaV=KTZ6w@3VekRnu#!Ovegd( zCD8xI0$)b2y~auj+W(fHaFG4PLP}GWig_WBLu$%_t-feciCMo_2rw0Kx>Ob&=f~~_ zS(b(jRr$_Uy)TvGsK$us3vUKdt5ULPFOZ=gT#(?}NynOSVF6apWQV0A2G?fDhMwdJ zd^yqcx2jgwc6!4P7E5sVAg*pr=U`Kv10r9|TYu zKa5+16{uryt=ySdFCS*bv1OWLLLJ>OF)o`ku+Zt0mEON4@#+sN4S|%%FUG)?w`1<1 z^@VuF?m{u<)cNvx6iJg`I!ngur<;(xARTRRbHYLt2u|L4v*j1&4XO-HpT$^I(b0Ff zg2i-wFZrgq(U!p2)d@2dbbcNt{yxY6Uj&e zuF7jOBJy8P8@g?+ZiY%2z1x#O#p)vLdoz`meo<+dCip%WP*LQtLmU7`-nLcK^CBOR zN5WYd?|i17CxOn1aw+MiuT3WVT4UkCfwV5s4B}dqjY>7;<0fFuLKe|7toh8@lp1*^ zk3Ou^n)SFMeh8%EM?L>%cu#_({ zPpR8rlA-ZX_9@>ndx2;~pA%K1U{|A8%Q90zeQ4!ZS4fI$;`Wx=(6@@3Cd`BMD>V~e z7EMcke%<}lFSodi;QcQ33mbQw4rh#W>GDyY_Qzj-?QGlNFzEfZ5zLG*@MZe;79)F% z)FE$%fL_pGvIz=@q}1>}hb5 ziWCb$O#9rAya=ZL3GL|2P&J?0e3B`7+GHZz-zDVzGEe$ zMa_c2_r^VT{#SUl-=ZF(J+6}Bfk)m6Bv^NXowDx1vwfo*BBD0pr8#M$)wGM4J-zUE;N>s;fkTF%^Ddck1)ylsgh6 zhaKaivN$_fdD+bHm!q+LkBhlzxTx)#!AZ7z@xRVPI%nx*dVzH60b-p2K! z`1YNilXL>q)9lOR`DM!@IJ4Xi$J`~`FY27oF0`Um*Xb%2|bx_UQ?;SuZ>)dMI~6 zCd#&$uw~^_N+pcS9lCm2NxfZPxrMT+`Ci*=YpyERP)#G|RLAG9TE3Y{R2TUxDRJ@# zF;7tk4+?pJ zz+Cb%5`%fnfLK2JFRywtZJZ2L2-+VsFZvwzf}hFI4Gvm1L_FSGUny8q2#AsW`^_SJ z*28FHvv-3>5>w0Ql#d1y-TQjrJ|~E!x)c#fTCUM7;@pE8`@8OgrkXcl_xxU6$7s(k z-W(~_4vUKPHgnhChzjDR-IpN-2Q4qNu;sJJ@NqQ1TPIg^QFo#VFH3B12s5gt$UKSc z`f70d)4;iFE1ywuOA}4>jLHWm^577)A0DEaT&IV}KmG;{6rQn>=1uFihexT`rI4mS zPp7Ab=|48IQazU0H|g#Ygp>s<$$b zll`Kod2?IrWLD2t?um)6>hUdC)nu<{Nu!$Ddi~5*M*(G*=&bgOkcgK-Sv7`qpq{{7 z7{;r$-%_W8#>G5MNaQ!9t5vd$p_e#@1Z%dGQraN-0YiOm-fF_j;ngBx0aOiSHKoJc zT8bj#f!!(=J-7Fu2Oh2Pb*9g_k(J6X()-C(gHo*dkC1UbgsYWJIFj_)LSvp0STBvg z&QurrKO@*C(g)t#76~rAX<77TnMBqrF+5Es=iATtits*G;~ z{Q?u7IqZ%i7+)EP#B_Lli?9N1c6~Ms^;%F*j~3+)3yRIw4N=C4B`rZ7Z|`yVV;xur ze0j=5|ph1NRpA}`;bS|vcZ4)nr{cRUKi;{gAOmXX%1{c1cH#&(53sxC! zD5om=y^x>V+6v<+1F`XgACG@z;~4CWcs9T8ZT*<*dVA-fFKnv%rDs2TZ>(iVCrvCI zdwrcZJaz0 z-Znf_SE?`R+YDX|MAjKy#1Y~26Os@lqY6y2l2+UOUH}T5-onNY0 z8;9sLQTH3Hch?@eObNR9^|5xcIT@Rx9(1o6`PUfy>_qkds~}YJ-g11MadUjmF;Z<-7?Wm0^n;J#0m7rO6^T zHrkL&1Zu!PQz1di=1U=*{YtjZRIEhu{_Q;fvg*(3C(S0Sf+356kwSrVb^a(_g@rlZrCv~~Iq#f# zfF^JB+hKFJ2jP*Nt4qU~@ZXIcPmbN%B^)vJ2sao{ihV5EULEP~N3U7nKfe7HJxtWx zWL+sXv!Ih1QdisM##2;!88;gvybvb@jr!ghGgCoMV;8qb!AIg=*{b)}3tAuq67rdz z$xok>Sm64*L;qCxY)i`;`k`HAQEXd2Hbi!mzx^jV)O1YObaH4?4lcwM(BoHuc1_vMu?JgZkiI$rP$eVmjxg+=8f%I1N8} zH6irPnkNM2*k3)qUJ6@}RWyRErH5YP>Z<3Zd%q&}T-luwW)cd1ww89g)*sle2XD~o z+^SJvy?5~|a9_HImKOUF#z(^vkE~*Dw{(@oQY7~Fi>~S#nrC@yGQ;ZZHlEz*3uKqB za3x~h@&*ab;}SdXmr1UWV=&@J5~e#z1lf@dhV9^*O1$~TFoqb>O z)Y}78RK`ukNyU0Jt@oH;J(|8i?#qB;dNw@iKKC^}uHYn4qscw1JM&Fbzj=!0e~ly0 zaZ92J7yY^BV9B8VYiQM|Mkw3VZ_*{s*w*^4M$3X$qjr(a0fQ8_I|uQCc6cE{#Nn1bVbTXu(_`s%_2RG@{Z_uD)b(>RJZjd`cQ9Dvg45W%nAW)Qx=$Q|rNw7wa}X!nT9mDD#U*XjE(L$MjCff?aeOH82P4zd%nvFWfnqDgXL;rA+Zw zeR^3nt#^oMT}yW?gpM}U8U$>6^6S}W))jAeJ15(qnCI4@n&%8H^Glnq3^M|nukC~%%PDOrN*8%XpC>@o=s;9= zv;44FxBi}4X?{BIsUbFZNCc4d%kEO-O~A*vEjQb2s8@&)K)}mEZAf-8iLM-O59O}{ zMlrTrg&eRvWmNfe)tl5gVF{B?Ki0%+x&)&|MJIIyt8@XC01DOX1(3Ufm!<{^+lMv^T(mYnc45Y(@P}5^&ZAr z>qvUI8ctce&9*gZ_?;-`^njiNY2pQ4-nUAvUrv1r6U%5MJ>qyswO-x7J03zt**&;g zp$!RfI*4jJ24+{9{AIqb!$&f!257lAQ?v}y(pl!YvZ0RPKyEZhJ*BxogG!kP8zNlj zEe~R@6Hv0$$B4B+85f+DHmiLS*!JqD{+_1jD(^bm$-XGjjnjwSwt}#*;QAyEUQ}7{ zX8?#p;tu+um{0HCfXTRJb@uBM8s$0&uG`SFMB4c;RH^UTkTGDchvIGB)kG7uyzW%u z+mJ=LcSQ&bVaF0)i^Ben-HV^%(DK17?+dV@6BPrjsttOh73$gf@pc>>^OY*HZDWd{ z^)v@bP|-$=Uxt%5x?i)HN3qo0ee*kwgU~?`D}4|5`zGXXV>BtE{G!1F{5$MV!Ssy3 z6s0b0U6}&maVP>XUA+j^+soUyudGb`jv$rBG8H;7iudBKZt=jV?PM?nVs?C zYfL%6 zIwExAnt1RY8BwCt1&hJ$u21jzXE+;jkJHPKxe{&a*w){A`VX1VaTW6e{BNwg?a3=6-+>?B-S{h` z_}Q%nuF1Pmh0FB3+T);KC&qo!?%dgk3>X#2OiWa^EJU>+uma!BS6%gu9-Omncy-FJeKB=Zcc-;zhtrsRj&c zX&W0kaaBNYLYa^#w-#$CV%tQt{qj;o#*Xpy;y#to)_!%BwNaC$fk!qALJl9hp8TZ! ztCmWwGjn&ydYYii6k?a zG+eDSpT^_&4Tqi-)@N#$Dop6#0cp{LZ6;@5*j2>(%dnxECZp)|7WYOZR#xVt+xm^o z5ENy~V#Pa0uNf+y=0_>A*I0hi#JdF7v<$L%aW0~59{942zns%d+31g?n6xr8GZIT) zA0+3dY(^9Wxwt+f9@^!73c*=(5}n%{eYj$E4~ms0F8jU!V)W(^YOf~FGWJQg@yN~2 zm1zLOkvcY?z7uq#MbCWz6>Kk=3S}W61z+IDPkL6G=1%$nJf%5uHI&$*Rg99O$? zA}TuW>)>ng;fYeF9;#wSdEho*8{|tmECqjOjD&s}+Sql9nFb*FwW@kIn9y_UgYHK| zhl=*4-?HMZ8lVrnpR%sUxE}1yowe7ANd+l0{Qjndw`q&dTc1AS-Gsw;)WN_E>K3(P z-|B9vh$9uNPDPI!`CT8br$TyJT}*<#E>yY8t+&s(Czo2}NxZ3Q6XW-_C1F-ZuZ_Uo zWAb2EyBkHM3DMT&UU-(oCeQuI#4v}^{3VLmI`i&qFsygqayb1uBB?`LZr{Y;wt5ck zRM$o(C@anE9A@{h%H{J-MiA)u-w=n#&9{V2g4W_3!eo@)K&Ln@jxN8LWhZA#NX1+l zQ;5!RjD@x{0oJ}XVi&HJVjl&VnpZ?z{C2)%X5M59f{fXOJCo0Y?E*gw zS~q=P50Mc6!?<{#J7KR~lEu7;GcnNaldu(g|FhPGPGtQx-sMxIj}1#d__5Gw$uFTq zHd;bYOc=`E=U-0}pg>z{(D(@NIsKR(MCnw5#$#f;3+;3o5jx1vzx+^DdP!$hj%jL} zZmMBVosj2CGX&u(S+ov9_>X}A`dg^*LhN_$TKrE`TMHpn(4S;#$bKQaY4JK|bwQkj zjahlQ>+s%wYAQ2(#t%hyt_ZSLj=negibxYCTd*Wdmt_L}Xk;gvi_X19F2zPHyW;Xz zdV-Va9nP_6^9#o=t5#Ki-#3JW)DM6JrCPj=CKv2j-10>f~{bvuuq-ayU}qE-byT zfQpR0v=!U8f;^@mX}po-8d9;Jpg3Z^BCNzmj~;y%uNO#VR3K1rv$M|@)Q9P>p-$7W zvST>b4@KDLC;rKVA?XCYHY)}*V&LiOHW^EeIWc1aGV3++s}z$P55%L{feS?2dvmu- zqrZVB+%V&!Q{m~0Np28Hu$7pT6jmTbr&Ny`y&Sfq6LLiI9+gn2b?4H{l;QO#`gr%= zJ%0eD66<$AoYyX@!xKTD6Sb5C;8cp|&(-6Zb_4wq?(zD)CLG9SMFB%qu`W06jvMx> zI!PFfHOMr?V`>{OCl1$miJ=Un>AZo!a&%(XY@*AOGFI`P=@odsqXPmmW|U{&?9k|o zA7QGh1pc+5brc44xN2Z9UGPccr?Hz_90cxhIK^!qN}Mijk0) zJ8=bw|4h{wtn(<4qFFur8ZhL$j4l8szXUj+(NSH5Yyz{8V|6Kz{e3&$-oDo4UEji2mxZE_$+8q>r(R%8}gW_FrvdFp-;>V}^@FB&r~m2cnCr)RN}I=!6opAf;Zz71`+(PzD~Sc6H6H)vyl>c7%oq_V-m z|$w9!w$n~RYy!6xkK~+75G1lYO{iBCzCAn*O%dZZ%997ffR<UqF!XF5aDE{8!k^@)WM|o3eb12P;!qK);@}ml5&AUH{ zF07HUF5416$3VaRI)^I>l2OVad52Pgil`!&M~`bl40`}1obmU zvJ1LtYK%y$KT|PBMm~#xcbaj({MVq=zA@AKN<}E5G-%OMJl2UDTanz@2!rW)j?xR5 zc7<0?`mv_W^+Q3~@i=}ezQ!hp!K)3uMQVR5a*HhemFVJ_<4vEIrcKAGWl4~gsv8Kj z_1%pV^MY5%N&I-UFfu)B5B#f#n`wIID>26i;tB)L&)Yg1d6PYWHr!(>iMOpJ z8`Cj3T3ZMld-knr1HkCNx+$Dg%XZ}I};(&;|K(0-@BGsPk| zbPMr-e85{aHmd~3zv+|2gz0Nb4IzkkQjgbgyUG-L$AvJ0bjGxVQHnX&@iE%+;i4d{ z_7u-%Jl$|-wvFYql>eRjO;x~=VJ)}sH!9p?eYp67=NEfpYkK_q;H4qgsXNA6mr~`R zzWAW`c~~MslPbQc5@RDb1*lu5^L?oeNBiQ@5wFtgYLp6mWT=CbP;W-KYw0}H1IVX{ zzU9$IBVaIc^4I$<-NVVF^6N_oA4+&RN;?;)GlAb4VyLX50p<5tWN8iF0ZPZEs^U+_ zJhbqiF_)JGTFix^kFJi0le;trSGsSEM$3LS5j@+I-nF@*7j5*y(DjkU5#knKNvqfp78xi!kDg zYyEjefc?n>4V+5GkACPjYRG==0hNJf!%9Sos&uVo>K1v#Q$2LZGEtanM9; zZ;@WE)|#B&BE+VZagfo_7H);Y9Ez_oCxlV{O@JNT!3NVrXD)^;)_3gN`5af?Qa)-( zNCS#RJOK9KRmzUPBVj^8I6s=kSgNe!E(70pm5e;TqkmD_Fd?IRzeKylALZ=Z z>Sk{jEaYR9$?2mv)Fdm+fICSuK9_jWCe7lo@Xa_tYYh)&e-~m*ccfd&dMbE9k`2>z zmbw)K7r}nU`G)n}WPwRnq)Hgyrvj{FNdx54WHy#_0n~w;U8&INwjoAt|6m5I3g#(1 z7&+1>v3ic~uRoy9+v9 zMfYx6veXvWH@lUw0Qz7@t*g%jWu%Tx{M4k<^)$YfJ2tS-)^RYt)vhqS z8i^g?htfoy3u_hFnVuPD{$%w%<2e>+UUIsRwZv4V>!KRB`-@Tl32P`O;C-V#CP99HW(40y8MAXc0 zc09*r$%HCmsmQ~1gCu&LQ@Jq&R*GHxU9I-S)ot}2`Qq}qG1?I=vm+bnB`Z6%rr|AT zKn*BP1|uNcs6-_|j2uo~SM#^HNx2E=?308}eoTkH?Y)YAVV1E!-JVpEOdve~M(Xz7C_U?1dzeIG+%G&YY=0}Hlp59QZf>*b-l_=c`!+PprW zpXctIbf1{L7|D~Quk{M2kbaTG1oCqC*+PP*5vgIvDe2bSaK;kKz|pFlg3+KV`o5?; zFD=*gD?o2p?Z<4;mz3ey*{XRtDpYMDWktz}JACbvAb%_fA;Z(-_KT9M`=MLv0W-c! z72?oj>7{W~DU)}m|5nvr%wiJgAy+jrU8lgugq=gMD8RC1k8Rwedu-dbZQHhO+qP}n zwr$($`=a9we)Ny%9952MP!XB6*4FU*X7Z5ues>z)s(((L#Nq~apF)CYRgWyuI{5yD z0*85f)GD@Vhh^tRO=X8#r=VGqxkOcyMaHKNzgayb`g6UH^(gAfK*d;MbPnW5eD(2_ z)a7o9q>%v63x?~CLM3#P9vl?ygu~Gg>@x-y1NsIri&d(S{!P1GngX4TcWBT3!l8}o ztm_0iFCa2)9CBtgO{87U4u~y@*8_pVG1cr* z$AA&Nqs-V1AR_tLS#wEvQ|D9Rl&kYc2n#Tt$7v`lWP7{ukrCUWj#0!-S!^zs zbgIYFN1e`%!eX?$Z%MOOn>+X&3Cd)UTePV&@5c*%^RAK&DRGl(C?YJ?8U%FsML&VK z0B? z+a>TXBt(KL`vbN{fmh3^CmqKQ!FNr&dFZjl2LV1QiaR|XS*@``7M%Uc4JLpUFLb9e zC*oWNaI;0FsC>4N6ht*H-o|EvLZwZhQUF|!K+1w%Fgz*m7GJNPXW6T-JiAm>A%%OM)7|XkKaI0pjLp>5arHj^8tyX!$8o!Qc?-j)F zC%~Tz6J0+qHKoW0nuKuvo242OHnk?T7M;GNWZ&Fa4ib{;NpWWcqj?Ig!OcsGzk&2n zG~W>kV6hY$MS#KYH$0xeo24+AScYu|cR1t{u-RKKMqb5*(xUnvL;mlQpQkPz4jh=5 zQ|Hr&1Ul{I>Lrq0H*fl2f@@hU)= zAr7~)5~lHeJu^XWD@<#V$o;StxY?6~W?=gN2Ek|wK$Rvk0Rar-DILn}UmcYB;e%+O z%ZuCwkxhhrmD~sy_+ds;qu3AiHRcWihmyG63YMcPO9Y)*dNZil(G|8hSiqGGTjN^^ z#MXCGGaNxZ#^b?vemU`RQ~Xk;@D_A}%`bIc{JLZ2ksV6!Kr#uZ6d@<}djJmEa`4lu zJ>>2uYUHG{2X-=#Xc2Bg%efwe;zojEkhDFDo>|6x{$SH-(RWHrgJw!+kF;*gA?RnM z2?z~hpU)eALh94j9wRDtXz{7VFk)~(gPfN!G(|f=$n1ckFI9nYS<5X{&X^`MD^!DvX(0mbaF+E(5b`n=# z$E_Y^pbS>=d13#+O%Oq#B%91lx$SiIGG84B|2;l zbLMSyb?SWT5@5xiEP*lcOenluzM^t`!c#{&{Y@F%XMd)oX#3s+y) z=TYRtEfJU}tb6!vw$sXN!+bxM7bB(9Tad)aVZ*@v!ymp2To{9w&aUPL7F~U_@j7%>T{C-0CNS|V%0o+st!nS9t#!5%6?3_hC^=sq)2VF+ zfV_M(Q4GPKt0wG9n=g5;dt2I-5x<>R?Qg5@%F3W1{J~c8M^uDQs5DTCaT2lgLjW;<8y6>9 z@@H5QenT}0IW4p9&>z}2%g7E^L=6iE*At2~Dy${}OGYn=uspK97rGu4tfHMuj4G4# z0}Se+>+GOqa+S;c8VFa4+(g`e)7peo0b6Ex)8AfnH@#%i4sD-MOg#Y23(+w_+J2u7 zcHH88S>YtK4JYFrS|#gi_Yk#})!)TR6C58cqbsDh8&b& z_oS9FkttXLUhR!k)jjBq1M z6Iw6S>&wS$-Zj_uY_r#a1`6Wncy7I4&2I6Jj@0f>|gdixNgLQGn<+2mfru!4Uio)qZU`nx2^2CDMj0MpB8 zmqEMx4aK+e)R7_|>y!+~v4lv}JYSVDon6grdLV;Ymk2g@4Zt5oPy<`UkSSkv*l&O? z!d@$dMrdLs&O3t|!?bwkwur);(&7?hq1jxWo%>aA(3={R4o?LvwBCx&`iPWYKQQoOqL z?H=8u8}wm?FR48=Szu|E1kez>8M#s>xi=la)=JQ1wAhkjI$cy@p3G0p(~3H zZa@~PKo?rAHtE2WwvEhXA`XUUN?qP)YrUWq;F`*)7^H@>Z^(ce6~h5W>_t~B0w;Gu z#4bFXPCAxO91Gu_S5%oW+Uez&0`aqt)5XaVg_XV0!1I$$cr65;4cyK4pj9MP)a!7N zhjv^6j`$-_FM5Flb)#`;z;5O9TpeEN?9Qe}GS(V(SMeMnc2-DdT8g~ieeV@2si6tY zjSZ^BU3T#5yDy9iTJKq6!cm$vzdTK|QY+Sfvbeqt^yRrs16qpQa}TSKdXCFN`JQW0 zwZB}WNI^G&dx~xRf$)Tr@RcnTwK$Wly4ARWnbc{8uJ{B~$7vI{AW9dGxk8?y*haiE~9Ku8)Vwx@gcUJ*si}k5zQ`K zE@;op5MvoHfb%RMx^%ec;j9!}Gv)NIIbe3}G&OJGpC-?!BhdCkLblfbYCffk=H<6S@+cU2S zAnYs;`|ilV&0+BTawW^mp?0*5+d(!ap83xC1KL(T1(tR~Uqcl|($pT~!9;nj9o>!y zCA~S2&3LiTxQs)-^yl2^BauD6i=h*lw!^WL8`M$!d~Sb6UkTDGOckg;l934-r75e| z3iqDnh3*oLm)LL17al8INiME-H9Pxi9g!|(R&UyRE!YcZB9dZwV+*6uYCl-x!7nYH zjJohmh7cK;sht5-!Z)GRjYf(?t=CDqkLTAXr14rAKfO1*vf+jU%yy7g^&6b0XHES5 zXf1*ONb}?L+i09`0l@ZdKw^uDT{g%)+g5J);u7CDfN??sG4ghmX~!WNf`^^c+w4Cr zc|t&DQY+6ixEevbV5;q+)$aFQQHa78fl-e)b4PeT$t;Zf!koiV0jZp{+2P31*rcR0 zXt{pgN)<`P`rHP`gK#s_KGHfI0RA_H-2a>QL61kz!oc!hQQSX;96cK=+ke~tp^#%> zW%$3@;QxPxT(!HgQr2Yx4NgF(?u-B-@#Ou;@@#s!fti(b|KRv^v^;!+66u z@QeTeTn9KdC@6W+ym-d38I`Fqj4|jrkPM(9KN0{H6#!^>c=*4dd`mMsgNQ~p`!IPb zs`Ewpg@wPVN3_U(^`pGZxH&R-j+y|+qk)uj8#6m#W|v=x2fkNjP#{2A)P4Yram)yK z6=g-#)p(G3DN1tSVnEjZF(NAf#At?=agcm)MnFx@Knnmp)M4XzD7 z(EQ-r)3~Z z0QI`U@cX-0D|~41=-ZCI?pMYAqbu`kQw{kAu7SvDx#+tp&WYvSbQD?r4o*E4HT8=S zkVV9I!>33b*BB1kH#PQAsOvkqY%T2{vx29&2VU#jiqh9NF!g22!3-T2o_wtfV)rEo z+Qj_r`i86Y4Vxn_A|faypLNr#UgL{J;SJ;8m=XF7-ttQ(yfgE}3-23@h*<9k?nYl{ z=Kzepwx-T=vjdKYBV&^LOLDyHulD1d!s_4x(hlszb75lg-udzS_H|kGYO6nFEqx{R zi;1OdN~pOQEB-0luWNyfCOQfq@Z0l+tNi=;^*ROYf5V5|mMqMP+@m*{^rUoZadp*i zPoKSG^JlCd;j@6FIe_a|qLZdKsm?lwVUSlDKk7NL%a$4ky7Z;?lc5QGa9eFfNt@RX ztsR8Nh>6?13@gc6%L&|H>O(lJyqAfvo96VmC9lVU!Se4_6lLWZ+K)eemX)DnP`6jn zJ*ngL<0zhQo#+FzcujP_m1sG*VC4+&w{W`M*Bjq5F9Q?XoHOipW2|f{>SKDqEW{@3 zc@ok5`rzDs&CC(($9nQ4j+FP%@K5Db1esx$xu9i6m-;YRwJwJuu6FRB!n>i=ptYxMc-c_d^K$=OmWDkMh~l3L#05*rPlaC@HTTA6Sxu! zGmMsp3zG}GN1LZRWV(MSj)A)C%Nn9Aph`?pd4M0Lp)Oo7Z@`E-_^v;;D>vz07ePMP zsoaKn&ZH{f;MfRVC2zCDyMAqW;n3w~ik2No*;h}o(f!2nU6qG|t~DGMd@^mknUntfeYW`jR7D$tf z(tPkvTVP6PFL0rB-lVJq$DAw&0jAltKyr1-%P)f28VC&`$q9B1Md&98J4CTtJaoAz zyAfK4w4CiKRi_~0sW3LqCIhQeWSf_hC*+d0O4`;tSN>ZFzv~GIRZdf)xr}s_(TGCi z9A(58Ao2S1T;G-5FzNanpWOMx2eXS>xP!>%EYCPP)WO3@1FFS17P_TuXF1u9PR2A zesb0yMz1R*+j1eTsUA>@Ol+>KbyIU{nu8k3_#7r5`s=^I?g$k_-M#FyRRPh9Z&TwP*UCp z=rFdV@6SvL>G->e)LF(Pk#JXgk|3SD)StTTg04Qi{GGolR$T&lO}dM7D#tYJkSj>! zvyvt@J7S^YyN2?sNYJ1zAh2zG6All%#@E|>sj5x9tQdw&{p$C*?GbLH_kzt13CiW3 z3o*N*&hDBz2Sm|thmmRb-9kf6%_I#PJ}52H<+v$gq^%H#NdHFduBgzD_)b%Xs(hn^ z49VG~jDoQW>-eI6B{+k=GSE)j-+sB7c7?{Un}G=~bD8)o3~kv{wZCw$Z#A6b3j}O) zLr4DHr%F;fY{LS=-icn=q%eLpTW;K7`wY08H2Hau7$&jP1Jj;C+sH&}A_%F$VPE`(hV8)jC+a*IP%XSvI)DK5o zz*DHhM+2#ua>~4XB(>OO!M^$UvgT!E3Y8(iWYOx70mZJYmcKs#BV0T4E5LuN5MHsh zrndfL{3ZKdt#h&-tgZ4AH1Cu|Q6F(#^M2f}X>4l{`zN4pASw>BClZb@Ctmp|tvXWp z@0t~$Z=9nyC3&IYU`gi4TGG!;}h$gvq@#ut=yfh-dpDrtQC7B8B3 za`lwr-vm~Wakgu;eM8E>D+DFbYBZk&W=jaC&A#Sfyu;HQp`*}A8bEp_$<3C3MetA~ z4C|KlrH*HoKVS%*jV-lmHdTh;+(xsT^Yu%yyQ*vCIn^jR0%d!Q@K@hW2U+!u&?1>r zsC1LoH&wfu#(%7w3v4~9yWQzqa^Da(+xQ+^iT))e!YL zQHmWb$g*Bo9t$lLqk7I|ZLd3C(ojjto5*SyaZ4Z5&id8%pN^dCzFqo>!@`QrBD7%k zl}8=Ba0ZLBq$ArkG=L!EW8A;NuZ@bNb{6RO=>pTfvKOX>4qav)SC?eDcW;VxM^nDA zd#U!En3>C`nEVFqirnC60E!>VP?zb#*b+L3uR;1fFjwuA3JkjNQme7lM00&Ckj00! zeqU6tce%^pBx;EmskElkcq752h&-||j6x=m?ls%OwrOkL&65%)|0tVJlXGfuNdYCh zl%obp@};b2>({{ERTgJk9yysrfC)~imj>1)(pZS_G&_A>eT zccn2zrgw_VB1EypH8?h+_ruK`!Qh}90vFk!<$7!kMM@>L23Ci+pSUt(m0_&8y^DUY zG>wt%)Tk6#_3;U-gBC+I`vZB9L`d|0Drz06e;xv>@^3-9Iue+5ll7F^@F;XtndM85 zSaCEp#lP~hv2Xp?9HXQBU~bv(UwrWaBCB~E)2af~w+4POo6A4+rjwFT>`X6Gp{P4%mF(q-Qx;yq8+*B?}^{0>2+Fz)giQJN8*oH;@_sy!sdUQ93b-szY zwjhKBSCxXR&?=tX>~9W4b5>1`G!~O3T<`jkH_YP6MP#RE<9m&Jv$V#~=s<|Rxpjey z^QYwDQ(h0arYLo}@GIdIW~fv(XhJbh=388(9zB^Nm0?^;AoMSj?lGLT1T<5OEp;84 zC1*9=XI!p(`mM{C&JW%YkCECrtxHuu9_4A;YD9pJgnD!zUb1@)^d#7g52dbHBG2cp zod2r#y~irX^1Q+`fZ?E)CX>n5v4guiigL1!5YOQ(KF-m@8tNO*pQNC9K^dy*3D${p zjhH8C_JC+f7H$xpiW6AC7^c2MvDh58JA%0kxROk8%VNd}wS6ExECBBL$mQEGpKZEg z4vZXzL68IvI_yp>sV8>nxQ2w=etC9iZe2~UrH@Y%r^dK{(juj)A1Y`2ZPp@A#uRy< z9QZ8wM)qjgw_zuHFk|vQNfP0CAJH3u#1I2s*<47jh&a7xO?`@j_&vW6Emx?xpS8X z>*EuEoug=(9;5}d`C`YdYyJw=J2^`yJ|fJWP%DHucg|D|3yxSG-p8PY$+XF}1+dKC zTpWU?V(kLhN|l%{;37Afw-0sw(M5ru$15=SRG%b7QbeDS9B?UgJLUhY-dSXP+3C9A z#VCeQD`K`*gnF2be2l+yIbv|NPC+SDdyTM9(zCIigP5B#dRV&stc;^sPJ<+%$8!8s++6fUn6T2t9 zEJ&w={G!-vzl;4?*-r^9l7F{<>k-LO+|ZkbJcm3HfL;%Zrv&>cXDUktJgGyqr+oBA zCNDhm#=Dvq)KVT3e&(;8Opww02IQ;^hI`3_MisKD2m^}`8r(R*3S&)PO&PQ;wN9c1 zhJuP`8VUQwK`Vha7t!}BFUsCfwv5O$jo7ZHA^<&>w71bRD5mYp~3|1p4!yoHXyZTO*LP*L&3Iz!59RaMJ75_ zvS|*!xp%tqwQ471&*1jNxTbIJH7yc9JzA-S*D;uFg1T=EwC?dFeAKQoCAoDDDhCto z9-@oY_XPP$gTp!>tp+BbqvbOytNpGiZw`XFtA8Eb|N7|M4{kuzo6_eeoHh-19~usW zec}N!KnMFQ9`J*wCO$wCqf32uLO@D&=Xi(o%@2kc9JorRMdll@NL)^Zag__pTIE}X zH-I_E@G=H%m$7IWb9exh=<4MoGbH7=r6rF{$584^Xa6()qQ;GPRW=4#S+La+`UF4;1&gF`P%E zd)KzOCa(R`-+5)|g~D1kaLetFe}BG;@S}8mf4K_Deko?BbJtbU0}1Y|jQwbQ?v!+f z%#?EN)K$TAEf?kW4ii$RT@q$nOt~h?S|7SruXSJ4)#TnK8W$(0P&dcfGe@iSjvrYN zuwhi!uVnE3-17mw$>|&+v<5*L34*n9w|E%zB>)r?BK9nL5NDI-uREmYqWpDi|{;j!y~*R)3xA!D0bL zxh64b@5uM9by^tx1{Svf{Q3SY|M;pkwIW>nfuB(yEy+EjQ)u`I3~USoyeHc2Mw~$wtKW(`r;8xJtygL^fRGyKdpCFWbO9m0mJxby~J2J$E zbG1i#Jt6Vaka~cpIe@BssrZixD~VMm0uvk?n@&Rwn;E`-j5c*RlTf&z30W*ew(QeS zXO5NJ|Ec|?Px7o1kGu0cCb?zX{_=@%+LpyN>{O<=MJG8C?AyXnn^pdHOj5;eAl<9m z@cJ$fcAYjt*iUSY^uOq6s)mQGX%iB~uCjrh`qK@Tk}Yz?t0)~LTKdH~U+B|7>4Qy5 zcn|r|9I0);_6DA24JN_9U(4Kg_!yGsvQ8!xtr0AtaISfA*t$MlR-yT!a$45W}M zF^ew;crberNJqyVz-2u?g5|s$2+EJSnkI2X+~8*szFU9J*)CK3TjNGWd=UIXJkzV_ zocUE7G+N`&R0~wVZNErQA62JM5VwTjM(qmcg8_Y#WD`crXmO=Am=KbLzqnYzRf`F) zlkG%ifV_0FHGVL<0U?&E{ocwfkIH#I8 z_l=^b*FTNXT^%#7&G!?(3?a-`}jQnc-q7&hN!o$o@z&S=2xXkq-shL2^EWc8?bKaYt3a^a>_yHxE8FuC0|0xJy42 z>+KDI6o`ofb z1?wnM%3rUlEPh;Ml=ZjDSIVXwtN6+hRG!rlzQ7>o`Vvo~UeH~}hY;Cnz~gkqg_yUV zhleWdwu|;hU}^!M?mpT3OEu6gSc}*)81_rre_YJ--*?GtkP7#`4HM$fO_qPh+}~de z2dW&#AB3N_cU5c4P2NZvf!ubAw?0Gb`CK>jvgsJ`^*2+wA*dIbpUNs=5**`c|NZ+! zSjDA!JZ><`CY@iO8AjDxG#ta@Ueb<>$um&jQQzxUf!PRLxr#nxZFIXC@A4yH{3IFs%BpRr z_T5M*$!^v3u*O?|VMz1-Vaqc`Fy&Pk`N36cHWaN(HeTuXhKLIRRz@&Xi2mkm z=&Tq{3~p~K0WiKKVoOrt>R%WjrC5i}$ODC${+4P`gA(k_5eKex5vfKLocq2_!nyUi zp{lB3TiQ1J+SPB7M1X02RKPzO*R4dH+!)frxxGmjSiReXQzPmCLZW=(sELU z`Ct7HaF+C4)pD$i;pFK_ZAvzog5_6)FLYdxRU9op6|rnyG?|~-p0hAeVZTSOLYf~$oZqfuokOB z#52qCU#~HWxdDK*0p_ zQ!kLU*ZPBc_RXnHsTCE$K=t8~cHs3tZCF9;-uKd?I*Hn{=ekIP@Prw+hG{ki`n}hL zq~XIwm&ga(XBe)AJMzZIT}Z9tnRUsQo~J*I+NnVIF5T5-#i`D+^{yjj>mk|mX&U}Y z^Muh{%aU^-`FV%5g1mYD#LJzh(h3&E5JKM|y9Rzv@PKZ|-h||rHTkW+yrcf>?FjEP zBpq6E=VzBiJL%t^bj;&(G@dqFmH-k$)bHnso3_dO6ALM=#jO0TX2K^nAKP(xiEN>% z4Es5VGfXq3LAf*HLTj-OjAV0{L|95p2+uC3kiI-r${we0+6i-dCK z+%Ueo?M6)okXsS7Iy$mZ)n=t+ZIdc2?JIZtqwy7ItpvZ;g^B!&-dd>%?=#OR(~t1e zY2r#Ry8Nuh?-PtJ7rvvG!`TOh1h^i1~EygW|W(ITX>tO3;TGvuPZbRc_XE=s%u&N zVfYc&3}bF)nw8+GS!73@rele`X{!2gaKvFn)}=*ZxVsdUoZ!!7LPPs|S5scSkPIht zc6vi^)H63y_P!u~$l=3LC&|WgOA40?hppZi zUB$TUiwkX3p(`iX+JMgSMqN=ZS}W$j{RUCaJ}VtUOJqJgg?&qJx#>Ek`uqG;*CfPe zlbe^NIAwAp@~GT9mW@DAdd>HuRJOnp!J2cDZnol_JtI*>Lu?#h5zSe;l`Dco(heRa zgmI5ep4kHys+jWp`I00N-n(?NS>H@;3`Ij@;SZwyL|oENnwM91a4cD9+f@KU1!e6g z>M&P1`C5oTsXZm!ePzNE_2+?#l^>D8Mr(99>J#+hSnCPPn_nIuZJuoWg@z;@fNc_k z^K;E(iN0I_@e+U0pMVQZk>y6KSh&V4i3D2(lBEZ>IV6QiK>LnIXPmDxfpB595)tH^ z2Jyx}zXsgy20>&OQ_bLiDO8Ilq#VLaWX;c#D;jF8%0|kOND0+Hvqa63FPlY6`o9`pF}2DLaffz4BF%q3X4Pdi`h)(@+yiBrjG9~CiAOLL2l zD%%47gn%ed?LEYpk_nShsvEh(QxdG#^@nxWj_LN`JG{K z8$^364No<)O;ZP=fURY~I4jdmEe$C#b~jzeaULY_!Nx_ zW?MwZxXuWm&-~tW75nXVhmrvb%9LfaqZ++y7Wm8&bjpv!>6;>l5FcY>Zp0 zRWGEbz*cte27}IT9Btl7A48Pw99fo_+a^^JnW8wRuBj`z{F%C5wUd#*uYJQ4A$`)^ zw>q5iLyOJrMdOL7?HzuWwY%G@eD_3GJ_p@{Oj?F^EAn%He15t*-x70*v2tC*J;Vli-iD>Mm&{*)4_Ata4&M3WG4vok>7-w{I4Z%svEPyTP^gnkO3W> zZ3brz{HZy)!a8doKXs zB}wq0c(9s_hJC%ju@a%vaV9qjR~Mr_74=s_Q>x*(t!^1z!}a&T-Q)cNwrW+{3LX1t z<4cl^aL+Tx;IK5;#nmfj3xbtW<`C2RjNkghM;8|{nPvs>k=)t$|2bHo^UX-?`Y^Y& zW^f9YRo_>ke2u8kA8C$I;uLlu5HIngVNByzT>58>TLlh@Cae)8iXoc8Ai&?#6zbw7 zHeyaQ$-(N#>bC4odc8@BG%SCoEacECp{M0EOgc{2>13NWaCi+hobDPAB5YcrV92v65&3k_MbWiL5_ZP`lA0o}Aj${Ybi!Urj zp^nMjBIZDREda%K@OprzAZh)5xYH!_$%iomc_yhSr8{BAaxh)6XRL>&Fv#^!*0cHh zTlpDDg+r+~7h1jR8(vnz@N^YeRce{_)&@hhlmEeV?gW5^;wKJ?-$YL2i&8T5Nid$7 z=nv?{Wo4bOF%FH;DUyhHoSDrOSnM6`4jjDGzI8=nuAay0i2MA)j*;7)-LbHZxNc2R ziUOkQg=iwV=w%wg18K?$GuojV!BytP_=|{dCNPmsEk!pMy6cO*+34tNi!PNxxD?TR zZH(#1owGES`)6I<7@`saO%u|KPZMr=62nXzT8=cis{L@1w&e;E0gonGRyQD*t|@tF zpXIn;dvo&iF>hdhJk!Q5sQ7m|*<`T}=SfGg;SC-EnmJW$)r`?UPi@~XN`eQp$W0}v zia>@F-gtFrK1GWQzR*;9a*0TX-03h;;|G&y6hF;YL!(^M!IfzSLw^Ao?D?qkVx{(< z^U$!pZ4e^}m@f7Gd|_#16#@+~fOeT&M&Lq@Q>`^7Q)I!dT4DxadpGyy#@a20xOYoV z9_bR6YWpXFsMp8XS+ zQ^vCyX!iK%;5ZkWT`6~x0VSJ$s}IOqVS-d*Yl|`0w(6c#Z_@90$9+cbUYeL7~t!h!B`5SXONd{Z@C59 z%8qcNE4oGFe!-M~o@V!X)3~awn-rLL;&smMy1{UQ?cG;3;9I(Uf!NUr9*tbOgm6Re zwQdoNr$Q#G;t;1Vx{S$J1x25Zwm?ozDh?^##Kcazam+~&k6#p(LwaK^uZvw3&Yi%e zWp!vd9z8GUYI3Z-MAOuMxhVM5WNlYU)LD2KX!Fg@$71jGo=ti$)_a6^bFY_+E$P$= z2EYjGa=d|`mmY|_c%t9rNY$3Tb-%RF^3!2qU)M|8kIM=84_PW{Q`8RLlUyK2u)jHI zqJA7~XG%HhU_%3J*!&O(NJ;O{JHMtd9v~8}fD!jIbX83pydBL)G46SP>qvX91zrxK z-UGhObJ#AyqgV&iEtYB6tI{oxPoYRYviopA8;%~(+{-7Z7EA+t7_FzK zaln2w_ur@-?@w5AY&Sa@Id2@rkJ56YCq|QFOO#TJ*bA-xqXl@H{8(JU3B7QR>nmU< zCYlz_PPGM}mec@oL5UVbE{Ta(2s=F8G8|TS;y4(hWrCWQ@%=(7oiLb5qX(aneM;! z?{n>6OuGkgAJ3MCa?Sj6Rv;z$yk?~*iD{#SqgjdK<(<25FVQBH$!dro=|5v`K!w70 z)1Zfz3%P=y#~`Ntg}q#LKG$ifA}yG2S=z48*cH<`l4f`_x|vEBz(`-lEy5JuXX zU6#8JND|Uk9C#$NThB(l=Noanv%}5LOARj$V#&lMuSFH5LB{U ztM{~GK_o*!$uSwoK?jB#Na2H_phN8y+wdOx%`neyIPOn*zx1icX8gy_QCAajI_Yv4v$g^AAbKUdXVM2PODx%=-1;~lflP!pcvJ?#SA;@ zv8!v+i~PgprOa^Ub|w05ER zZiSP_Uxx;Ux60^bnJ9%W|FBObNrJV-86k-JHTD3hwk0Ld&ye>UEUo+P?&3(_Un=N}|epak_{U>{Xo_E;n& zK;=7B;4G`ZQDeil@ERIoN=GN3<6Y1eulRN0Alf+eSwI@0Ug(cLO7$_Fq#S+8l4`&7 zs7EXfobI%L(|E70o@z2P5qZ*4a;M$Oz@^bop~fJ%4AG05}22G=r1WcY>b zv_ApdUk;&%Lzc?djlPemA->G+$_3io?sTzeKbNYW0)9wM1!{u1=W-v~_RmmS8E%}M zP*P!AJnM;0nU}qV(mDA`@I8TC3JZ}C#Ahu++!OT-@_lYjKB~zq2AMZLpsMB4y}==YAtn|!zRCB0&pcR?K9w2;~bj(z^f(LY!O{;2sR zaOIPNUa#N)j2W9Uoe&`zSI~jmkx2bCaF3H7@nIdwNpfTUZd`0+l;Le0;*nCkCWI0a z;MofCS2qbp7(i%$tR*&r_ccR=0DrunfGMtGs9vF7VR5=qt5Xq6p8Fp}+8?zeAR)CB z!e~bG{qw;2Xti4TQ4>N#<0(85W9BxKvGynU4D1@Nu76ZeFB8MZOlC=T;@88~D&x_i z5RGKZ201!|o|ns2<%_du5~&kC`Ay_sQVPh#!?W0>-wqP!4BIVvr^iEHMHBfF{(U>O zUeV`5B+%~8AYmR$9YyzsVR(&4GHHzfm<##rA^sQois67_lw@I6M=QGSUd4RwjX?;h ze3?(6#oceMVOlj$_xACy4AF?-n zxbHcR?7?})Ky`tzHu;Pw4xVy>p+dy~ZzIB$9SmWj6lM{S_isoptv*WNZ^=dd zvA!~N#xLRqlBtoLV6a&c=>sGgznXdFIvs<>KW2e^XkgrIsG`;52EO{is&BrlBaP{4 z!4%dcdp>NHJ`--A=nYQHWO{GhtlP$oy$?EcFuUL9{ntfvF<=VU< z+p6g|oo!Sz#E}GD_aRH1*k;%ifF#+_;|}kW`4M&NFrPAAfd$fv(e}(jS#Q1J3VF?L zO+&7CoYT@0qI*N@K4u}IP}hXyFA9-wby8;mVw+(P3b7M;vI2Qf}__$ujdl<+AP_}Lfq`|MjC)X0b#8Ke&a%AA=4hI1Z z6eLFXBar2Q8>`je?sKDj7oRyr=Rqhh-Vm_Z90Q#1jPv-f1Lh~~0{OH~*!{V5fyx78KZ(hxLN1HDCWE(pM_bTLjYe4n~@t0UjsQwK# zJt1uHeuhI#%(Ytyw3Et?8a14y`vF&A>`zuk1#FDk&o}Qs27wON_tMi-Yj^pS~V2K$O%y_4w zf@)cPPM*GAb7S z3-D&vgsjQGweZ6Bp2=U4 zNw^mqjsKMV!!Rz-{^dsS?NoX(HW}pBMxx!*Jc?zd9R}Du+`)QF&g0h&8dpr6XCCjJidYWVYV^2X>aSY_8`B}K$JZq%fyX>0J z=y^=2NYqX`)~IT6k%auX8&*dKR^*yW_o(O|J45<6sc-8R?@m|A%Ow} z>emKFx%p3lxK`Nx14jOHMB4fXjI{3gyua{lmyWh?`*zI6Vj6ZU=8(^NooWb+6qN~( z8UZmdpn?NtpQW8)v;#h*w1~{aOyFs{BcxJgH|f!a-=%| zGf7DU6qJkrn3w<{qoJWuVeo+%o!;n~+w6nnDJibx73AlC%Z~Gs01&?Z=D$BVH8Ft$ zjq&1YNm=u`w3P6b%7*<~ilQni`XvUF_f0K~px_ncl@Sxu0_G*fsRE0o0ZC)SSOY}N zh_IxL0H{kED&`fEqxQiZ0o1*}0_wp4WvKlqW)Oapro<8UA?%r%T3EfGn_QS!S-i$Z z{LwSL(6c;0dwYkea{@`@L|@!SIeQUi*%&XWES-&3>!`%o2dfy_AUzmZs!%&u2`r38pP)FzZM&6u%P=p0Y_twbpi^~2bKiBP$O_Qxo%qN~h+%vj3 zd6K0fRP+lkF3gV3|1`alrQ-yj^ex`MGJ|CLorN(2gey4-fg@oliHXUj%U%0*I_13t z`J!FM+E`z2`<=vkqOJT*4=heBERV+Erb2!+l`<@yT{}tPQw#Am5r#4Y1EQn<(X=_R zdgXPZDS`X7Kse@Q6nst(%7=t7JA|X7XAU%u184UR0g?OJt(W@U6@Bmp9{!~U`E8y1 z{1v(JJwEeoANs9*eeV^B+5xe*>fC62LjCX1jB=VGo4>U=lJ?R07^i$ zzyEv;Z7prw|4&~3)mp>!-|7Azz@(fEKieV%H240!=@;{a0H7bWDtl|3#;2VQFj){D%a#f2&M^CjYg9PrCk{>xDDa}b zvwHt;LjDVg=|9hMhE5KaZUCLnx*3`NRsDbb{_~{wUtq+5#vqe_Mn}cT5NPr_ZU0m7 zkJ{MT!QqqSe=UH|s{hCNUvqD2>Sk&TyRrx}<_WS&%}8^q#mX6;5Y_4LWr7$Ewkv5+ zEzI|;2KD%+hW+8HFnFyArf;0$es6RCePZ{vCr!OS+KXvJ(UWX?k@wx3gsLweWrMtf zgJwT~LB9kc?NlSm^KwCU3sRe%QGI`VLP=S_`1LFPR0oR#%;f`>ABju8A3Ev19ioqM zN_`AQCvqbgYHh*EDS5)t!#%~|uaV)Qo@=PSJv^H1m~Uh}hFCsHCq#)(?gkFG4aVra6lUfeIq8;zL4<&##GbHgi8&;qGVKf6$B zTxBkH$ylCoLQy0)Y#Rx=qoi`kZoF=i^jms#y1G-v*a8sd1q`MS`x|A7w_)5HhP5QS z&%sJ%zVZK*&-GzV(ms7dTrjE`YHXy{i9FK%Q-PP+E}Wdv6T!Zd$b+8&xW8n@+#z=n zP|HgmLkMw;utuE!IaG@({R{l=2ZK4I&9QW~=C^tPPlt9SwvJi-V_t-q?Uxv%>|m@>~_C-xwvHfj?K-f!XVl0BKZ9l z*N|qnKJD@~b1ga6qR_~C)VLa7BN-ALO?8sLOQ}g3ugopS#ZA?E^IkSnX&huKOQsRU zBjZKWQzcn0(9CtK zi7bkABXnM<@mNKS1{J|#32vf{{Ua!QM@jJO7n5B1RUgRKn)Ca31-jg-C(*qNRv?Sx z51^YRChK;Tko(`5HFN$xE1GZoXG(>J$c!J`3w?QFK>jKyJn&!gdfCUa!MZnit^1+} zp?`PEa+X817v$ThL=flGdsFqLbvfxV%jtjvJY1k-6DHDiP2bIL^ULPPmzz@kfg7T4 zEVVL)CzI#?4Ttj&y;i+a1HZ1XRyyK+Tti}Wr zDcXE3kw7e_iTy*4RDM_H;h|@W*WbTJH~|vwM>U6NEqh3=5BH}`=lcR%ixwElORifmmq5nQ||0K_i4R{{lYc$a~;H`H6tRwyMUmrKs z0S2Vjua>qX?*0Jlj5J(`YH^$KZ%>QT|BpdB#7E7xA^aAP{R*#RZeO z%N@5F2r%f*_;V<4((LOQq7NR| zW;YcklG~>4s_2g)uJ`$&T~1u>NhFt)Q;EuSf$@z=&hB4pPT+YikkqQ~6^i7~NmZOh zg1yrrnnh5w*8g54`CKdr!d#~~rTxU-ON^(SV~1H2G(HrJ-I>qHphsg~3zrZxZgnU5 zO)~xH4I8@BpWo6^$VXr^AZj;CLu!o24q*6D7BOh@8B08__MaNXfdI6Hd}wXQKNqnU z-C#9Pkbj%(jm~9}M^JN9LouzdjX+;-APQS*`??gct&Dk{xT@@+%gB%Tehisp6zKGX?3t(c zooI2)Xgqew#MBcDdRa-&^cF)2oF3tM^3;hjB37qZ6JbO1eyCs=O}`ry=g`Z+6O6V? zELA2#3no8T{3SdotK%KnVufK{1ZFiMwX(|Q{o9Cx>Wo#U0N~cEShoM6?v@HpPIe{= zDw8}64!Yd&St%CkWnqnvMB2UZUSP5&at_923w1}>=Ql&xc5Xfd4gMpIzLsYuMe}vF zcbNT*2?Fc{gq-Rbh_9)FO#lA77HojsY3%l!I16?7(5ih+50M0xgnoGr57j;c%{}8- z{ct9^-tS8NUD505`i1q6L^R$X*J~XQ)waq_R zEC+vfeq#=*JrT2q6y6`6B|W>K6EEE^e}9RA#Pz;1@e*<_d*SmTWYL>N`{mD88CZFv z)&QfgUI^ne6O?hdNMRQg1}9HQtcH6Lh#mXF-Lq)^wE@EBTS|gMAkH>kJ3b6i-{QH! z8<9nNu|-BV6+5Q-a5!o=yHk3hb2_JGBCzy#GMW9RaelT*I&LOdcMeH^riZ1W)%DdK zS@rkVZF{zg?2@7=8c`%Bu0b)#_U%$6;uTCuEUbO#TG&%T9M~n=r zwHB7nH}=QvO>uNJfU}EOD6Y`kTu}N>AgbK^j%54@8`YdZ5
{)FX+BRDXq&I=WPUfD-tgZ#nL}lgV(O?bQqsgN4zjB$R!*7k~Prxger^l8mr=r=f zg*VicIrR&UQVsF6`Hp)B#>b#3-LB%GARWo7mhcJB_}Jk^^ZBimS~mWirLiQj5o3YZ7poil?wX4UgOr( zS!Z3lK;d@00xowUNCi9uT{5AdUFg0EYLIqQ_4gTYtkm0t(WRJk+jRyNeO^l+LmXoa zuDCZV?Ys`r=B{x8qh#2%-WFTP3@k^Rm8f>iUiu^pcBWWt@5q+oqJh*kQk2dtMc&SM zrZJvw>4gWyXPp~Q*7xtGSiE<$1ADu59J}&T%XdfmOHV@&6TJ7XDx#sq&*a9O+ii9Y z)W$PfLn0;V$$hTe;askyP)(jTXa*I)xfD2Q+Z>V_qc0@@HN>(!knJASLuB}`wKp{S zjfY0!0T+xAUJm?#FV#%M->VE^rK4JTR*l7o1iEiH?$mM56nQlu2q#SN&247M(K;e~ z=Lb#7(F+pp4YEz?J*D7P=CiFNa7PND2L;t_gU~imrR&iwDSUDkQAb>=9o=AblP9Ex=)wJgRkoglyvQzOk*$*%fhEg zT9GUPhhLxP2F|MZSv2RJHN%M>Tt;=(I>4XS@)3OhI30hj;2Di_u$ff`w=4NNt2OrE z%&hk~64R93dxk5RecW469e>Tm7TY~O1ha6tEzZOl!TE~kpO>(vr#1bJHsDWF%?L|u zVEi@js>z6DeJy6vTpmpgByWPHC(_@-jr1kKqbU_`D9T>6f}UVqLu#qPv0>VEm^x{7 z@;wgkJjg?>$6H$x&Ty~1`}j6Jqo!r_CzJj^HdLF-DH2P~^WY6trWB4G40YBy9Y@`S z6qMCps%*Fwxyw)QDdt_&P9r)32RLtVR}o`4ux{i@ z-9kxAf7txuAPzoe+l+C&pYRoha)&%IX%iExkv-D_Y$G6*94VR9;%&0Z8z)VsYix=c>o>yKE4}JgZ9$ukE-7OS8bO zKGeAH>FNq`cQw;2NeYgO&7xurT?Up)-Nqk(RKam( z54{EH=0qs~q<71ud+V|0`8FBAse8ngh%UpmRR_7nM9k=+p3id#Ki;O)$T$e;b)fwr zwS`{0nn5r`MI@H!$GLHt{0Y2d=!#m48!APM%H|qehqnNPOJq$*oFmU|h*g~OE_Zd{ zaS&%Z4+r1_oU%XLH%FNVA($+ntM1g&{_p7oyh>z_gv7x^)54;qW;t`#rcFg`!#n3* zj`JA|H>CPKJXJ-ckPn?f{9}h*{)XQ9LW4Xn_mmXu175Q@T!sA_sSR$Omz+d&ip729 zRf-~>m0&@2EDJVWkCC;ix`WvX!_;2nE>As1iwoG5)RP;2i@_qaV167rQT=OMnW5^& z!*`@F(_@Z6AVNfsN&|>7R_ke3(-v{B4=$In);$dk0pU|LphFt4=)hv z#v&X1+dV&;09BgNyNsclZulcm$%f28sYcMOnsxIhLzoF8^TmzE&^Op$Su?A6?a1bl{)S(+GTvgNIoXpt)D|*R^6-Po|zmQelEcNJpG{1yNYR z;+#ryv|SdQ6YuHeqmZ91sA^D^&wPPD`Nk|nTC6h!yoNG53ULqWaO;=qzQqYn1$Hr` z_NnLgvB}pe_W>cZ=*`4P;*DpT4}{{J%y2yVYP&doUkN0jyOwK_{21U>7D$-OAj1r? zwDRB^T>FC-m>_J67xzsd`611Q2iVTE!I$uxF}_LZs0|W*8LGT*s>}>|Mf<*|vlJdRgAjBGlkTG`kr8z9hVo|7(!BV%pq*3I5%qym-Mzg!r-58KppVUZh1Jq z)5x@4qn_;|tUHrYuLxKp!g11F6-zxI^D&S4DIGfd;2dJZoEk|mlk3zIb24~UVg^KMxqE7*83&K03)nlg?wd0% zc*rO$m4y)Id~xz=-eE5=TZS}oossWWwF4K~-gE=SXFT8QFw1KGkKZ>kt#vE8m$Nm{#W*{36EJv&n@_hasM@X+G}Fn-c}TZ^<)WELMBF zNmu0itV*K3wqRPjQA$dc|Bx{geZHvmZtl9c>(q!8|3x42%YHuo$=1jhdkoINs1CTD zf#~4wa3R9f;a^4^G#%g$4p4`oQcjK2U5W>T&PiPj(uS5rMf>_rH!4&OmRY*NL>B8Ggr3F$`rW1(y1!ibg2o^4^*LBdWKyJ9v8wPtiz&PlJ8)G{t>iX$$>jE(<=`&=oSt zI*hD#-y5$fX6U*jD2s31R+WFq(=Mi=*+e+`LBlCuskUTBKF<}^gYFhRG*SHNDP$&` z-w$By!X$s#R4PfjRHmVCg#Ho#uHT3)Uoo8vK_q;X0VVs02>t$zMZjY0`Ydk+zO zD^LS;2kCg!MO@%-dWGs!YlGRaa6YIiFxYTjyV*AU+N4<=`?4ge^mdP)Yg^1hHnKi5 z;OFxc{AS6Lo>YFOWE0{4TX*5Kg}1<*-?k^^5JqV585d& z7RTTZXpJ!k)G9g40b0x6QhSbVBZ*GMtQh$%7_4AgjaixX#>vvLRk$MwU6ik6;{t++ zE@2k}wVs%OA*e=~R&bh$n#i(wf4dN-agcM=6mr8!?!q^1G6|zqp4}?c zV!fs}Ho>)D<&~|0ttu2;$;#$mlegQxd!TEFS3Qm5yX6Y5@Ts@r<_g(GpkVRYd+j4~ zZ_Z*!vOLz0pLloZZPPtVlXcon#Ys>Uar|w|#8L><{f{>rs)Xso$JGb~Pbf6Cg+69D zcru!OUmUjVcst%Hw@CjN`yCPiPq&USsL>aN$i)FAJCA&fpUZJ{bAQR&B$Mu$e?(tw zyp5|+4ok_>N799&p=XplV{|vx9Mt3*%M$gebA^h1WpHbOXttmSt{q35q#$#P#3*YHA{3znUUk<@U*ARg968;06!8D;^6>U92zv}6neMsvZa=l*!F)u(gcqxk+t=~v$H5QO2 z(Vgj`)rb!$*8tL=b}m0eV*A!NWvZE|NxfAmN3!Lxep5VU!Uz?0+lW|Uk^|03;t z!$vySMZ!$4s7ripEx3|S0m=ykgFp~U(ZT)%py-K#LGZVil_s+JAwIr52wA<2RFNbHKu*Dk>W z3j;sWs1VUK%hS+TXT6&@*hcfQLH`uI}R-y4k=9Bwgl3AcEo2AVf8JUm>wZ0#>( z+@h7^s){PoPP_G7?FT%`I38a_b-xZO{K2y56>_iJmg=kLS#Y%_ zHxz`$)|a~{H&8mi@JYwnq`fC0Am_GTAFBGvD{%WaPF=}Ry1Nv^&;cETiowd;%l^W9b+BeE!uvlrc^cp0A`Mp9OiIW=eclORH{B*$WfQE@FNalV4aCk~ZP zpOn`)GjVdzw3G8lTvS!j-bsDzN4_Ds7FVqWB>jSz z@mCqs_*sK4oX;S7mIViOX!|`KqzVGq54r5EAeesxMZ73K-UhSvc40I3r;(8Prg@TE z-mw^f@rWSOC;*!c1k0b*(O~{A1ehykhu9orBDxM6S0G*)rx(N~iy|X!%E;LgLA-{Q z81jnGZu<^iag1T%3)Ug8195&Q1h3Nnta%Pd#j@gmFCvtHepOC`kakBrLS>Af?rwpH z$N8{3YVz#4)N;69M4GN^p0gruV)A%8<_qG%lfK-#BtaDVc20*{6E33`Y#5k@fFJGj zrXBwn^57C|Ps`3#Pt%>Q)GJZpwK^@@sEm>z%GXg`r#K?0B*(K?ADYuEQeG~$XpsZI zRb9ri?%nItKj#-fiB>u@vltZb66L#fU-3(3l-!Aqt7B*FBlf0(_WZs2iHMqlp^LQ8 zHb=#ju1I+9bvG&(n;*D8k+UluQ4v{zn7$Pgh0p>%SBd4^J-|7wRVTY5{he-BCYbAN zStv#-O?zMMY~=m2RH&Xp?767AMbvEJU#3|C8hev>2kt6uCk`Id}pE!sCD z&%Y|9y8@J}*(yC%dgoWf^i2+4KUk&dzxE~^pYAY>P@)$F-m-|5r>fNBT3~&(8w$s4 zsSBFa@Z(Cn-KL+n|_36`Ky0VMaEolAQn`-1l-F{+e>`dytwMRl-h8v?~I8W9eN&e#+1BsxTFk z7;iCXPFpuXYvCdjauTt#%5s?I#0-}C)WVEoex^WvGgV$kq;kJHg5gxF9}6N~YrHE3 z@pmiw%y4n(l>=9~^UZCdw9(Md2YlrCBc=K`lPWhz>(@&!=ILe`KGc?YiXPE))y``r zyOe{cjdDjG)&W{3_@w++1HVkMLWc(eAqpN&H7=$Qs}FQfNgq<0*i>qpm{VClqQKQ7 zq78fm{+M#@)t1ikdBk(VE4lsNyS0FEwIU@6Zqj%^#~ECTe?E*A*t&#|TF50dZmu70 zer@CYvP9?nHogawRkX-ze|qPb9NuOc-(*1S8Xu;~Ehk68{ZV-{+!{HC z?u5M_eVN8&EW*uU{j_Q9p_5GT!W}(1EnGCzQC(((OVCDr;7^%|7NT>7rbpvjoL!vL zA!rQ#XH|v->bRYVa2uf|ZYL*U!0Si9BE47!_Bqb9N5!kRSn_#*5>ZRZQkmo5%g@cL zZ@WCL))v6s9C)@vJ1})8*<0ihhVhl<=85Cj0CYkp@@}QDB}%aR)}q^`HWi;#?Q)f_ z(h%8vmO56`lEzaq5$=guMC#xaJv%H`8|iIT^0Qaj#Q>&sG-Z@b4fO%CB$(dR_Hs{* zbaHTO1y$pFT!XG6=6ecUBqm@IchzSb`NA9Qc;Xm)ks??X{v9z)QL1) zf^HDup*w>HPDGrkWQak!VDRlVa*=rP@Rx7&ckJ&`F5abu03*S=e(m8g^~3GjD`7mn z+wHgUikR zF{$ljd>xQO7!=UO45GWOvl&Dyj`1m4uNSn?y`E%SMz2jT{p}k9PBhKIt#__6tUG?r zW{%6WF`yngEwumqjdRxMRWmj%BCTgf(A0lXLF(3;ftYtq@AZ$@Vnd)9B;$056O5S+ zN?)f-af2!|)Ye@Awwa@TT^UmnZ|(WbcV@4-k}`JspBpGbVvrO{2SuxIDJWsmL0{Vv zV15$8$5EtLX%QEwnkqeULjdryz=IIL@9`M53P0KltX0 z!YV(9Os@QvujwqDf80SAfi6?0G;AiQN(|J7U1UwmR92E&6&O^GvK}+hSoF!TEy%Lh zIrvOYE~qR04!1Ys2Id>HCRkYn2uU8O287QPPP298BL<}aIDXm1e=7b9YC%~C9} z)zJ$`3*(F+W08{dXsbdrrY}m+h5g`tUdS+Rvn@i_J;S=)grG@dZ)%A}X|>s5Ut0Oz z#}=<4zB4#gM?vf!SY0_7K8Y#*+zDXMTJ{Ky`^xdrC> zt@*SYF%spTc2MmH+fZ;{B+f9N(xgz~q0e*d%Q4Bk!>|oFp?|O7$*izO%FCN5fpX!GVa`h#{~;vgoll>J_|S(R(~#dLz-@Db!ZWI?I7O!+o*Y*u^} zEVl_JMXS5Mn7}{Gyk(8AYTI$6(|btyWM`NIwWZU}g8JXn*_K;8`Lf=G9f40-F35lQ zR~`x(XdiWYe)}6;=M6j&pY8M(+@vMz|8?mQ=ZY_J-d?ci0B+jR8Eh6Dxj2Yp2C-6s z^MrK!Yc~Xnisf~6r)VyJ{8n;-__Kgb#$t@U3I+onHBs_H?9X(}`_2ZnI#=t1UpeO+ zBj>v}z?xV^AXJLU)PZ@721*Xgf3u!T^|dr99iX<;I$G`93lV)8J&PtAoux5mtSGkq z4*PR+^KO}pEkR=IagpF>50Z=!Y8JFMvyP}b7GnBlNS|N%9KA*eEU6$n?>X?B4{gqv z%ZZlc1Cw=q2Tz$4Z{qSF4U@~m*5Qwuq#x8;sT0J90ZpQfHTD!IwmLC)xsJ;E@afJZ znR0EhE1v2N@nkFo)sH}IbsYnPQ&sR@&c_i0m)vS?^h^H>rwqBP_ z*}u_Jf=>cP-Dfm)K`wavX^raYe@<8<5v=ciU%GNtKnv@~36LFTcpV&vrJxdnaYdV` zM0@83HBgPP)isd1;;7EH!bT|T4;{o^1iKspAKzY(B-tXr_32SP1Wj+gxsG1l6lNu3 z&0`{MTq@Ztu<(%ikbAgdSgKgZ_Svq#fx9#{V#)7n!U{oeAWmeW+~t&>-?VPh%xr8m z2Msy>;;O?7(_hoM2ubENRU_+0h7qGU)h?*T?6D#_^MWLLwY%&y=#<~)G z3{UIsjfMydS#uyV(d;g>Niom1>{F|pwW(K>N~6Ia5sdSA^w%KqHIpHm!jj?)YPTMR z7r=8vwBlmgXg~5w!4`Q_mtsX`N>6DE;B29#bt_j8McxrsLKol|tm5Q=19j%_9>$Rq zO*^7Ug&e1*!YIBM=OoE;1aeH86j}M2Tk@g#-m88-qLuwn(XHG)mN?xGX-2UwU_A6b zd`69MdgT%p#?Ufpt+U9b?KffSR2HDZ&z%kw%R<|O{Ivpw96q*Ec^G_~Y#vsm;dm;7bV->Gv=}z?dS~r6wA^VB1c6MJIRdlxRrZP0;jm73k+qYI>N;~g%e-pHjBfhf zT>L>2bLH!Y^s~T}LE)*@3p7rW%?0WNxZMmgc`8!f%4cSdbTN+bpD?u`4_mQ=?S7nB zYt`cpyneLnED(hsmKLK%Br|+4B~Vj7b96P>84aKeK4-{^QdDT?Wrb+h_rEyvti4~b zJ%lD|PtKB*#0-9KU9)mVff^NZFw(v)Dw`yv@%$Bwgyj^`oqHq07XhA3(k$rzi!chU zRb0G@7~vad-NC@51jjyey~_a_>9^YqcjI7(&8i|VT~aH^dHzZeI60ONvZ??L^;-WA zqJ1?2rP`s)9GelmHa(oZXPmkth}SBC(BLC$Gk_5#gGDDOsvXq=DH zJ|1T>wN0(GzhCmpDeI8g8QEiY&BPdMw@LY!P94~mxmnwARPG2VrLV){_Wn@*@@>O z3MV&rFMT_buLx5<5PIhAsLCP%S1}q&ya&sMo;nW;RyM^ciRH8({lz*N2PGUXqGV8c z^}-0Ze%~H0QrriJUipiCiSg#Qtfinl7p36Y_Yao5J`quA>{PeENDnjY5_gm}_1L^G zb>9kSlNQZMRt>p~eN5EWoCp3$pV&VoO|_KrK_f5`U=CQ`T_J{@JRS5VEVR`ie!U_| zge_hevbAhUEd)JdYxR* z9IKbP8&$?phTTMCtS}F(e{)7J-DtDoqcTI7m@;7nT3oX(iH05{Wg3b*3diPj5_AKu zk3^)hXW~-qngaONR#qpIOgtL$gq$XGMu}3Xj;e!U$w&!*#tAVOU@; zWMsZ+Ikpm?pA(kF8Aen3(HFGfgACwR5+bmab4Od%n3fSi2~sMTmGzvJ)=#>G@FiSYq23sW7BeYC+8+YUjN_UdlgT;b$E0 zt3a?s;pKQ|`Mf@>`<#~0S<~F+mkJbW+&z+!$kh~_!o{Md&^=B5N-||td~_}9r`?(E zB0h#AOE$d|8TQ#`%ws&b-nClU^%n%c^I9Wi_s8YV7q>9l+g(TyFn8doo|DFdV-hge zaTH;Ij_2nNoCK)|tZvUg`0q^LRF?$=p8fP;-PWP8;cOk4&bkn!8Sct_tfFc1Vr2W@4He|!mcfecT4k+4^jV}8 zb;sb50uQEiFFJuQQre7J1zr*+Jpi?7aW9sLB^-8&NElDqZ(Mb*3&IjFlP$Jf`k7Dh zkva$X)OKNi)EX`RX7w=c{@p{%ro396K)Jb-qk0`SR})f3`66RGWk2(q@V zWVkUQiO&jogKCbuy7|2I8{tsmo0c6XF<<7PP|OFOC{>Zker;WaWTK6SU+dibtk1el z3yP-PU465=5~EImNhpbzK#<)B6MUIW1Zk3Nw`kgmz7=9PiwteJDld|Vvo8&(HJ)0 zf_-6!9@g@Rvl#1HHg7}01hjRbBx`rsy`tvPUU`ezVeqA!>yh5Fxck{Lm6eka1sX>T z(>nD%j9UXYaP%i<9@v|v!g!N0qL#O3lb~kFSxd1)dFkrx%rYEa3~y2##=ARu+ zU(&G}2D*Dx4rH+Ju#1Ixf2mG-gD(*7mo$-}PWI2^%1pB2ir(02-%U`@W%lJA`i$T< z)yF0klLO5!^>xAGwb5~yDBROQG_(baNu$Tm1BfyH%2i3IH7`_9aTZW}in~5+cAb%d zRw%M-uBy9uh2^%A;hv17d}z=`)!;cRc`^3`arD%oAx*>PeRDLs6@*`PqQx9qqEeFg zGKD-k+8lRLFEt&<9eI3#8Ret`1aF4!*ExSK=tf!SVR=@N#?DIuzSO29Et^%~x(ET^ z3wAcodz0(M7bG_`==^4<_QXy{9?1xRFdapBIz^sZ>n!6B1X=G468^7IlL4=i!Cy_x*yx!x^9m%ER#2669S~QIxyTt*VuqO#2EyL zhe4|XBQ+gVolIEo12`nUkD;sdheWMa2gD@L**-3C5fMF&P#wp4R~5RQ=_WYZzMga5 z`EHm|RDQj%hta2)uECNI5vmqPNnWsrqenLbAMWk3NdFF(-BO;m$yw~di03u}lM8v&K zQmfuB97%C|!eY?nXDQ{5XQ=AY*McJ5@WWG369)tOEYuldjpFwg8!t=XCTwa!YKG{6 z!e)>Jc|P&u;oleQ8msK_%pswZ>0G^4WZS&moVVUyp%&3?E`|+I0&hbk&1UO4?MKqE zlo0e4s6Gvq_g7X5gWsY0-=!~`&tr19RzKqLyhg_vUPwLL1_B=-5mYC?w7^*-#%XFf?~O2S-UXcnW6=Gb{@tl<(r`<^h>HD4gQ~i-xY(szNnpn6 zSD!4)thZ!IkxVL!lrI0}>Ez~w{_?>ILB2n)pNG z#P_}e8EOuu^-l1&#`UQWIBe$tSC$u7EHKU8gZB`w{=p-d4}L;2B^YlAb($W%^eA;X zcZJn_?nmitr(2@CT9RHiS+3?Nm|I;}6QdnhQM4j%Zuj+uBr1Hyw|f-Izpwk-zU;U( zYf;R$u_}~{Y&A2m#scyHtN z&&48wyZyT4wr0xxrUYReU*OXHviM#CU;D-HNOrp?Ch#un=XKc-QFt|yXHq0@e7015 z%Ogrz`JmHG^&IW>*eLw(D7boCY@(^X?Hfc-anNyr>M?)PcQ&k~+Z*InxV73E^D>!Ferz?dwWJ znv;YKk}>(dPt(`D#;4Yflt_IMLz`;h|L)M~d(Ry}aYUQ0#N`tQGr*`>+n&CQhHjV^ zE%?G#vQ|)k0Z%TE81xX$Nef_TfEgzk@RlSoHdg$Om)7%a1_O4>r3LcFg--Z3HN z8TQ}qw3C;Ob%(>5MNEi1&LhWDhJ^&83X1SKVHge*uA!f+ZRry2&tT7}#yLp!WHdQ) z+2cqTiXYUB?56+;(|#TP>D{pZz3YF1s;Q;rYtQ0wyM!LU_7N3 z?9PC&xP`oqEf+oXW~%auK&rYhIH%|W@U=HOU9hTn>IE@A+YZkq-|O!q^AN6h!){Sw zDuE=ql(@)^6KoNLRiG#Mh@bhgU%KVB6n6*01l zrfR?g4h94>(o-fXvWiT3h%%|DG5ub4sV=`9pbhYSl*4{o$dQEK=$3F93sQ(H-WISL zSK+w|EumCz7`CW((@KCP?4f-PD`+0GsNn$E~2aDE-xF2Sm zU4fX~<}*iRZ33bLPTglP;-KD#=mSuVq2zsFZO8Rx zV5UN_&M3r9QC>kl5#!m0#XhPFYCc?8%fp9_$?-W2=r_#&0(D5H8Iu{$zdXAuI@-9I zToZJ=I&M#lj~uHue$eOGNO_J+J;|z#@@wI}<~RSsNPi0r`r{+Ef9jvVVu>W%Zf%=O zlT8%?T33TwF>_z_2F4pHdD`dYhfT91+_vdrWD?DplQWG1p{|b&7DF7Z63oEcb0e&G zDwxt-&T4DBQq<>U7u9k?35$1AA@m-dA5{~z^W49vDO)38LStN+8Bdh_)~Jne&2{{9 zpqw={rVq4_RU6|qaT6RV?p>38))QW@rGF#He;$+ig?jm`21|kC6cb%YYSr6QCBe0E z{+eXc zXp6{xUSqz(elCYjW=z&07LzhU)FB+L>nei^v0gmuoQgEy%2chgM6c&U}(} zZ7$)Ds1zcC#Nve@Ij9Dm|ySe1|G)ZA!WgRODZ(zm_&1|8qoeYK!qut zH`}@@Z>|KHKvvz@&+JM_p5Cm#1OFt%iaiZ9Si&I z!y@imdAG48^o8}^#6u<8iQ;oF7FX=7e3(Jh=Y4& zrJHQ#PbK<&3YqRG+0Fgdy_41k*Sk{(W9=p`jSntl`w;rQe--T1+~(kq?1&N=OE|hwjzrC{BN?(+4y(Li&K;ke`C|V)R&7nnm2oG zv|<|lXxmCoIrEE)hB}J=u42KFR!oZK8-J|*i8}W*=7u-E2PY^wvWM*eyg8aw2JUZn!AZ7j$#mgeVhgp(kGHOAG*T+J6|`CXv%7dD zTjf5Zp*ytbq+)5vI_w%`SHtDaxBb`qQ@itp=RH!{jB#?Q=^OR5%RbL=1Es;oW7q2C zO7Ab>Uy!Jck_Zmrt>a$bWiLzm1JN+31)%T2O1HV!TZYJ^`csfDEbG$BgjA+%c2{z* zRk7<)8H&g3k`kj@CU)@3<;6FKDvW;~@%31zrV826^O{Wtu zz9#?_8F1N6fqJuiwJjqcxPjYTkHt<&5jM4pc^8DpDoNM?MxjH>1bbHHHHlLoPWgNn zv@IFLU|K_sPliHNX@8P!jM7zeXhYmx(y3atdy3hxl~pC)Q00+ThTX@`Md-hpq8@Lz zTyW~)RRODG)u>YuCPP{-C2@GYzzmf$_AkK#WFYeQUQR6QGcBB_2rigF<9_6mt0%Y6vNAs8y^hVBWJ?yQ@Zt>_Ua?jN>uC@M6AvmlCu(a-TC&^mv4KHp53 zVrLX32bTLW&-e*_Mzmzz<0QG9kUXOl$O#L@dz2i>WJU0H669R`8%hh1w}14r!T%d@ z{`e9zDh%EW zw=-SOmf<#8S#4pGJbh8=-dXjU0FR3Q;x}Pp_^*BwX6FADn*8&d(6cf#{qN)d=Qm+s z=3x3~H~GK#O={d#l(lVASuvU0k@5q%Lb|%F?8_j@w}L=c_fVPJ!P4*tNYw3L|H)3i zjy_F0&7QxUn3mK|yR~v@=6qi(IhAi!mNSF}UP|>TytvRvRZa2n_#q6fE-tD~?W&CD zs``unwAzDqPjVzwln>|hlhVR_aX}!V(c|$$K?8~V&j46k1E}ii>Kaq}xAz2vAq@{M zg7SX~$V9~k1l;E({xh5?#r-aKdvXdul14+K1c z$D-%g)({a>mB8eus(Av$hiL`o%2)$X)|RosHw6F<$5@-ikOre~a|2rY@&QO+-weR_ zlXNom9YJ*YlMaxL({CED##Y~jv9=!>F!A$u@I~bnvefYQ>cIL0#K9i0TT~?>{)0;nO$sTEuOWw^&eFf< zy^3UfXZl%A!tY$yK(~dK6rRh>A8Kv;SdLnW9stC_wVvVLJ?0zoWDn$>3P#N=JZFTD zNgsqgfJQo-pH<)NR4rZYif{YfEXV&>u_q!ZC}vD==fzLsn+PmCifL^$8zUp-nx!;j z%E}rl9EWi#Pa~m)sST_i=r=V;8|O#q^pERDl|ZwfY3L0L1X6rYP7D|T2&LZh1p z3`G9-Zo~A~Ez$cf|9xM`o*z`tFPr0U%Kv0=|EW#%3QDwXtdpg!^}zOSae&=*7)f3I zS9yTt0lqYtSxIGoXU2w64G-`6Jie=1P~UEyf5GTA(2`bL!#6a#6^DkWrU!tJzO?`y zQUlwA1SsLrn56tWB4(_1e-i!bfdg`^@m=@Se19!z{3B4nztD0*NrtC4Zr~8I{i^z1 z^ZjZLQX2a#^%Ii+BC08wz1>QsN^GCFtVOGLwEwy)c;G;x!N7sh@9`a2P;3PKIJ^Oq zlbYVb-WeJm9{|!f+}HQ+jIJ)bud{dm@(ug~8GfH?EDVo89Kg;4GXe)x*X8@=_VYFT z5&)ooK}8qmWbmBL;a7B}uLbCu-QorESu&}Sm8nhsYJ$~0|DL|rX#xD{3Yv*OHM^R5 z3#wLJRMM%uYw`>ue(K~@H}DF=iL_*SaQdda+VoKxRP~UG!J`VwxDQC=VK}oZRHgmtE`WC_TqGyZm1F{j=L4 zF&&Q)Bs^jlc>8Gb>r)sN*05w!v(EI@gVpA={q^Njoa6Rq&f)_0p+(5drz8 z3j)(31@e0~)m(aJGa)07(s?I=13rcfKAdP}WvprN9yyyBO9FjLF}!B5c*<^n+b~N) zAo-9fnw_HX0BgBpO!Cb|G%!l3t^hc-67uEC*qxLZV19UbtP1$Iz!A$}k0yjz^IazZ zg7l&zPVQQpK~-bKj)yzQe)8=?O?nF6aU5Iu+AV|-gGs8*<@g(+NmDs3uZ}l^wfU-* zja0%Bv^y7tHFxKd3YlJe=$XQ1715F_hzfNaF>+1v_0YY@>mG#7Wb=cW4o;EoaP5yJ z#r-Otp~U(1zV>Cr7xB6OB@%46izVAW9EU`ZozT`$%>rqWpQ^zG48I;mgF1lC%MoRB zf+fJ$OeX?}=Lt(2$9`ffJwvIJRWD@RkQDd<9DQaleMAXfT4NSAVR;2MYdmj9M~U2+ zsaeXQqIGkkEFWlxtM}^%P)r?@ZvL%&)jRY+ZB-_-!5vSz~9Lmv9ZREYp`$p)W~i6ta5Bk?4M4TJT!P-INt zc2y1wL+$n!Fpj-?oukT{NP#lIb9dSXI^r2xq1d}-+wsxb-ToE4c|2x-g8WHmd){K<|L-Mk@q3G9`iQ25Z zRbRMa$&TXdu0UoEvj(?D!cCNR>ic0`lDs}X?<2h~CXc0rf(ocXN?=~m&$f^rx&RXS z1<5cB57vdaA7NX?qeJhJp=zA~FcRJR2X*2Y)p7VP$(Wz(%Hbu6BFfm@ey8Bt=?k|X zH9N1_{l#F%R=Dad?XQk9DZX6c8>1UONxWh|GK|ntq8oeDF%uo_jn`TQ@t_clH|ytE zhv;~7+CZP`$fSTJQi2h)onS2b$$ABtiS3WRDC+51B`bXl+gy zCY&&r#@6uBCzOb!CT^w=y0=n;-I+%&&0;|=&p1^ck(a}WScz5B)x2jl(h8ws!vc?= zoi44(*w@6QNeW@)0~QO_!cH#lZ(OTx{B~*nCol$)v1&tVnb(6-MPfQd*-{{RS%b@JTI}@lUinNmMh;$XNx%1MH1fGC z41n2=)1rfo?4 zPUwE5BK5i*6!XrM*9*lrgaeDWCiL&yNK90I&Zp5#YKAV?oTzum8xzmd##eSzf=)1j z;AFvAJqSWKa}Lqehw|`fAaZe`M)uRainjo#nIN?nPIvz-$K|2AEbaBvHWE- z>zcNn&m#)m)FfuivRN|elPVFR%+@{*fs_4*?KK~!$M%hlsTD%0-?py1g*>f!-N~_J5nAYYn~oQkWWg;bGglsz0ohVOt9Xbw`L+&(6t0rP~<`rYX1Q8VQ5W3=Ycjfzp%gNv7> z>`UwN?5Dc!OWx2%s9ExoHUyB-r}x@=VD4ID-Qi9^Xs;;RIM9Ii)wt)u%Ft@Q0F34N zo`I_~B_WcJhfX-02vpRfj?s;U2DJ>GIs^+^uwf$pTCxbv=OALdr#L6{=Y6i)9FjtD z_rkHHR8!_Kb(;u|($ped)o?+$yNwlvz}@hEwsBftn)p3bzaA-Rd`5pc$CP(%ZX$th zPYg3@^>^7UB#SPr1C;c0rt;TFy`Xr*w!p&2EK8j+&)kBDIB_kik} zEY;Te2!g|7HdfgW^=|3Kwkp`~5PRC61{Gc#>^jGrDkr8V1M!<_1<{qoBHRmu{HkM$ z0=(-Nr$eWNMEO;{-{>uIwhC>ex@IM!7wbWhNnnYe8RnKn){NF>hUuxSFC52)CAP{g zQQkd{9^*i4#W!TfFHO;(yQC?=`|-WB?c(;9a@1qR4sc9b^%5J(B#Yo$05*Z~sdod6 zt@KD8(uGo4c)D`aZ2K&f)l2q8r^?(G687QDlDmUx(5}TUsv`pi<%14tfyvxntADAo zJFOF)mU=mQgzJ*3$5=^gD_34lSnAirWGalX_5)O-XW<+Y4&EQKh6GIvg7=5HX=`P= z&Qzu8>NQYSXgho_Uy*rboGDk%lT0$6G-zPKOqW$Exh>dXc*8wi{`Je^a?tR*ScV;Z z;HdVFLeuNW-IMMls^BYTR`oPI)b69tO&z^7B;jb?*v1QGDF|FQA{<2)fZMHR*#N}Z zsUA7qaWOqx9|=@hJmxWZd%4lS4(dpo;z<1=WIf7Uy|7`l-lZ--RByjWx;SHcu7T_O zJwTgxuu5?$K4vpXo70X9YAp@Xdh{&+%BW`F{Xove@EkhGzDco(?HB_?8aS1D7@!-zN}GpbrC}hiTf(2b3JNH1{%m&lzw`=FC6A| zM>+E1eQW?y&s7lYSa^CqLP!M<{#6#La#oHt+?YSYGU2lYF1uYzqTQyk z5m0cpUS+9^CsS*VJ55u6?)_GRF)eJ?K4rGu1cLza3De*nj#6Ow-8HM46Lr0VV)3S) z@jJZOJ^&dw_9tNPwEN(Kx6iGbN3X5?NRLME?zoNuo%!+@?A>GmJMBhT&O(W(A7!m4 zFY#_jc_tYu_1Xo8T^-y-nse5oI`Ruzlu8E)1Ap~Q8ep5H_9GbUA?WMr2~9&W)4 zkPM-rhFwP;yd$y+ZM>yAjJ#2pkqW6k_BBCWO6P zIC@3^28Bgc_)FX`MauEjIICu#^_Tafuf+9qY7zt%SUmUTc9S5oXC+oXpx|q?8DfpZ z>*_GXk7uOD;*@_P=qWMboauHkBv)p4ukZBx?wYx#pO{U(W3{;4CP}9!n+)+#ZYZo90`kSRv|r-U;_2NY}Gpo5HY9XzTd7 z4$GZ48VfdI39uS&m7Jg*Bkv9c*z;(a|!A2f37zl(U8N2oH z)YNksrMA$dV0;7sOTq>p?S>8lF>`xCVA+FCR+I&2#FJBtd94^rk74S&BAv@a#?=c` znN~B;B4jBwWj+c(7u!69N#oSAUJl=?hmfTdg&HfNdd_y>`>yZ02;TzYH^ zeBRPRfFZ3umrc1el>kxfWz_FwwYedh;cd%^l8c$W8_^I^ejZr1s_>+QJJBu9!r=xI z7~2q!bH9=W>j#hnf4eE2uzz&VB6dohxq7g+lJt>or6%{m$eyw%E;5(bQ5Q0MK@D|^ zD2EPnJnDt|Q*E*)Dey}3UKY;}DD=)T_2L|g75j&6(8^UD;v_S(TX(yIP%!i7~Yh*e?OEk zwxC`+)9km6#d=BlK&fs>i8wPLCyaY-ga0%NyUFyLox`Z+FcygRTZ@(56{wS0S-m!B(%l3TRua)E9_<5P$19mQY|C5cZp_PiOoqTutOr4IAV zI3;F{N-0;%746;vJ6ieAc%Vu7T1fK(nUx=FH^}ngL;6iNXA3?1A5I>R5xbQ^0jq|% z6-}NP(LAgU;m|=VpXi+1#lt@ha(aaAe|+ z_hXY*p|4pO?azQhcCla>o09?@<$ic_Keski^S!~8)@1`xo2~>wm4F38BOUCh*gGLIk z0#C^FNI2JlGhZU($g%ehsAsUv-b^yqnlCjH!x8eaiUM(MF8?PGbK*~@-u{^ohUM&r z#We&{0Myb9KGMmmtS4(l>Fp=FtM`77P7K!&R3ia0Ekg+RU13f?z&j0nnbqbehb74& z0cDHA#o>7PMJ$U~fFfZAK--!t9oIys78J*)b{La~Mud~u4xJ1}Y6a9xQ~E06U>z1Z zRYzoEAe%Uxn>#R1-?zOq&`$)E3@ZmvmL+&KNcztD`E=2=DgH0AtGh6rNi4;`*#{qP z+b`)`V(y`_mwgip2#2a;()<_((g|h0W zKX?#)pFTc^cLqNUYKG7fuu3rV2_nqx?tcB{D6S0p{@n!4BZC{Nz#u4-br>>G?*ULP zP$PjWjWF1nLu*meiRR4Q#cUEdI{2~ymxf8j0RT=x!KDucb&7xC_S3tNUjyb0-$}ib zRttg^oMuQ#uj-Z;@?8{og8iUe_7u*ShHFJHf;Jn zHC_m=XlBG)!tG+rmczrb9XajKlgd}N;Vx}+?ch*B<9*7^8?!#L6BCpUT1Xj!+=j~V zLTI2dYp22OdUdo%+Kr;R3a#iQ^;!F4gk)IgRSS+7CRj{R`}2^kznn0-E~{Wh@=7kC zrIr{&o*{8t^$n?tktGHUArDD5?IZB)_HsXr787Cu}7UU!@A;eHQ5Y%t)7mCP~l$gZV!AedXb@fT>NW*h!s#M9RV1I)V-M^AD{ zcrH76*X^OG)#I3cp%$3Po|J+)lyqav6bi;v`{T;Rl9Otg-uOwWNZm&Qk^_U7rf3iD z3PjS(G7*Qtvh&k;Jm8U5YyMRvV*l_Q=hL1MsbjaVRGa$(>=}9&o%d%t6ykGS@y(E)0fvk(^fD1Ya+3 zQaW`bjD2`U~NY9_Lw&msXHPGV!;F;8hukv1Y)vyrBAum(ll_M}job zX?#Tdap7w{hQ&(T38(9ttGx-fsoqItcsI5Via>Z(CqVpqA1twX;%6#2bl?@%bi}+J8z!QK@3HTprvjo)Y}+ zSQ*pyrL}H%ym$IFxwM5@h(D;f3QhftUVxOMPPz%hjHdU%j6ty+EVzQ%;?}B)VG8+cCdbDUm+0EaQO6aGOLtYkd{Ps6N=0zTlq!&@8#(5 z7UL$Otb&*1q1UV0G-rJJ!iA*k^QoegNNTJ+V38Kw>Fh?=^B&gMH=~o(yQDt5I8JV0aW-3YuUib5A2ra{C%4Mp z&i9-Vnok*9^_~vOoI(8!Q^9O+J?Bw%d+LkjrrR2+jJy6Z5{b zGwY)kE8~!{GBsal3j;79gvu&(gj_I|VN-$JCe(=dq|IF$XJx8eTY8_Htmd=kgj-s% zuXR;N5P0<>6d0-I${w4l)>1zxJD1_HfeRnrl#7MDZY6E^QjI~FqWfSCBXy131zjn zS0)d%rInlj*)R-_OL)P@oweA7HMn~J?siIn*B-xwPGqZW zDHRe8y|zp_I@!OFe}CY}VjFq}%$RdFxY#tiSMd#OBS#J#kNoeVvgE{{LX)wVlWLN+ zF0*UkVjX}TG#+lP6$ZHWs6560>mq11Sep+m_6f9&_Eg;%v!Ov7mk z+SVH3imIg0U!nNMb7k-V2n>yord8qYUePIK5@e?oBfpkPcQIXEG+wVFKvjE`r}P58 zwnIX|!O!up@SXawkoNBHYt`y&}EG|1w3!r32 zp4%rr5e!CYRj5$TI3b9pu)Ac%8kv>x1)M5$i9CX(ci`=#=s9$}Ey9>CckOmnm{q(F zi@DtyF^Hcp`O)oqqFxvx|!)F~PvY5Oe=$?Ir0q zF)3M?2pal2OK_%P5Q-j7I#ps-f)S zxhe3kMA4$P2ii+mI+ znvMa>KJHiF3hb6Yzc3#j^n6Os4TyjX1k0mxXz;czxzc`1^46A@#j}b`tKEs3ssw_G zRB8GEb#foea2L;`Zcp*0a(RWFb{x9hq&Jt%sH9>Rd*?jOP!5(+XHk0GTIJwUHl&#n z?RT#On@ctlP>Vzl`a^L;E_qXA~0>M)sR? zY2r(x!z#hyv-qRCRAH!=p2qoE#Gu4Z%x&}A?&UXHQTO@y`3_uotiEP%wPi+wL2u8o zgw!Obg5!;hHTWaj$~a1QZcn8X#``QIvc-{P)~F?kG20Z2L{^bUr){X^2ox&~X>2ce ze7cK-Jq*~2Yx3j428q|ShJ4KrVTHRB3wE-PO?JZm;GmruGfPmq_<9BDwzihyJ*J8g zWgS4*lqJoukOB=xBFpHakGyOWd$_@iJE{Bj5Tf!~6vPv$-yJ8de|qz&UPQz1cR3esZ74-va9PL>-R1Uf^`aKVwIpQoW6>-_e z83jSP#1%m_nNf&ERxCVIb8|A^g(cXdgdu>5{a%?K#54?Gv@K~DI;3GsXubTJY=AA- zI8&_Cz`tnVI2@`Hah~}& z>|!v#2I;WP&$ceD@ujDGlfF7#JaGQH7i5t$xViD^luK3JEbY$c}`wNwKq7sh=bsQ>2JCO3ujHJ0$4k%6Qiy zcNM#mM%o+UTMnh9Vv(~?P(QZ-GFEQ%h@ckr4NY4qN6FaoMpWPmb^x@kDeuiiK+P2l z?Tg>MI^ryR5ipG|#W>4!6`VzAW5WWa8W5qSInu-Vmr}x^HNIx@I7dW<0Ca6|D@=Hx z2GNC&d*J61RA+{S3^GySJxXc5M}fbKf+fv^=njpF zvm;y`VBg4MJ$Gv>o(QxxdE9Zi$6=z7&@+NeKglO?Qiw13h*}wnX6o8o4_&)@bWK5X zP4K6_gj29x8EGlH{Lx9G0-iQol{eJlX1b>X2D`(e+KMazlPcq#1%8<|XTGP3G7aX? zry(RFf-E6LjaQc(NZwFhz*Et!%C+>_&Z$}PYav)zhR-1fIr9#IjT{Y3O=-(TwT~39 zgRrG5BE%#)AeqISPh`*4fA}(c#~7rNRM&T`D>}A2jFPW!I)qlxD%F|Sz?cv{$Fmk| zZ5wbv%E3i4qfxKcrJpPGZpCbN6NNbqKa;VIn9m*U{^-cS<8sP`KSS*z{f5iAaG4bA zC%{Js?$SizPL*WQx()~&=cwdXTD(s0$vO-^j_tT&IvDn>7rF^b@9)h`(>A)=dg+mE zNp_daFQn;bz>LhRta3fo68mFu9$n2)qn;j_Omln)Dk6Yd3uf4yc5P09xrGNO^9Xel zT6@x^$=przhW^EoUojrOV$|ki`Ax~^iRkKF_VMLr z=H!(%aGqABSd3lo&0z7tQC#Z*-+0%g7DLn zl_T=#ugAJjTgFq1Re9}zXt61ME0L3*wM#V8cdchTkCs~`3B8+!@>ORW8-%LmK<1I1asm_Qg*5&Tw z-_=Pjv2#JP#&r%K>3-p?as8qT_Ot1eqcj!PPK6^&uvoR_COsSt1OYp;8lTes@2Ff} z#~Fu?=?NTAQLEcLV(f#!u}ibllnmh|FTXBW1$TG|c0>0R{0m?jg8wdH`xfF37q&H6 z^|k;@Z|s!N6U`AW`)w&j|#8HMJBeIYWnZ)vkq8n72@~(<;0f7!woB!b<)p@7V`l*TG#nZouhV#uTlqF)-C;+n?`MIW)&9e$ z=GSdJ6U0X%3VA5O=HS{ZIs|E`*Cz|AXeiDBlmHHJZBwEc+WDci_Fcd6VK3L7A*}6! z;1vDPSZP_wA3ZYcml|P;?mfiPVcTbhck`(!rQwYuRN2WrPjs*n^ zO)rTZz-b)2{^7uzc4`hs=S;;}f0@(mED-CWeDj+GVhP)kjtgU3NilC87qZNHFHJ6L zH&&$plA|E+`!g*u&^fL~4bSR##n|k&Mok4)3o0RLo5+}XbUXf+gn9j4ZK6 zLOqm5pO2yelwDtOvIFVaRBk8Oye&aeG6qDV5hFF;m5T!F@0&r~S95kB!a_Tk(bQfdPO^O-)atURC}#Xn!#_SP>;a_zB4;vd32=fM*K0KR!=IgZINC#7+b zulEVyV??2KM_Yb{Lpv0-g*S-l9V1DayD{nKz6M!{YQH)dYY*R&GHjk!Hx7Jhd=|P~ z+#yy)cR?@0D_`r&*c02ko}Uq#A#zpzu*J+sQ2tjB1eP&_SpklThY#%sP{-SL7384GSpie6-B zvnw6wmCuJ5NeLAs+T3rIY5K6Bx%1Akc=nK*CdgVN^aU#bVU7_q<-Z^74Ia&U6cpztztkg{+5Q)&{zq3c)3g2edgMR2n&tmWS2vreXX`YP zK!ddH(Z+QB&tjQx?;_*3cl*zRyGh&w37dHAbvl`L>9zZr&c@qb?Xgm+sobb?Rfs3A zVhB&?%G4C+1k%A!N6+v8jAVr^wWY0$g^i5met@n-RkdZTC4KSlLkHsq4M86t9R54{ z&*6PwIRG`^NDmgSl@6$`0Z7fw&3%Uqz#v9O7ax<-LglY1q!JYx8~ejY^V<#}-SY$d zj&*Km1o|&@_-)@-@8;}S577Bj^415d+*A+HuBin;ZF5BfU?@4s$rz~!U`ZhY?e`Oa-U%dg^J^&+>QIjs0nHzxe`I2C`ou0h zq%0$3i4UHqe*)-8|M1}96-)mRs2(T-K<9TSpo*yfkGbis>5m+s-*sy2FXcGI(c9|K zKHW>2^!mcc-w|lz!z0MIEENsyhh3LW&8+sHq|K2NI%xamuS<&?^OF}jso%k$#V-*Z z8Eb!905vGNRX@iJO@L_|?d&U=?w^w%sS}XKcQp)KT2}t5-)etcfW~@8z>H0;_V%xm z_o?r>>o2oB|KA!fBr-CuIzJJvpQ%f~zxsz4h6Z*M;B$i?Y-JgjyIZQP{O+ZGCnA5$ z&%yN#e%iLTX3qKO-Js_CXv079G78?cf+ISJ=69grG#6)fbQgyAZvno%<^XUK0ye``Pd9Dmf_b}5AYRsB#5_4oCU-rCkjMHWYw z2DR5m|4w7-TNwVnKKz)h0%U6WU)lJh`icCke*eH2n*PwGcecc2;N0P{u>Zhl0L=Va z!TGs-s)0#cA{rhnE;|2)*?iKO9rr2iSKb^O1HR>DG$Uir{I2ffQ7R~i$@#+pLy^Jx z2c$&3-x_^=Vtc5sfB*O`{zQcz^UXn$*5YHy`QtJXF)=~y-TwZkCTV=9XHM*I8hi3P zosd}tG5>XY_Dwg$SD%3e{-k#AXA{(y^PiezT>s$U(jc_2&&WbF-7+f;({>9imz%Mq zwq1VQ@sxPFl0}iHf`EREksZJ0zm7r4y_OBS(Gv8nSl8-9$I@p3_4R@}UMi1@UF3)f zZvY;Kj33|ystFm|wgP>U0fpj6$O>Ct70Ek}xQ?vpOi>R7ipo$ToB3ddEGzugUm_X& z3@-uvKks;C#(qu9q3qMN$)xnnor8~1lfz46e9A(HMMOhAZ1Ue>Z_XSJ_Q>9(Yd;gG z#1gf-qxqkrO>pICZnSJ5aKv~|Pi}0D`1lr?Me04TgG^TVE@tOC=*d zM(Hr-w34`KkZfEpRe2|1EdS;OXMkJ!32!TF$^zffBmVP6>XeB-oO<>lt+I|kv!Mc$ zl>27)lJcWP-|Bm0OQyY1Mpw!WH5P1yDdv0pj{9&BeLq4GS85iSP7u56{xOQW>kp1~{`QAtV31hk*)+(xXqvdMbP{yEiFXCWIl zF@)u-xwC4V{9eE)R=s+?%uM8APd4%Yfy0aF?C^SzbRI}#6TNb3U=>)J6t%t@UH=;o z`fRWM4hiI>8KS)9eo2l(?047z3v&KK0=_7sW#3)M5S@MiK;5H?E&YPyj+19Gc-oF~ z?busM86OqMmk38=8gi3wi&*ttCyia3B7+git*wFx}e#J~2 zTkC2Wzxkv*W#F!I*o9NEGHJwMFYsnloPmL;#|GnS{Ef_kCC(0v<_13-7L?16%sBVl zX#1g!uF%A9t}n9UJ|GjFa_ZOxGq)rnkkiA5-J^7AISa#6x675%K;Aq|4iW1tF&!-$ zR%@SvD#3phxBbNuj*<3|f0Ys(6@@85orr3L|7OF==S`|M0+x@i^I9r*g(MCi`0YYT`KYg}Q#h-{91%OQu~V%buRaPC{V83CX8(7-i*@#!IhXa(U;8_}o}QpZw=DuQO=rowb{S39_|rNTriC`^y_{@p%$Ua0;mHpt zsxsrp7G&N-L_ft;2)!n`_ubpZJ3go_q4l$ATC(L*5@bvsFh_PD@G{t6!Y<)Gs73?W zZMOQ=Ak(J5Y%1hHmG-($V?^ntJDaHQ4Okm;d=t{?TO5)ysDa&P!>u^z8`&Mxu35Ix zaktgkGf6s(+xC1V{>~|)70L5sND~vRN5|XVpuhDI$=JnA#=ACH=U2mQwb2#HCYT)? zXoW0EHIj2}lld`x`4xuU$Iu=F0srNc*aZJ3)KOdC<8%w}qfO|*xf*6SGuuZb9{~MN z2wt~%5a6-ZR+dbs|IQ08s_UJckDo;^%z-1p-U(>!vb!{W2%6re9fHL3F@Sb*+1%ds zHV>zKWt`ZPzM#=MmEHO@RDw|mnq`|1pLMGqSOxo_>Xg@X_!5dPdoa-P>_N~%xkT?q z7vVxT7~qI7raQT}N}>Qd^BEm#L}<~SrY?tpy^*1Wn5OoW+|4oR-m;BX1R#;Pph>$w zNoCJ+#(gk!TJNjcV3<5JHhJg6rlaM28;GMcI))C$Bow>g&M^^2CN>HV=mvk8wNdYV z4H8n^F0CNtX0;^BE~frzk(9pUct)c%9V#>+`nQ@acA2Ht%8eS+P(L_jpZ(6qZv|Y{ z7p)TjJ4iWma#oKbatnrG_^9V6ghg@O?8l2*NcOn~hr}7dmKf5)K`hMPQ$FvRe zM4oDmE{K`D#lm^AG9omfQR<47noTzKb%EqUjPww7eKaa4s(ZnmTXyIiOG9Rf*vi1R z5v?W9U>m&yhp#(0#uRqUBGH@>8KaUqi83+INIpJgf{VG*@8y@UU`=&pHz6}|X?m(} z2ASM>zQBXcG%K?k#bHF$FrtMo5fcd4NeKDa6EgZr zhb#f~+C!gvUi{fV7?T7Aj}fxTxo)@cOMncSu2u$$B&6CL#pv@n1~g`5+J&9DMd0_x zP~83y69%a;(_lu##jfktIUeb7n94PY@rpdmfRvPoudXNcG3>1YI+@nQ7X;fwV4VWc zGWrgT(Uj$!lIp}}kL){ToqkP}My4RS(Pnioe7fWW5XD7nax$6 zO77XksV9fx#-4@!JjOcndYpVjxA^qv*1Ch~D<)JIHFckNhDVVKH>a?5nLig)G1zHq zcfzhpi&J^qbDrKFh}p_gx!OCM7yZ8l~xpg@@^;9P%u?hX*puUl7VY! z5aky&3y=bep%I!y1yqmt>Fd}eu|V1JW702nbjXn^0x z*x>hSW85idu9l~3X%joQkvXHuFm`jdazlj09u9$`c)9~a9qwEE5&(;vx$}GCDt_(R zo40p4dlFrhrSxvsnfWms+I520VG}+-3yn@9Ahb@MQ=6)&Yq%g$_E6QrKa(B zx(5nc!~VjoK(wYv#?h|osrJ5qf6RS>2!*an|0eWJl7Fw=aM&s;DqK*yUM)O|gKE|( zdYITIwdM&O^*f5|FH>Ff<)#{3Ckzb`)?o;Y6=-Ey>7p+ryaKGE=9=_&55iSl;o8^n z;J-*O-WJ9RYCR#@8}?_YwrjZA<0IaC1f*^!3gr|{z~aAOkkuD`?mVunZ(s?l$V8H& z!4jz|y2Zgi$R>%8uzw_-Y8DV3WN$4(;|I2o~c>y>_HLK$wEIomfM(Dkm|6tcUVF&5Vz*eU?bR^VI z`Mf~EAsR%KJxl9v`SV4%r&fgzL5)M1YOxx?wqE%z@9>YkR?IGFM_KDuTU)3Q+_c{= zfVoCQ?@%^3JxLvx18-%`uXbsb8D+_qPs79;!r8-#J+N~J zPLNG7hjI}W2!vf+1XgQEbD{Nk)A>{YooJc@hDxEr#sb7!d-iyF_o~;HnY!Fs#mPE9UiURv9uf+4eNfEV#)aVsL$6!jW+*`4$mo*0{|K4hpZ^SyZ}dXp{E!`W$S zozk@tf2Z+DeQf+$|fO zM2GUOaL3$}60S#3$<{r~fhDl#DI_-IeS9J^|5;SYv)+)Yr25`?lCVZH9FjEq!*;+B zFCP;rT3y?^pi+#saY~psusGpngD$@WZclT1P&BlA3`+?{`x_6~S z+Coi*3-g;0;_-GIycoF(*X1)1kcr?`7I8RR{B*?b6%71a`2W~@rx@R&aNDzN+uCLS z%eJjuwrzWtja{~F+qP}n=Du}KcPHIBC+XWs_eLSx^JJvW_re_Xl_olM;a?GnD-Z^1TnPw+UDy}Qp_~SXb}>-%o4gIoElMeD95y~ zI+-9(@eV)VlB$gu2<;`Ywn9{4`s0yE|8Cs|0uY`2-jrA2k6Xl%3`-CH2@(Ja>hnSw zIx@P)a9np~g=_aMQO3>dW%81Uy^#(FxBj}5stAgFI(pUTKYbOJrJ3D07$ZlN=VwQG zmn?NR;vB}BaeVJ{}dL(sk^^1t| zmFheE&6zIep~zcZ1xWOtV;aoY-Wi^xE;h~n#+!Il%~x}Z1~849NVnBEi2@{-iJaCB zn<*$fq=!3>On?3kwXOTcJ>8%K`A~0v?Mh4(T9l%B1*$3!nZr$T#wUosN`%fMFw3ZnO-tJXR&~ z-2~E;FeTJH&s0u++BoAEdTb6pU6&&zLn`>tD!o!=-|!Jw54iLa)TFwcC)0hZs2Z&= z?-%m~q<>))T{#X+w5sA!xoXU&-LRZhhMj!GsEX?z22x(dIvA3Y+t#F4<3enak@K|7 z7;tbvO^DcVbu>hsuiI7ltftne_jFtXs7q5U3eTD%$C+I{xfo8Gd!OCZNXkJsM?rry;Du*k+ot0LY;q|9Hr^V77 z!f&}v7mH+2;zK-<01E!f1yCbO8!5piP&uoa^)f)a4juUm=NG#doj@$ z=H)ue*?}HldaI)!u}R_(G*GPUb@73j`s0Y2u^w=!>O=dxgHjVdU4TUdTl%kgX-BeZOZT@~V|+8~7_;DhHI+p^NUc>H4)p8~nX{bddN=IFHJ` z=H-n4i`pED^V7A(!W(epAXE7{h!uPSE>$0kgOg&aCGy=+7-{9qtH!*LZts5|A)%Zo zY+QmV=A<07KZfGie1g-y#3RMWsofrw&8f)hoj@YC*nWDpy7oxHm&yN6Y#|nGi>|pL~GEC4q5oz7oglg)FkZ zxT3B?ifK_kxZRdVQO5QrPWq7;23S^On%PLe$ZO{MR-H{*D+1i_mr2m)qy%2gX~i5v zD-N5|y!kj+OzlCNE?tQ38F1m)qg%VEkC<<(@t#y@PUObX6q#~Gde6FagVvbNBw)r#W;ru5;FYKh^;Ad?GQI0j00#sPuNYgU)f?;& zX&KGK*7C_LK1s;0LO-Z_zq=6HOD4dNkE0aqVj;~iiG6$!`gm&5;>z(Ye=>wn;hK7k z{Q(6vLBR{3-bV>&)wvE*{A5aI2PT^7eX14mVzIjLd9snImJ9@)L;A1uQ81g-0wl%V zVm7K}kM~z?TXBe8SMF?L)ED3Qo)5~)zZ?;#Ni*)x?w1!2o&;9!kOodfM!(D=soLG| zk7{0*k2MRbv2qv=K9Qk3^&zIMbs|ynIPYydknKKjUm($EPv-2RhpGHBM6qY98zL_? z1$n-(bAjsmWiQRB8JmsC1r?BuvUyh43o zLYPRJ0B@qsF*0 z6lF>xr}lC3(D|T{hweCh?V~TI;-y~BvP^5d%@!{s|K8T8+ipvvhNOgBE19u*0^y)- zXS~3&*hofshDjk|79i|hq#@mFO1oe`Hh>@I(uL>><{GpcF?_>jMN924+(a&isQdga z{FK(YIIfZrbd@CEachq>073wnTf!-2!%#{NGWDz>H&i7gC|@GvUsY@m4c%=tcs2)I z8hLeaHr@L-Gs?%p6}2*_<l5~#EvfQeO!b&n*O-xk1#sdOh1hy>5YHJIs6(q-0$I zUqac9rX=i)9F<@}S)W1I#Ftk#Em#GtJH8gk%#>5q_k>_>5tC>JXc6)p6&4H%K30au zn8VGOcOhI#28Y|M5(NNUyV>NO1i_Q2Bn2^zxWM;*u3h*9qO)~sx1S6>?#V=p_drPD z6GWHZxy_Kdw!i`?U?1f`ZYsM0j~rBF)8#?fBERx7j^LLUVP7MtbVNu0(QPSv*;;uo z%A8YB7`6*|RD7*BCl^JA-(XJ^F+UNYe8}cn2u9B28-$HimuvX3Jx?9M*%_!2#5fC+ z*u}q3lQg(hlbFW3`lzR8Gk?KaBP~v;ieg&%hp(2>?bNbf9))euM*dEkS^7;NL{(mI zWB4on9l-!0y%Ratd3LNHPN3z!xd)v*EVyA8_8BE%H?@HkTHFN|vjiu5W9#6% z6=6M;NYOPiy}Rng;b zXyVrTW_40~W^k4cNM$(x`(;&e2z3gO#!_n-V{k{awMV91s!PHiF8-N7&?m1N4IB8r zhPgrW*V!V{;XGhmbiJS;6g2RO`bZ4~_6?*961QV~#`e^)Hx;zN@C*(w~#k z5ol75Ihwd~*uBRsICS@orH14tQ}pS@`Os)JxZ@IRieLyApTy}zqK$}${1%TWhWdkw z$()f>GPu0snQ_seW<*Ceh-enrsiU&Wpdh!jdoxFU?ra~3K4VYWSO=ZQLCfCAhd2xq z0eR9kgxlGaXFZ+Q?o;_FOc}I6I7AGLcr_mZ?`WQ8BH)fnv1n(OWW*5JaSs}3s)HHz z!*<9u0X-=55i}f8Oo} zNwUK}h@(`W^OZ4p4Jt^LX&w}#0%L6GOZ3Hm*syp2nO^&neiBMv!LY@H6gvc467zOJ zj69l|*xfEDoHWGUFjSl!r$qLC7!ssa?qJF=G}FU&xE-t0)~?RJhsDAVC7oOmf`5i| z!e5&Xdkrrrp_YwDNod5HqAf4?$Nb@;0BWdp8?qbeyY7v{jkpVKX?MH%swZ#nmfsB+ zI-no<3)*KoRTNP2b{BE*#8P4FUlLCofdYM5xMGbPhqdFkV!u6>xh86;5VglG34^Uns#TR}^G^19yA7s0emryJDjUX1 zf?H90ho7(iR3cH(Ceq7hJ-V{2c`p4Uzb?LP`PUzYzaQl%euqU{N8RIsCI)3@=9`e& z2D>qo$jdb?^NIgx;IqYnRBYJU`xa+5ZNiM`A1mCL>XCzCk?zN0dNVty`d_lt8Vueo z9NuRS3HNkFGJ+ti9$ZQ5RoDh7SqCy#%`E6Kpen?#shjv%g>uT_21YntoHSa5;=uK& z0=%c_LxR?GC+Iq@*rFIbJxuze?f_h4kr+1lq1vU5KQ463sTvvMbpWrp*tC|Z7S#hj z&{e*ajnQHo(X>Q%or6t6iIIHjpu%_=(tIi!ETx#^b#f+&cNpJ$bDS-@KkkzE7p5hR zB7?K2+6dl~^nL+O=NKo~)xudi<^;NaDan=~R>ZXGk)%GCpT8!Dy7#IWJ8sf6l?%QMKu-FRr4^7)6ISqE$-X8=cnq37)bbD&41gtk1dY0PEDYO&{&BfMl0%B{mKLVw0e3bx z=}b!1)V0Np^D2_XR-0iM)(`k}-5@DNHj@7(QuIDWCa>)|@D8Uah(PIZFlt7qbF1O2 zGDI1Vv8yBaDK4dMN-2q4BDl9FeO{<)YU3|B2XX&+w-K_MMdcS<@uu=6E9Lrf+2!=0 z#@0BaJl;fIzBQ|NZpNCSy{98Z7jqEW39Vp*eH#F4$So$!OwMj9k{6*UBC!!M#m!y3 zMC1N;FCHX6arpNPyx`3=t1JjgDjKjHL^)Nr@TXH)ufY6Jo!$rHdr-_8$#a=Rq>2mg zXvnc`IaU@{NoV%vQb2}OsS2MOyndMWh6T&jQv^HsrPq({oc*)AwD{Vw|SP9!Ofz>N?oSOtCP<`YX7 zgvk@mIQEpp0&;?S3XU2k5EH4}xP$b(Q%VflK>q2U;}MpT0YPB1etO?-uVUH9+2n27 zC0_`WtC0kYy9tL;h;a_dKd=Heqi7=g4a^~-Gmpqkov&XC%jjkKJY&WavhhdXf_%!U z4-3a$*zUSyhw7rE7E6oal*#{8XL)!x{FS#2e|tW{;#vl?(=n4i9rD3&jQX}+!~`YC zPgK97uU(>xn0V}L4(03e0RRpif1hBxWibB!2Mgw^i5E0^@&LNUa*#Z;scak<{8h!!Z;8w(JmpF|DYhL>; z3LOG#bvgQ|>}E-`vgyZ=gZnEeC{Nt=@K^87np0v+ZJ$s`GWqUGq3P7ff{1zb!RL0G z;4YYzCPyZ%NVZsl`sY=WqRYf4SAt$Yv zMXzPWcOhkMTfk%~E!(Kgr8ve+rH>h$1_4=j$9p^U-Hc`+HZqCzBo=@&A0WMH$18YU z?G7J%QQ(8N@RN@*K4T#R-t9}PE7yjrl+q9-75;$G5FQ_#H>+!wvrjw^=#1!=X#(Pz2gPIYH|mL0rXOIIJ{YeI7yY~krKeX; zGgC+vyhL;}?l6bX7&ndxaBTQZw=~itp&Guaegs-Cl$U|>pO((<2T%`CdXp-#3wX;x z{M|l<1ISqyNO)y2@&~@HO~3O(eUr$%uL=p)Oro|;oMv#KG6egKSIp0zq5@2=TP;#K z)4I-Ib^3bbBEpi!X5(t83R+jc@qwp5k=bifsEw8S!okXxk$?MnvSFmK ze1|Xd7J1@o3FnBACy@$S`pRL~toF?vR~0|9c{9lO*zD_(bw&!^Dr;i&vU%fjT#^2s zZo|W)Bn(0p`rjM8Ge(YqT3P!&=xS!tm{Ou%)R^Ufv9vJVuS#}P>GgwVoQVgQPMt2% zLX4x!D4HjrTQ`H>28p0!wV7R~jkR+kojcb{i3 zcrUK>1M)k=hi>O9zwdo=E(b6K6cRd0{g#}vCzT#2l-&GswZ67gvkDm~1O*S$R0hr5 z5=JvGr{mcKV?L4IX``q5)9r>Ig~c%vrHhZSe`)Fao)E^x>C?VlwUF9yq4m^x=}CUL zAzujyXK~0R&{=A~i$uMt!7vK0c53Aj=r4I}v$0kB3b$66D%>c#O}I_^$n9a9qcw)= zR1=o$4Lcz~Bctp4G)^F`r0uq67AI za+IAxA8vS2ll?P!Ja!Wz-r!5^=cR^cUMqp<|Ct~CP4KTRtnhYA(cfk2~FuNN=l7LmzfRln(zSLn6NGh%`Jo&W@tg4Ig$R#t$ZAktLku!D-n4pfWOv1y=M00o5ndn zEV{U{a364iMl4m&%029HCZWwa?8WYVYwt)E0#z1$5IEc~7Fy6|=1%9by_V4C0bvk4 zb8E{$2~<~Gw(oQo+T)i*ZeizLCrKPg{fpTohR~(2ysMHWd*`f6uqpGw4jHSVN|kHT zFv^bb)*!KWNS45!-$E(Yk|0dtK_4d+1I!2)pOKah{o6d#Y1kkP26yh0#nv zy>2?5C<_#m4k{Yp8^_xL%HhkN@k!(ROePo{oZy3K*gC9Yj{>1+Tu@>i>CaGE4Mn_c49YxdMaKa5?`b0a~AYwzld4!4a=Up1&Y$}dxNQ`c#KEFZ2qy%SX zO=9k>Ych2UQCyAM$4h%MaGx3D4)?MJsq6p=x%{JQT1q=3^MwPMO+q6wn#Ey|-)UpE zp;+iyD}O}PkPmWS6I$yqSJQt5;|Ij%!T7VSz`HoqD)EEMF!Uq_U1zN7*M`tGre{gT zGb{EVBH!6dB=9LeN}gQPxiW8mD}GHCd%}2u6Y7kCmK}D>H^@nVexRH-p=iWtazMBo zypLose7=up2h`uMd2%LxYrG;}qxxQ6*ii{N;p{VKU|HjH=Bcn$S&}Np+KZd9iXi>%ONhNhWaoV$ z`+I%`&K*;X;D(@ZBN$6&0h+_0GSy;*=F;{8vi<(?RuEmbe~31R{@WxoZ8viS9Qr zM_tOPJd0NwQ~%z5neQLx`PIcUlz>oJ(Dg^4gHQun*Zpj(P5y{WKuXE`4ZF;NH82OHt(PjKIc{ zNZOpvko zD@&oYxh{UCc}bxe<26eb$KuKbj01kxW)uWs^oJhP;;;14>_KvzL>bZO;`{Re>c=q8 zF8e11V8d$eCgDhii-m_kxJZZf5P0PJCg?b=8uAyz{6fy0OxRo%a?f}wIbiMpUx!1z zx7V8cc|Ht-$-L@uDUq}>z5p&&WEGq&9C>I;a0XXeY+aABxcgkGf3cH(MqD>z*GkG}gd9W{;o?_P2>Hi{liZEwh>mJMTS+RxM_EL{ z<4}z5(D~mBi1NcLpZ1EqcfK_bKazwibxyw?&s=s(q!%~ zd#2cV-TI>ItY-jLEi2(H0d}+xGOxL_pLK!zVNdYcb-U?T%Il&MezL+q-b-4<1M;Bj z=2pj1ZRtmjJl_%d_grwc7zmqw%N6sR`69UJfdS(8v()GJ@J)==@7f#YV_>|vZrs74 ztmaPix%m+E4sUyrEXd(7F$vARw;k$e?EkcZU8?KN$=CUb4DXVF=~H-ysOy{>kME#&WZ5)KS8v{j? zVUI05v>UMN>BosT(YG~du5vNrdy{$P7aH?3cQPIql?WR|`MyaftqG&gfu;W57|L9e zc4=CMeo#kko^mm3W)+*mhDjK~moC$+#`*|L&1I!V7rujsU;Tj)O^jF)yhzMhQ*i#= zZHuPL4nLjEcu+uIE6)3T2 zr@b1E3GsyOL$mx9ZkIUfKxR)@rmPoD4_j0!jn&M{1_Ug*`^HyS+{l(?`v&}_z%##U#Ot8nMNp52PVM&T+))wj zP*e`_M;x^?*98xI%d1g1Q}420cYaiFy=Xleq#iz3Pq(<6iU|$K=>@!K5P}(_d|DtmueB`j|u8hsLalbU$O|wNo|R(Yk*F(RXCO)LR+BV@mf# zA7tR@VuYPsPiJ5Yrmp1xr91jky11JPf_ahO&=+WCwf!eY69n42A5JKcv(jESxrIR5 zE^4s1MC(PkcM8c4_W9AoNsXw!-(X20@dLmxCZB&!vP^yLe%YQK&I0>a1Bs8dVY`wUzv=V>R0Ih>tGI(4Fa+Gl=V@-OmruNL^ZdSJtAzUZmlAVd`eWZr}?YjE-F~V8FJ>_(#EsqlLzI|ZG)bah$%alfGVm>?!a$r{G zDTNkav&SW#d!Y28$%|mqoKG<<^s*Y&DThS5lCD^KtMzNGgi_s7Ia!ihP4$f=ie;I@ zGvV%u)*GyZK^vE&iNYWUy5XtV0|jSB3QnX0M20s$39~FH&QZ3Ws6Cb*!ugp&gsg&` z7}Q|!IED>4HixQA)K37}QPG{cO21fYy4)qsV2;=k@$g_Z)E|x!MNKn`EC~vl2=0Wd z!jf_*(oRyo-CbE)<>eaT<=^o;d=vbfkw%))u{AQ~m-vxnFIwW*2(%D-z~3MWN{D=R z_rV-^N~Jk(E}xV0*SlXDPx|M@lRH}lAGvR8S~e%F5u}fz>Lm2}2CMO!J_p%*`*)L; zT1!$ep`!#Ajx&#}$sL$4sE!0TNfQbDS}}vdB?+}Ft!)F!`Uu44Jw%x-ee$Q;x0lfb zWe{umFTVxrjL!l{@<+m&xn>?_Uq?nruT}t$Iu#8`SXxc`qg}-kB$ZWn3>K)>uqNio z4YtB;(x^~`eqV_73;{R)ot~BTzvx+s*f=@=Q>FSplLBO;(q~)1h}89fzAaqz95);y zAcHPSf>emtT$OIwv;vk%uLK$vC;ZR%WQxP0MUzVK;3Un%j$oLbKf5KN^7`2pWy|Vm zUvA5zbd&U7+eKhTMt;S#_)1Ld^iuWD?LvaZhuPm+?ByHY%GT?qodt)oT3tC-Ze#C$ z^W$BtS7tEoi&qsNyk{c^+X$%d7KdGI2i#YFJ4%hJD^2^0dbS*_Iv=@{UCZhIE?OsB z$nEldi%u11qEmSm7k#h_UZc=5rRT*sUlBP=@o)ln&j&2+2gSV3eTI3(42>Q*p@^!k zm@+vb>+rH4#kMu&P+Qp_-&=xz=KCDWEZuTVSuPH)PZu9Q6jrWQVzT%nbgtyS zsvQTaeVqD)E{Zf0kC^OjzHDX&mFoGm9Z|=ZoOmWDX`$7B(PO7#f?-M5NuD8xj79k) zT?tn&prQIlwW9T+#9>98Y)Vj=TgKb;p-4&MC}vJ$F>(SK7ydOM0bzO^b-a$x6A$qn z()MQs1~*^%tLX2lqi>7c9P)^=b`${|0WIK4)lV5Bh)H4S<52wGfIA9#dr>Q~CrMdA z`gr2<*cReW7dW{a6H|onxh~Zylqr=-tSbpO$7NE12Kg-_ z9rac@h|Qutz$^S}AUyVmFxiZWibdUzGIwg&(U7qOoxv&QjpZB)$9lM_a->a>)bhw0IXc%nsQ5pX^0-iptJY=|2CCZOR8~MG4a@ zEZL)@*?-3Z+y8egm^ZDU{ok;lyG7c*az2#R{-Dq%`R%j=$<8jSmK9r#PncDqI@>aasIOQ%rmeK6VzjFQe>0e=zm(}_V+HL7Z)_<~~9}4}&a_>6zD)+I| zf>yQUQpNFze;efN{ut3nRU#GBuxy}BaMPfgAN<6Ef>>wGQQ;n$23f9qrm#&oT^?HaKl9zYXTP#7+YGHt3^s zP6AWYWUxx)6u3!Pkf@^7!bhk9V=;lSXW|u$pGhpH4Wkb&0XO7iTZqciG}^2WT|^p9 zDQ5%psBt1h!Ui)4Vf;n9N9Ed4QYsZ zRzm}M&{Fyxo)Y{+22=s=G2*Y`9(xM)neNIiKGc7af(4R?@cll_m~yS=OfjqvHDG3P zbD|V~46!N-GOfO>j#hh|PGP<}K>hN`hP_qy;czPVvWY)y^A39vCz#XFa4PxHW=)Ma z0jUcSDV!tTI4)rDYzLalMrr}Vfk%M`hS$(v#(cYrm zC;QB>8b85*)CJv5()OkEG5n5&|72kWQcdlL1%zt+oBv?J*Q--GR#?qutF-z-w$38s zF61w}&68{S7U#u3Nt&1S#*`lxF3euM=3_(i>IQ;*al&V&Ud5nywy8iC!4)z;C*Xhb z{%#W6mNZdoZ7({x1>OOvo}R3{uREd zWh4?9q)tLX&G8*_$pU~!!=!;}fy49Mr=y(%iZRwOX!8;ak%!KrfD=Fk#Hg{!Nr;4F zX-^1#kT_MF1Xo8@@OP!d{;3Y&#~21y5)AP=)mXWyK*lK~QHEH~t|ZH5X65`Hf4qTu z5F*jCgP5d*{B*@rSO=}JjUn8eXnD5l!aAZlipvsMF zhV4K6b0|i9G!78(%l0!!zN-q3yP-#EGBEJVgfQj}b(vU`7DE%6Mtsp+0T3AubQg6r zeR+NNeT;yYAm92_s}-hS56O5lxy(=6qw-(fcYQKN$qqB%eo8aJKbaT(ZL+X;@Y+;P zL!2kC@-W&O#NBt;=!jn@=kkPn+S&|+FM=*O5be~j2>V(DgRDQV{=Y4_jK-U|87{CPrO zuEzuWg2|?3E~JaRieda`P7$ZO!eg_P4c}98K(VeqGgIC9`!l85uSuLW7%=+-titsSHePtxi7zq?|G=2%iEYv>xc9D%??i{C4QA^`NPI6i?Kt?ng{DY z%QeKchmY-w)N1$+tC4BK=Zt0fjJ+js=_)nLHI|A|#4Y|8nSL^cjRsfz#&&4EI=P77 zjVzRG0OVqj_<+$=2@qsleI!jtJSbfIbw&fwc)@sOvn)YH0Yx+-83fT_D%KY$4$WnS zMQtVFx?(aGWGhM>7Ms>W!3791*gbR4i3D6ET|m&VA4?W>w8QslE%YT-0C6-9b~ zqhsdXAp2;f#{ia}JDKC&@Rf$ySU` z14J@|X(mC05HIpnT%#IyXhAPO2;W z;go4qnb~wIOLCV%HG0nI_+R-3e={wn5P2;?h@Td7@%N*2IvRhs4c35J-?#E4-Krmq zPv1B5DeQAjzx>Zjxye6lSB6zTInU>u_-vo!TkYBzyfn;9I$~Zg=12R7gqz(R$>!Aw z$!4lrV`-c*jIS)?NV5US=F}rnE#p&Ct$B&&)fLI++e=cd%b%gki=W}2=Q+b#e@}w- zUPGcape4~dkAY0e&5xJiVca z@6$9zg(l5Nb?Qs`avKU_r?%MkkTjQ_P@E*@E*7+fS5}!L@~pDt0iD8%|24KJ@T*lE z-RIQr@Dnkl;)DDh^sKnY@xQ^3h4H`Q$IANuU}2^_5wp*T)OkYF2}yb!*9Z7R`YR|A zGM?jd(p;dTOK7t;zBfG6Ucbk8YYUntnq!bUrDF3ahWG8R?Lm19uP>)Z>JD7TsR8}< zZASP)mRwYMt6Klv4G7*-`)Yfz#HJko(J>})p z!1u!k^VRQS_T5E7J>OIB1+&DH9w`QWM_sU4PrsubU`OJfq{L-trd}i6>3NR z)~M!XeBaOGOFEVsB(HM?HW57Q61Nc7K z0h+_$Hk898&l&1-a+vZlpn9^E-oo)1An&h>PU?P2WDrHClqqN+H{_$BE`1aQC|PIR zCZaFfAwEA@MK1!`G^^X=1sx%x5iv2cGd6+Yb~G`tfpK5I($sQVkihVLsW}xdEi1ig zp|&gsAqH)LQ;>u(P04SL`h{}Cp;~(cH(8V8q)FFiB3(a*^=!~0peViN^Ul4~=CZ*y zjUpE16eJDoCLa_(=q^^cVt*n63+r~e;GQxllyev1{^x*YPX^Z{w;(E zbye;j^h#}%Nt8Ve77NFooRc|Jf0y!XoQQpl5gM|Phq*aP;Q$~6YHDee33fH{4|@!h zl>=Pv6W*}B{{-6TAILE}IJ9gD=$f{{kYRdY_}+X0@iGNub$QEUvE%_<^#CG{A-G-=K?krIcn6qm z`>OB-7$gv%X~$?8q!WJ~1Y=LrI5t?80ReCxFEWFu=RsV3VGyHj5YxlaK=UBU&d?Bu zKbZh?Z1rsBm~^TbI!GXN`)M%BF$V{7K|*?mkSMv{G$zYI@M(A;L6>Pbpc4?YTxNT3 z!{uJA80O4=0LMTm;Pud_7x-5yIw=Pf6Ot*Y-7ie?z))gbAVHMSKtLC zG}yP;fq`?h5Rh6#VvsAK!7K>R^RbD-rMs|UQjCynBCK(aiz-m|7Ak0+U_4Ne(i70- zREZ$+gMB!30fBQaisA+=`XSuwxS^V<)&?Am-~n{iWN8C#jLP{U6(B9AXD|c(Kfe!9 zCc@CvH<-m}T&&G!l8GhY#hHs_XyMEodGJt-Iej}9#?IE0Iq8W#Juq}gW7r0SX*_51 z70jF^xbg5rooet=jd2@@91}s2t)!)3G4X-EfcVH37y3Jl9M1g`nt}c*Yo&zZB}TLz zQS%@t_)F-A*Y~d{7MO?g0f~3F5Zm*QzCU>D3AOUFFCo;t*)B*Np~&#;Thdr7IGl{J zCfsZ;LYUxNRG=0+7K?tID?5ab02~gZKo~m~oc?NbFFq152T_P>*5>C@>`EoC1-=7MkT-r3xmX(Nh!rrd|cM$jsg<3NNw-q92A#Ls> zb-*t$2>uM%vgjDwHY&(0jSZAcxL%kXdQ_!WL#TifRLlS=2f}TTo_XAlu*DjM4UKja z*a7xzKF@$b7F5pAJ#$MCMqu>MFrZs0qFE|m&INAo&Wuu2^DD^LiiXHZ<+FEm?y zk&qGKJR*(!1jkilix;1;Qdmm2INU~S7|PI9ES3;HZ*zMn@MvOW;Xo})3pqr8#!!a+ z)>tMeatsGs+RlG+SW)8~Awf#JF%m#Q5Qi`vS^|ToHwm@4v2i2=s7?pS3iG>QEI|D} zpjJ@!(macc%W-k-(d+CcIdN{u(sABmr*{87G4TwT!%vLEe8DMd-YnU?cGxlGQVeS2 ze>BuSR<{-a22g)x9`1fbA-t?N5W1|Qs3^jL6K>!CJ;~A= zb9h>2_0Aq|K*RCYNI^7Zxsfrhwp5~GIdP+6Rom}?J@XS#{3a3ZuDfbSNrlN-v<<7& z)lUw9T;y&tNWgO`N$KqxkfxokRKCzPL1>CqUD0H}1z|~Pl@Lxd@#~n*i#qP-qR=op z9xgm(GQT!Q!EWGhuB!p?^Q|1@PZT-^kd)0X$~PWd2|*?V<_vnhcc-Cl&^KRvo62qK zFZxt@w{QR3<2xhOlfzips8?6{C{8)R-Nf#GJ$pSHL!3EDFzlu^J#hRyQNhnTQma_Q zf}9>!lg=;4jwQs*fwsnsz1_f^;>m@{*gGN(wZX!jqd3?wdwV?R;@S1Q`+9KX$&iaV zQER{>oSFDMh8Mt}+u64-qMPg{V6bO?_WuzRK0@>6$)8buK{ppMoH9I;`H1Q*Fnh`| zoYp+T<1aW!^3Nhh-W|SlW*!kvw08-_I}1?^Ri+N?WMlxk3R8yQSn@gHY34r{EO`nD z&qmI4%s6>1}zBVosbbWnwg@ zo;)UR$6&tk&=P7c?YF!cYHH8RKQ5G0K1?7sl-FgFfUn{9*5yjKXGW*2G!`B`k<3`U zi3_SZvxd^WIV#aQdW!$c%{jw-H|wS(P{rWL0tr+N^0D;_-Lc!t@$+@MKR-icC}Ag5 zooLuUHrdm|`}(UV$6e(GR>JQ{I-n+rMH^B@XYD;PyjRzJAFtm%GOJxTI3MDs)n4zo z(T`e-t8NC<+y-HkOEn84N_h3>@Rq5uJjF+5hq%o~_iE+#{qyqh@u~t|7hn(JKE!}Y zqZ=&c-c&tQaZFXS`FMNoj3ZFV@1Ok?G^>^CP87h`D@n71PA~*Soq_{s4K_+g2g^8C;s?aQ+K~`VwaPd<);32>dls&@-GDCE&9sm@P*}- zD}owz<<2Pyha{S~u`*pQ;plee< z^rASoHHe@o-joriITCuf&s`0D&Hm$!tX*sWC22u#XJ!KNdfULO*`U2dVT&Q}87O`s zme8q}aV+I93yNzpOa&f}#3!N>mh^TEP2Q?%3A%pH70VDW|GkY10ygECj4-*@{;}{?Rm*> zTnwr)x4sO;s38lyB25&3K$Q{a&a?3b;!8;|pEFsTD%XdsZ!7FEm-4ZA%)<_{;4X|| zg*(4IlV6M%?QF}o?Mf;RQRTg%srK&N(?Sv9AzMVNWH5cff`~=sOCn9eC4+mHpN2S^ z+ko2aN>YxVm_7q2;i?o-KV1~uofJR0a{8s==CZ#wkT&zSh9R`aAoi$pdXqkSS@jUz z)FfAfDj|rCsw#+`dJv62p5k6A9y5A}$nA@~d;+fmH+^{TbAkrl?=?D=}2u0)t{(JBH@4fH6`_^R7n*E*GGkfj5)>$)i zPWI`zZ?>*7D|Ckk6&|f(UvmZ5Tqlu|on>TXI4s##Ao`_1m_E)2XFK-5h0^#AxK zA4C^K{YF7X=<&uV$cTJ2L7neFMWFqbre><~u%&Fx4z|$E+BP?x>9BOjkDxOudIlCz|@1-_f4B&s2{YL{8<0?jciKyF+*BzgGMky)iv@YoU=@|pLYa?rN;uU4A+RLW;DgX6xUrpc5maARi< z=FGrMTX=f&Fx@&fSfuqiZqhfsGqwq9Z)6xtr3}$;-<*w;dIX_okmU0_JFV|zlmC@B zrAs%8J)S|&*VkCpA~f3e!I`C>0I#s1Vr2W$Bw~T?#W%GT+tb7PbTeF64tRtd&BFdm zmVQj)DS_1B8y16u=fZ*{;ly)NyZQQRl|1G(UwGd!)_Kl9Fn^wruyP}P;YPWpj(gLR z#vPspvN-EGUgD|c`mSkco(ehD=K^SCrlje#EH1@TSOE=_*9^;@LhCWkJ1b{DD~jsr zM8@8`;L>#e)Eu9-^svl9S2GveEq-|Pr4{>N5x zF1?UB_1z{_tf&TuQpE=<5~-BKgi8&>D6|% z3RUQhiLe0X>J^D%R+S6@=HukI-=BBOElto<*M9lbJ{3Qawfmhix zfn=_j^A)qWVlG$A`ij~AqYJx|j6s6f1_C|3V(wS$S|5HTT{9RLpSC^13HDFcuZ>(= zcfC?XT(N8Hx_j-+;|jZ;#kHC1t72E!-#uOQg})VsUGY`FMTV7}h2?$#ch*j2n% zw0Cup!=~*loN{7d5Ez@)gZcRd1w_EYhFA?XSL^@%qPDvQ91gR_=KU5<9xxI<4Q+XS zpn|89lcj}=%hk4N+u3`tV1IvZAAm&{=I()Y$07ja7vvWb1w(`cc)>u(-}eg~YhtsWM) zT7_BxnSKMrWuULPvSmj7%i@Di$p|0SZ!f`wj$%C_ak0;W+KBI8hOMX`GQ{s?rjbIX z-IHUj0Zjn9IsKeoVXuCL8h4BM^~pVbo0>U}>W_8PtEs{XitKS+jmy^AcjK){nIS-< zlSi^O>BiQqJW&GP5dqY;^$`z?nQ8@+*O&$9m*h`;R!yF(gBGncWwu!d#Yg%%hTUJO zZi&SWvFodHHsTG6WtL3^79z} zMXw36V02~BeM#&`O+jz1E>VG)EXx}Swd)>j0U!1Oy^#YeKZ16Hw+5sV)PrmYzG;hLfB1bcm910Be z3eU+lo6d;#jmkJ9SfRTpAEOPa)N*C-xr!9p6|-teo7nDlDK2Y@@nLj%E(vi_UuEKD zYQIEb->6w{rEMa4LTN%7wBcr&k;c=}o$Bp>u_&0ddx-W77GYvuQh(P6bY7B7GmG~M@sm^t7iDxg4+cIi*RTub{9a7%;zC7-i92+vuF?+6)OQkYpaO6+ zn9&9vKpRJe#Uu1UxB$ThIsIR#?y46}Y+clwsbngKxc&x5eU41&_ztV$8ianknPh~1 z#_M=~nOR2CiEjrssj3TfjL~1G?D1%4-8_Jde__6(yS4JO#J(;M@SSEX!ei-*J@xV3 zQR3c;AET%6@}e_EL(KEvdW0=EpB6lI$}%I6=NqIEmJW$v)|@AJ!Oi+7!uwXNvi42J_^KQ!th0py zP*p4Bp@BMXQEfJU@_HQ;4ruCk1x_bISDoH9Ym{f#26}_1HryaQJdhXR=MX~Y#2SKA zdhEJ9(0{jFnZ-%6s|>%po~~S(W;d{F2Y#DGk_qS~W7~j-Q}m_d7Eb+HZnng6>GGYR z-NY`gU$c+GwD@j@*cWf!glz@}G6iQzt-alssnZ(EmKH2Uu~DggVUT-0bO(3b^nmgP z5%0-LzL#q!W_b?z^I&<7CtJd2`fV%Wn4j4p7Ag_HOB(-+5bK8qCu$mZRR;0t#&f$1 zQ-7+8Bi!zLlRYH400=}wy6l4C1TTI1&7Dq!_UY};y3{h9A_F#MoC!l?T+USm+#6TR zhND^=fnW6cs)fFYk$+9qg@BGhLThR_oR;6KM9l&oJWQX4(qPd+hAxDzg*+&WhWM7M zqg!;`XwkvV-sTrke^5VUA1R_6uD%VO(fXsdFgZo>f*)6<_95bW>i(oXVm&DbPV%yHYl^biR_tSm&Dtax%n8 ztKrct%ctCbJm`3LNWY`Po%NvoT@14w-<)%IX_;Gz&R13Pd1_L*gxy0fY41TGapZ22 zmaYbpn=%U6v`6;d{9M-=CyU(>OzOr89e-}1Gb8P+lp;iB1Z5*!r1}Ef3DlXW8@I)9rEH8^}Q1A(m(F!E4Rkoe4|{xL7>u_#aUfuVu?hA zklp41RGBxg&(m%$dn$a~AH0rDg4>7B4IB=y>p2^JPZVA%%UU8vit%F$0FiW5;tyIDE&aw%({H zw!eNRc3%_DsTrlT&(`CribcV<*&FLfjNjk|;0Axw9BRGAgM@dD68OL32X^-r3T)_3 zXf~*rMnc!3RIIuRQKuI3p>??n=(&H^(?T3l4a)^!_^9vG zXZ%kwui(FhF#1rK4GEu;i#5!L#R$YA0unMI;nTABgI$Rve0nTK{44@2{8$j`>WaXE zS5Xl3YJ`m|ws#doU-jfzjKsmBLV_S!eh~#B8Cf}nCo&3x0s;zhG76#)0U==_c?C(9 z|Ez-bqY87e#m15RBEpdWZ|uZ2Gl(=Xpcy!*H9JEWem`$7RfeW$Cn@`X#taUs=%q-e z;J(5oc$^uvESE_XlPfYykk10W{WO$CsAM}sbpGLQJPH(E!$YF=3joKG_lzF~?Tsz@BEV?9zhLS^=c66h8&cR!p2vC%Qd@^x@F7^0IwKygC{yk5Qj!~_SqjQk+Y*%BYcTWz=0 zJor2ppz)G4&EdJ;Oh>eG6LJ+d-)ooHwbdvA#rO>c{e<6$HA^^A{U%x!kEGkDHtlje zAzJJlpdjyXGaybo&?Rp>ID)IOpH zSHGY<6i<5U$&dWg;Q_w@E~gh4aO%oVSrcK>)E-@tq~;ze0ntO4558-O81rz3UQP|z4xlxL-h*GA|!Wi?AI#TBU5 z=C{Qj0}bo!#`EQ4X?dG##dQu?O}BgVZH9Pyr8t@ zSU%G-;3%&wZwdpyUl$NeERx%SN2lezsS~g(hI+1XM2jlw)_i}nkx&56e82N4T-Z|} zI9ki6=#nbCQ_JTj-wI8u?x03Qw1<9DXhx{0obT)A0kinvk(;45p&JBMR3FpniqV8i zi5Pl<43`YBub8K+WNdKbijAQSc;n?O)ZBvL1bBjXf_K0q31^P;BZC$uWzJ0*Maz}G zYV)yK)Fq^Dq)0vCG1CJ0Pm(yCFFjuiU@XkcNWG@Gxs#zHbxCqfMiQGVQr?V}?pN&! zfOwi+I%YcAts|v}Rj-NBupjdojCFTS1GA5`vx(03miqJRM*gG--2?(wWxCLvFxq=< z$_tp^cdaCD-mzz}XYhc8){B;&XU!`){IvUNS3bQ_h<y7ro1SN&*g4fou4 zf=-blF(2dqMtcwx!NZ0Dsv)@PTNGSs;Vz-Z2Td&9s%v|m=HmTp+O!xwlhglJDwTEX zr8(`$vjsYJR$)q~)E?^ex6Mnzw3qrgy3H2101<`D3R1J*ZVn%q3*2Lmxag@rNe@Tp z<2hO|l}GY|s@HOk2hJf~Had^dQ;@1gipS<0yP*qJgvX&0UbB>ho%e+F3vQCG!HFn( z9`6GgLki4u7!zay3Xi<^$@nv0Xqm&9M>`FwoGB!FYkY24%D3Xv_Nnjo>m&|7v&>@7cS0u%sNA44e-y)kvcX+^D%hkNo zyX-}$ca4D97LT|kMF(6Hm-|J<+RViw(KW|eQP|$k{RZs-W=(d?|oFn_j*|i&f@tm zCtbBWG%pm67^bj-*y(OjprjE^HMgZsZ&{SiE#yO8`SKY3{|wLC3Fj5?u72LLUFY~~=-BOm(KcoegPw>vF#Yd&0faZc zL9s8IR=zt0lQ#+gzkMu6GoH-0RNxts95T)Zn~;L{tXV3#s>XLCLYvj6o@eSGx_qJ` zM}ZK=B!zWALKqlqPXZUBP#1A4IWzeXN}Mrnb!?DCdPcU2nujQXV`6=y4LCRfj7U}h z4Z#t${fw#1t8h_m!+5qZh0^%7bNqvVB+w8#tt0LNNzaAAfL#h!6mq0SvNsAfo6W=MSjd;)*3F`I7Zke{H zqZF-V7E;;IjmCfOv9Z#5@EDT>_9XGrSeX`cio9D?x3f@ZDK%LdJkMUFk#Z+U%TFjG z>fK!{o;HNHl3lTo$}X;h%um_6Jx@%b=mCVBIt{4sdFBjQ`{*Vk*}gr>{FN5Tm~8fkPBkn zfefbtc1WDcOq9r{T6UNBgw%WKl2&|Y<}sT^mu6&S?v3PtoO-80h5Dmfsw~qep0zEX zl%If_2ZM!{()awdL&rF{%q+!9pQ)S_i$?jVYZji+d4ro3H0&5~?O9Rkq${A< zKv-0=5^gRpfx3(d2MQBGz}G5&R!4oQTTd>ABZ#a)jm6&Vp=cuHiw((-Ks%Fl7pfWR zw}Xy4jGorib>6*iiArv?J=M{6eCdwo!?Pora`wNs{H5ZN}~-X9WWdFMt3?i)j0QN86GERiHA&E{VPwJUA9a27cmyDp9rOkE$kqf0K zi*$t%e??nRAmzboK08X#x|s9S9X+bh|HEY8>%rloS&$3XqTA@>KhBOhr~bE1-{jhp z=2qiC%z@%o^QK^4x0Z_?33T{@56Jfk%Xj!rHrR zwFlq)Y@IS7MkRm?ykUCXPpBpXzL%`{ zH^nsfqQAb?udB=_b*KQiV9q3~W`$xoh_CkqK6(;GXZ#g)>OqD&_-ruq7a4{RZ`v!m z(RT!IVKdxPfXz08DP!)f(InKPX*W7z0Uc2mLkyLi4hs#~dP>L>;gUb@SoW@7LPOj7 zVkwFrFG>hQbG#3x@f`@=;L{B!5-V1~_d_%sUDkoI(LCS02Za$2a2M;XVLB%!-)^X5 zPRN&|(bY-ps0N1amoOAMI6w^SS2W{f@1qMo4nY8(|b zi4;KSqPS|}5Q{70<1q(GJZb%X(^Z!fP)P{5@FJ8s>+3NuW9XWt&A=NGLQnws7$Hg^ zCTIro<5y{;(1IKoZUoTfy`)3hKREm*g|ZZ%UPg4{p26idBRs!rnP2SmfD{}up8}`J zBzXWGe|(>q0!Z@LrF%wn^R6>`>`P#TTQWeZivkei1=35oDYbduw-(UFzG_rOBlA?~ z&dD;<>}>hjqB5moqH9~lO|i$Ey|fXr)tCa&RK_qKL zYINoP2on06WH|r?NnPzVr}oLj<&zoaz;-1y!_G)OyyeN%EQ(A$b!m^%1>qE)9!A&j zLoee}*;PmjdUvX-#nzRz$3u6wTJ|-J{DGR&gY^BG_w79yzNqI_3Yqely~ zIyfRih?Osdz;@AB%)K3eN^F(xwadul)qutvw%VE)>JK0x{-0d0dP~(x-N9Hlgqp8+ zn4rA5{i5B|hRVM!UK1kPf9c^n8`iN;Kl0`N2!Ft}&8(jNPwZm)Z^)(M>0nAgFK=X} z>|zT=FGs-0!0=ys!pYf%fP;zsf2$2fPBw=B6xn(-bnUk$5q;O{H1g>ugwsA*KNT_1 z9eTBZAsq}m1h#be%aJanhf84+nXdfzm{EikR5iGiCGu;Oh}Gy^6rSs=@12M+9q5^I<&85{%c1_KU&1pHP0_oLj z1@yo{#sSc8G63S|7z_i`gCgxh7geL<@lov$3cgi})LRH6d6>Y&gan}R7*1-uA+T=l zlOg_a!bE|%AIO8?87hF}vI~;zgT7@2px@&y%YeuM=`pp3gG|;#VEOx`TY$!DxYR)S z&&yNOSKoh;2(kxQz=eWBkpu^YwFHM0zpM7+t3k4-3dmc>JYIsj-wgiMgl_`?`M zwr&b&0taLL$v!b4(3u^ShBeO-hG7*t(b-qTfr}+aSWpBq9|APQg5abSvLRqRA09$B z0`@>l!C^HNsTFY%v!S$*BaP-jX87=K(p*hqecHKiy~aEDm_Zs6@oW zN024~IV_*Y%)tJ0g3>T9avIYOq2_2#Qqm+qMi1mEcNf4Silgy_02?o~jSPK)sF9Mn zjD+YJz%M2;H4&N}38%OUAwx2&!$K%0Cnv&&y0MprE}iI$U_bk-K6z-Si9XfH)kAyy zZlv~2X>a~$-&Cb@(RSFjM`r&cpmPW9Pf-HZyM1Rmk=E(Gx}EA%@#Zv{wsmu@-?fFQ zf9mtTx}$eb>fe>NO( z(dzu@wtz^-t%sf?kFI;xR4d&B?Z5W!vIE1tzeJU{@;>&tbyCUqcd$}8_ZsVCJnd6% zp7ztLucfM+PZ#a;O2;+b6}<_p7DI?@u4>D)V|?mks5>!$W&r54!~J;+CW559|P zI?ni&v`&4b+Y2^G-|b!vciD#kn$0J#|CV8Q^_^J3e`bc*22O6u924Jg_L{*LGc24| z{;?|SD2VCWuC6oXC7q%ft@14EErZ;&MF*GjzN~A0<;KbNsd{(4I@k8jTu)Vl(JY!# zr|N|Us)^1v?xBOuZgp*>LFQto$8%>U?2sI7b)`wR8oZg-ZkK+FDbG2OQAe(OFGv66 z2JO3jmcztWs}3E0D6Dn1x+{X`YOIT{^5fB|bsRlL``EjsbGLR1_u(w=+{V2@1II|g zMm=jt$1iat`D(e!l~df6iMCdX=HwO+O#S)Vt?j0eZBMyLhI>n0w{JITCe2-zKuqI& z?S$2cEq^8T;yIUtSF+`qc5B#;uQ{Z;%hx1tM?C9mNj;t~O&E0Exg1A*$40}ao4c73 zmiet+yYtt@d{e`_acJ(&!9y5_?Q{FPL4eVjekI;)?q!+sl|SZpGTfeYR`jK!oF4P| z*d$4pXZw`s6Zfo7GHj&l6yWeLPWu^&Fl>uX-KpmaPIH#H{(~r^cUw2QKB|AZB#G?) zQCTXZu3SJf5J+5c^SPf^sx*Ngs?VYMrO*CebE&QElAfF!2I~>o1~(4yqpGo#uG#PS zY~ySDfaP1##Ei9vsf5-~<4}$0k*O75L_*B*f^FxIJ?!|Ev!dUWoV*+s@P=iRr0LRC z-kJHA_oKP)o|^wuP+wz^VE-$ zty;G*inhnX{;hd+R@QBdq-RCeEdv_NyKtsTB7y`lE~pDPYCQ5oY9CfQ8U9#FKI?EH zEqDl~RVH*WvI zVQZexVg1!=yRwQid-c*D$1gKxRR*e0-iEqrzQ>6I`wxy0agru)`I<~8cM^S;SnbHUUM+Ju8IU{537E-(mk+$CM2Qy{h6)vHaUf<+ zP!v-}9vl||`@0f{!c%4@7cQ#a2JYNo>lB|TG^ zYyJ%fV#WFDe4p5;NIxwYTB$4-?wFB1+~w|{k5OQ`%7cev?ZBTSjGh_93}@D#1SE}y z65<}d;jo}D@Zz=?Oa61gb`%r)iqg_T%p}7v+NlEu%)!*)qbRfTOqL^i&A52wEgJ_} z!6W^&ptZ%9D9JI<83jhm(LL52X{F~VNt_f$=5QAb|1l>t(c~SxG+cESM~U!zcN+6- zmv0{d(W3AuN#>uplX;QsJuWy6+QL|1oUfx>u-v#`yZPJCZx?&vq|^KJpTD!e;7W=- zBL5-_7?}T?F!*0K10(A{=EMJa{{L-;8g*&=Eir`NPjv*jzytvi+P&fhyk!zP9S}+^ z${q^7`D3lkOd?e}OYz@cW^U<>V$uyeSjwppX12^QM?{o@}FmqTN z*Or;Kqaz{P?W@V2Mt?I-I+xUSd~}olEY1m=IsT>~P;JQkESve1wb`))#G);IWGuL7 zC!^0;1Myz4r{VP6506#rWZr-_hk@{4ZZQN;gDK;m?f3_=vzXbmT>K)7{+X8Kb-=lP z436RJo>{Sdhly)!gdLxJ~?3CThb@*;sgsUU?xA2H%LuZt@ z&N^$W_W+g`qWX$_Q!SzTb7tc?k4ds9PCR)$$OW6ZSFgEe+oLC)_RTwRezN?o1D-jj zPODthXi23jqvbRgm;G($iroZXi=D>gsRU04o(PQ$RfciJd5zgM5|iG%GRLl+V2xnJ zKv6mDNs5pJ?yguq5w?=LsRzmxoXB>25fj$xdsm2;- zY*C8|tESqV5wyW7E}U)AA{UN|#hPh^VUjQ(X;4VN%2~Az7*4F@Xf2Hf7g25Kz$)#y zq*Tt!^+l@GA|Se4>*vgfZ~NGv558{Z#yy}6$*i=LAc`Lys6@BJO4WN^^Z?fTfKJ=0 zoF+V~)jK5t)qnO+V5u4|sy7#&@)@BPKSqM(|Hm;S_A$Cs&rWAoRdonGcPw1g;H957 zRThrBa06K_oCaMMr-G{Y({LWP*P`I5$7!k}s%Nbxs#k1@Md2(HC3jR1jpKEucjKAY zsjX_Acdkau#lDq>zHT*b4WpWK?l&nltK*^jYifEb&EJ z@O01a5mMSC=4=F;SMLYMKFedQGe0YjI)Y71j*X&Syxj?bUMcXj(XqXcpd!oNu{g}M zk7iL$7{l0r=_1+Xi{P-nFaA<9ZCLUy*Hqne{lq1yfGR)^xZopf&3v7l9q7z?d+Pp< zdQD4dH&C0>-|H1X;D#ImTTq21qWcr3tYo!0X3Rq(FsS)U=l}~_gk=qblc{7qzO85- zAwG|F(TboRVa9pt#UJT&u7i)PaBKMfXE)fWKqXD9+WD`vb|u;& zX4tYh57Uy?D~cAE*KPSr<7Id*dWfnyjr3*5)2LIf2%gXO7c{cl&(**12qWje@dzvP zf65~%8q&^NYzV!V>JESK$}Oe|_E<0Y)uT zJMv%#^cyv-f8SjTO|N53zd65*S-CwE>R?HGV|EraY+}F}x1NQIp)hgZ=@_SAS}*DI zRR45-AcPVN!h;y?fwL-+*m^GBccqouasSC>Y#CVr=Vvq0K>KK)e(+JRZQ6!#UAXAJ z@c8_LVr2La{P$@upPKHRxRTmsetmdNb=B#xxTf4!ewL&Am;)l~=6!oeOK%E_RO7O~ z00_Zhfr4q)8q?>bxB52K^UN^|GP@#KQT@o^CfZjO=l?kGUYD<(kfQ4Xz)MLH(GsBt6>(g%{R&6}bVG_%1|KCq6{!@A$mG8CXZ-n$ZW7YRaJL zIw4=Z4Qo57YPD(V*{U0<%J+y;{jmp|`weQ_P3YH6Daf63Ez{Xm_nNq}WBs&0?Uyp+ z08SOcH$cX;8Km|gf5Ihx z;>iO2ksrViEgG?=zWaxZTcPQh947{yj^<^kY=D#LbIF6NW zp)JrV`3VfBCxb3$aI?I&FZjvB6J%;ZABd1&M(tIJlC~9~TDlB%a`aN|Ha5 zqKD~ck<}_j9X8J_9*&28O=cFt^+YaI8raW*u#N{|0|0~_(2w$8WwRIl2jSJGG@EIh zWI4@K6ZWRwaU$WK2+*)6mB1KamfnwL|L7VXrW77lNzeH}RM z$#GKWZDy}`UK`K##mksvhOFM*-2QxW@@F}5R&UYiW1D=Qoc4GdsYx5LA*FQ=N6qPJ zlcGYg=MqtYjrTGgo!F5R%6J!eGk1r%^;G=!xQ^vAYRBJlb^G!ZE)Em2f?n~2ydXPx zUC*WKqfO&JdM~DW;nO%H-;LRRP;PswO+xzH*R>+QFZ9Ej+Tg~-MT+}t zqhY}gcIVs6WXr2@gtTaSEnD&M;sKEnh24ZnYD@P)gCb9ec7fCrRCPG8iJS#u521=p zeuRaENbtp9NbyHGi+79LxqvPMU+^?SR|9T?NkJUXV1*=eFW0^M1Y8^=9h-J%#Wzuw zGj5!u%c7n2ir=ZD_cCqgM%J!B*X9|P!?Ntfrjj{1J3PtGgnv@KW1bwJV^?kjS!uv} zo|$23F8)E(Op_*cXPueW#)m4do3h$SSE{JL9c)m@OS!E?CMjXf$Dl}Cx2>P%L&5@- zi8wGwyaXx1N)il*h{;GG$beeff&F13cA*$3cmY?Qi3sN{{|SaECkQSkrKh+;;u>q= zT>xwx^5L5~R&b+cm%znV?6U#{l6bQs{8(<{12z4zRPuo7yfc}@vmx4X5UdK@CeZJA zMhz1zoMlduQSdtV?C!FKC)|2}#Pye&tcb=7eyf-ALgYHK?MSD2Y$W^yFoKWjM-JK1 zVFHO&aoLxRE?}_Vr>f474o)elvmx6Y+@~zVSSv4Qyjwc28gEU&o&GMLrv2@i$>O&( z6_O(eIi-FxnhlEI}@sqI(o4QezLn8cR0c3l>TDR=Sv}*M`<9Ev+qe_B*tG} zshkPd-a+joK3Z&Ym{YYBuX!?i@4@Dp2gep69;w79s>ttML40-7VE&}ywU2k6Md>TM z^R_&ruKn-n#R31XcBzOt715i2`E*Cv8I%?is$1D0t-XTA@1OkC?8kY-`zn8w`y-8& z+WFYHq^fLxap%Xa%c@sbDb#(P8r;PVk;Wr>-0M(JQ-MK5rGtT2{${Z0w0~ikf7UGj zV& z!`X^wcJE{No`2x-f!T!|j{#{x(WMe1tt0UBz#~%tY)~ZDGxA8FFxV)b>&4zDGD2&u z=c0pFt$WU@iM-Si6Hzn9pClQY?53N%fa3aX!*u_IRg`WNz4zMxaxGPL3leqFPnfg2 zl(Dm-`c&rmElJnnm5P6`)V$eohoW!e%0bRyccT7T`Mf(}&V>u?S&&>v`u!A{!%l*9 zdTBO|O;~QXh(0UQ18g#_S#Lf3!$yK$?TIJJ`0e22Gx^X;)Us|_Ur73%F4+Y~2x!9Te)e>EjRt2R4Q75<`gjocjorq4XF1F3#0IrBR z2Hd=*c?e$XD<}X-?{Y0e?<4K>vEkaIlXnIOpiBE?xWXZ5(PR}v$a@k}5Ua-s0H=Ty zddnD~#3J=#Vv+tvF`B66f{;vX>s=%630<3gfYQ+*dDnpq{t|o?>LwMrKA8^mhP=XNc+Gtm$G zm>Fxb3_b~-gnRBQEV7016wjWPHon|YAi!*i0Fh0>!ss{D#JXWUVNc5qH#FPmfe|>Q zqIPm))j-i{!buTb0r@xz2wm+e)JL`CZn8l5k=bEha5nO?tr4xZ1|^KU{>`soBQyS3 zU@5s!0$M!GZJcj>pM&vMTJtp57$7zd-zAZn>Khz46&p!xRcub(69v10tT9*38c63m zu(@cE@}%$ij}5)GQBojMx)dBNoR#0!{%%kHd{u2T(S@|$-s-*~aaFKn0u$#&z(zS@ zmAIhQvNr_wcUst55NmKGtMTs@WmPNbfxUdOpN;|+S-v614cCyHb7Na*V<%XNDXEG> z{KXKQjO#V|BRlVMhUtTX!U@Anl9OXi0m+2V_&&kJnR=+o1S6Rl zRRrRhxz_e!moUs}r5k>+J=9$-M~~2Hm&%JuJMZ9k0^=Yw@87$LUv4oEzko#oEVO(1 z5PMBs0aQNL;Io4QpxZF0K50sQ(>YaYy2iS$qbOEYv+awq0bYMjhw#rKbdlu9G`BLV7z54d!8E;d+f zHY4zXoM<-c=aL1Zsq!e}c1)JOGy~`C)!P&g%@tJ+?jLrCgmQ- zH{;`FCr3;qHwj~o@PhZ~WD=tVkhLPA z>UWOSw40up@67vV>WmtMJM#HUI468ce0mhMZPZ$65l8tO;VH{R<_4312F!Fgt7ZbT zBN2o0L7vKYi1%A?`*-s8kfVXo#R$8ebhec&jZ&V!2!L_-nEtlLFd%`mH^ZvZ?mb{k z5$vTI2g-xJ9{Db87=JAl_=S!1%2527x3+BAe2ZUlt|jnN>@;1A06(L+JDK}9-|G$7 zTxWq&c@OKcw3I`=NK`kaCw36r8XLX>Lj3T}4Z~w|IqTdJbf`DTm>NQ6-8n7_3jfE= zW?3kP$ll#0Yl`>6Wkaz=<`V{+9nfK0h5aI>znsq_H9Dr~~h;?$wfCYKMz%a?K{JX9sNOomDRoQ%tWu_~&xI4YQ4xwheX zb))8l_;E>OhL4`{TF?x1;zxyf?vRNp5|D$Z>H-G`?sUT0?TQ5A&rb+bQgDD^=#tY23NXalLh*=7lzKEUB&PkM z&;s)mus3VKVO29hw%L>~nMBhFYHJ|;bS|BW$%2&cnjN6i5gKOrCM}hcHSUmC+p-)& z&(;=j{<;(J&Kq2rKV4I?{ZNh0H;E2Z5`i{&j_A{Hs9 zHN+dKi6DmhBIAx!flg__JLe}>e1`#zCxouDQ--smJW~Tg98w4uAHgP+`2mxVUD;sM zut*Ln(MMC24`DM9DRG5Y-WPL;ElY-S>^b?)T+1iH%Ki)m(LO7S?6IBeu~J91ns@7( zIrML32OqACv+Rj1ZOf8yq5Bjx!5la3J=^{VPRl~wBwI2)!WO7mUEKv^K&YR0Ibtz> zPT5|sD(L50)aB&PeDrD+M0ce;e-#C2o8%dEFMimC^rVzb<9(ElPQt@ks%-nq4Encs z6J6p~eW4CA!wExaL>u=ADM3?hKyU)Rc!~}5E11kHtyYdZNgnrWIEcVEUuk`9iLJ8> zMCr|+{344St(LMQrQ!JN^cmb9k72i7CPFyi86SAP!s7Mn{^BsbTPvG!MM_&_{N6TLaj%d8prL7}LbUqbwu{k!iNZ8FdL|NK+ zfA;;{*CzhH7_N0FT72sH#9b~=QSUxJIQgb)cl||bswSh(Se~`t>D^@PGPTQ7mRotM z^V=6413t~-c_{pyC7%2KO?6N^l z$6&vP>7exp^s1=}k53h2Ds~up=Go%#H{_+>B8X)!`62DkJD0H4{F7P3!E-m?MBdeS zD`Z>7N>!12Nu?Ow3&(pql&Z>T&)s0DA&;yKcb2Iqq2#dHxWEL33~J8`XciR}Mj>rZ zB#yWTWJGX4DCC+S-p~GF)Z#4BOHwaGs}chmIPoWjd~_;p`#mnZkcRKt1FOZCE1M^T z;P4719rhSN0VcSD*QP2lEq0@ZDfg$VnAN^mE1)Cxyyrb^$ZAVAWi#&GG!!9Do2EkC zK4q=J<4vCZ{E4%FTG)9`*_d2PvFj0;Hf{Hx4A4VXl`-6<6ygiF?|gNJZ>7)3=Cz(9 zOXc^B=wajpebF{8@AsVsfU%N4Y0URVrBBtYI^eRUb#$~WEFVQ4~WKjiAwtQ7Vt(yTfr>N_5kEo zC8XW<&y2Ub`ucrQk9+PTVcofR`g$7avQ8Q*nIOUzU|0$31oO$9}f>UUej^N-HD={s?GF zuJza26djk*0$$jzfPKf|0YSEXxQU6LXDK1W&`pR{yKj}&O>(AcT8iNpF7;2*k&vO9 zR<>AXT#gDxJ-fB9-5VSFSBM9?iaWe`veoY_kU)P+CPl8ER}!iZMHC{)poH=iQh*|= zEHHU&R-k5BJGEL@yj6dY`~Z@0@jy~MJuKt`USQ0_H0G1>FJfetXn8Pyz-#MHUHl80 zv9tcm*v-oEA7>tCF#bsfiCyjV2}wZ901;`H*@IsSx3YYw=5V`n{JpeXGnoMoEcUMdjorp#sLu;P{fG$MLU17?Si;y(* z9oy18m<@6uF*GnN%Ajcys5t4}RyEogD_AwA)U=V-h;BSU54jWqS5|PyLtasd_8ftb zob+C7wxgN~Mlcn*TEBUH!P{G;VNS0e@t}{SA{1(*<|z4EzV-gRXeEwb1EW48N+f#Ol!UKy(c>l-9O8NJ-X)RVV7cudclZw0Ai>X1UkxfQPm#t+Iz}w(b9Y1 zwtaPaY_+HpiDx0^J#AylQPUsF#wGU8fN!<2n|1}~^euu99dDdurGYFbPs5>sn>gxV z(=4{_;LRpFw=6s7hD>tZZ95M*3;EUC zlB*-#h~(m%9Bz8os+gJ9h>T3cDNwP7j4mH;-VED-eGt%y+hxIN8z$O_6hws}fc~*1 ztO9&31lak^?H}kbXle|*a3R319+1s$4q}4)m0UHQ>=U6nB+6-Or(ZNpiaxd<4?N;p z(h?1!AXu-xzR z+$bbdQCg*{x7dhb55E)X)wBCKl!OlRrkSr}76DU0MbM6l9dFRd*UC;|_Wj8<1HM+*Kg{wHyDp0nYEkU-WG!gL)zbQTH znpEj$nID2!+2d}`4E;dW!zFU>-{56=%B__KwV$LNJ;HM z6>7lEJeLWVmfl6-H%J?j+aGGFq=L}dzeMYaSwe@?ry#GtnkRnYk3n5easR^3ZJP>W ziRy{^s4G+yn_nTo*z$lPHEZ#}t#3g3ku$JPBb$179h>`ul0^9q`Zk;Oq6pXXfpbe8 z^Onu8{{g;63}hI{{)QgpPdDN9GR@#?v0y)$8qi5i7e=z45Q2&*)I{6fi6Ze@Bv}VoA#YM;*9??fmg_042ii7IuzbJv?&X4LQ7c!ZB zM$}{2Hio({i%6~_@aZWpQeL8XVHS$3*Kyk1FU)Lh7Ru#dtidvKVO`ruH3c6it?8xI zD^+X*+H?ErOorzXw*l7k5~6r;6f5OPX43ZXDJg_R1x%eAAw$yB0bkl~-}d$uDAM80 zC>DiX8e!K*ek$)^Z}#`o4txxGWqd>t^5@KMR?gdlA@?N?tp7P3Cg74&9~NLSE@l4* zw1E!>0B@(#l_eSYB$`nPCqiCy%2hWC4Twn#f&v@>t1uKhGdD3IRk-=sj!w&iAtRR5 zy8vWxIPXrZLdlsR=;1&Oto-1wKi-kEC9$*Zlv!;f%LTuG-`5)!>YJBDJZF7;lgi57 zPa*!_`$w3!I%Tinoq+Q>i%81}kU3?bxrm3D-o;Gajc4+%H)L{)p_4S!hcZg_F%~oe zk}P^44k~IDPR_<~8Oak)epgC;REsuVziIC^^t#pPcxWOzY`WpRBdfN3jX;6s;wlN5RE`mnL$gN9wH(5ZZcI8WGeERWc5 z(7@56e!tMt$;*WoTN}z_3dB!j`Z|-Z_g4WB@5aDD*rJIkx`}aS3uQiH?=LKxGZpaV zSz|MYeeCzC{C;-4SP7AaV|kpev1d<$Kfj<3gTiY6!af}T@(PBL@juU{{+Cx!^iMqH zQe9yeC!Y#yCIH|-3QlTuceAFZcy;yk@GZcQCOJYda6s?-(`61uo_HhcfpO7r_xt7t z%gUD4$~XPHF@u(Fs6R>qr9H5vqYa~ESQ|_YL*dZ7wnefA+k5H+weBTUq9Xx6^!TLc z=)4xy+KrnCPerHym~8Q`e2=+8fr^`DNy7_Kz*uxDlOc{-k4OS9Q|b2U?QM2TWWNPd19u$z;NM z{6`_;SvbvqK?{b991rPhelFz#_0S7wVO_~a5=-Ojuoqq5lmtjG{@a&Ou|(1B$LYkC z5%Z_{sLGC^ZI50U_2J^Y)WgOMZHp2I$l-9b+G=uVrnbT#$@V9M-lke}{kX6apisjU zP-_rrGg?3tH9T%8C@=&sK)f(uCb~#9m>B3H`^I4`0PhrP^@YmvPw>3S9bT?Trb@DlfjkkYBhWsv}q{5$R~AK^}SQ?_71sjBC}| zpKzph&+&dBJ%shx7p!=G>LpJ>3-&X~#M@}7duaEC{C4d?(M#RdawIyBmWWUalWL<4 zg==FT$5TOpYw7A63*~MFrwHHL$cth)AMBu==>52L+)b9C^_Oq5cT{C?mI7foFKW7u zT$N`({Xa;dYM-Y#p<{|DZ9{M$=r`_FeYKX zx`b*z;D3*ZCE{EYUElBV68@s%_DkPAv_!RiJ+C|Q1e7MDFG+gB;d>e1RyeU8tkt&5 z;!O?ZUJ|`D;UR(YuTf!LTulENZ?cXVaci*?ZX7Cm57C%8kWT&V8}gA2@9+ZiAV+l_ z3M?$!Y-n3@gV?oSQ>)_Oyt0Oc+s3Kp-F3@dW9T_~%Z8(<1iznL~G z0YJn=@hX}?p{cvmEqM^xixBNppa5@k8Jt!v3<2D)=9Us(N|jyBu&BWAwv5ILP5xU< zvnm3%onf!dQ1rHzH` z4`_uH7Rdhuwtuqq|4ml^e+BZ{IsTtOK0D`sY$D8P>dNb|Blzy=8&=RyMAu!v*XtHY zkRaL?t5p)DY!cy7*et0UvKysQy}$B0yAwjw3`2Jn!yD-D9d#VtXWz%LpY8`mb8?}v zOsIMjp+m+`(xvVzNzkRlm^)1`jAZ64hqSiS^sih<(FUV1utWSH_P_iAA|Wwz0gx^! zEb@@OYAm?I#FY!9_*)*Uf=+5gB9sJiEasyOe30VWzK`1fa*jgShH_bc9{IXqX5~T& z`Z?r%8O^Iv29#BgcgP?C$uwb>1(bbvpT59|7y_we119D~54=aa?Y~}P)kMJwHL)zZ zB~K*IxC&TYRKymf-dZRU6}K)SRY1q0r)YzWDggqszK{O4qMT&KaYRV+Qwn>gCG9aED)d|1V;dH}3?2+Yu> zGB)B!h763j!$5?wLdAmW4x|Y{=7c0uPbnwC)@hX53?d9Ogc_~jP^5kwM01fI8iBRR zsL+B9Ld>ZdaeT^(ctJAIo@8B}iYAAJgMte9Dr!k%#x`1+3Dgj%M9;x(l59h-K{5=)jGV`KhrQoB`F{HPs@)F07y01jyO}qg+i2_*e!T(WXcj+)j9>`J ztf1%xK4I%!eRM)z2|awAJBx4iB!J6Q(`3x+Zwi43!&jV z6#4|g*97cl|6vZ(#En08^w*_}oBJERb0>Mjg6RgXQ~z~uV=ubTyeWR^w#&|iuYq0J zpNZ2SGAFlO%`ET0F2q+oT`2l3Vd}#w$Nyz2({)eQJguzg;E4|v{ZNR)Rb!!U(1r1<397@ZJBa!(qWc%ZFz7w!FstOZxtITG9C4@Q$Q&zvxRbewIgZc~T z=Qh|Wlv0}%9GcNqJx5%DQ_)F+aNw4U{#7q#Z5r^qnz4JeyOH~}eDqH0%QGXE=H54> zmoF5dNE4~62p&1y$rUmZ0g354aBrGm(Iaq3_gq#HQ#i<4Rcf!77~bHZUNUL+f-(iX zcsKl6{e~^j*rMFN=@lzEsmEjROmO11=O2hz0}^sZDeUxwm+Hb}Dw-q!eCWEo=WX#+ z>})R@XNp}zxk`BxxlC)jm1(eyV5|XcRRS#EyyCUx+sfl(M?L?OyNzSY_Iw6nP6)9R z&~U}JfT2#f@ELWA=0`J3Z&^?rA2kCzJR9xW@_^0$m=$MgjD<0&8!`ssoS5Y>QV!5I zLB-S;&5P54^0n><;@R;UrkrQEB}E(l*mEBJ9$n1ot!4|$B6G3<%X>$ZwOr6=S254v zq{&8(#iy8Q^%u8-qT=3s7BeLM(3-DT&gIr_pX3i3m|%v#j&AxJpx7rxcaK}7VNqNq zI$NYf9RMr%hUi6T(%uFpnngq!plUt^%bO5#8hLD$gyodilQpn0tqw(4D2i^NJ3t&8 zm{Z#jVyqD7w)+uFT9?1qH{!Ru-+#5-`6Vx}*D0cDBqj@Mw#tbUth^@mp&(7{6&U#S z2@Tar-3+l~1x(srH==h2$M%^|z@Z~I{(e2!G*1+QJG zJ99s#Ht3t~Qq_Zr)tB2EAeJX%ladc6j&*`M(2Ue|^65mHKDcC+?0xOizQf%|@g#b9 zDu(>2N=2i!KLQZjg^xeJ1m++)q zRPsZ@dlNN%e4i*}lZ>AJsAQ9bDAxR&SWsc%ZJ{;l$I4Ozq^;y|c6z7h0K`$uR2NeD`}e>jQrXV}ei z5>;I+vx9<9frx}~h*qcj%NM{+xsW7^cy0IvP^7DE&7wOjvQaU@iTlHrFLS#+5D6pD zx?|F(COrhB^@u808pcX{l1B-xQnGpM{cIxk%#Fo%j9rInn}rHn&DYR0w**nTN~tm) z0t^xHD=sH4tn)+?GhM$gL=vw_c*yzkc=R4sAEQeyxv}oAnE}T#pgumI1sAEvH*?i~ zQTY<}xdz5186yx@z#)~ia%-hWYS3;SS2fQ>aeemb*F_Y0-|g}b*`FBwJ98R0v%Iaw zN@BYF>{rak#>~J}myQcCj>`vE2FdfA=lKnBg<%)JgM~pK9>{&+fI?@tvmqS3#uzoD z_1$Vut%gI&7JBIP+Sd8KcMlee6;TEqMOdsDMQyy!k>ZyCpKM;>xu_ncKO>JaFm+yb~5-DjS zjc)ANN^%d7#5GBaMu-)O?!^zb>w)z>?NpFQ7-ff?ZSHZYn-=uV>5YW(pBYCsfqF5A2kfW{NM!5G|#dg9u?{-LD05QVB$CJBk9a&|roces+i!wNJ%|_$j&bAYJRMpo zxo|cPtTFA@Pna)lz_XF8lT(-5;FX2N&Lul*5a;{Jvjg>SZ@pW};N8OjD=MQEp# z%P0|GT%c~9G`Rju&@o;JSR z{X)l;L(K0+1EcmEjyYV99CutU&TP=C2{>=-QtFT|(PaIIZ&vdjv9?hPzhWN>WQVc} zQ_bjPU*sNJnc+iprGH=3;zBEuRaoVCze|6<5|jnkSq1n^c)|tkQRb+}@BVBm#8yL( zKg`xO{t|4W>i#*?k@m}$)7o48le|J8-{KtV&Xh(MbMi4{|H&J>(>T3O{sS*CF>yA% z%yse$e5Vze%v)*HHN8X*!kicy5bq!2K`?O@oHaX&}fdt=+#E?#oZFEtH!5azzq5-s9XPfL}k0>Kk@ zdLU8g#^w@)Nv0M4zSGGO>6$pyV^qGJ{?_%j(C-cr+}h~h{#BdTzJO+o>WC=OJQaw3 z*eD>L7;BTGc-XH)R@fFSZG4T2u;Dhm51HxwYiFEd*F#DSjy$G8!M9b~n1|euSvCxK z4PdeIXVms;=gP52xZSjn3Ijf~o!j#Vr0ydI^sX^TEWBMah6^M|x614f*6!j)x^%d; zfaNMGzVJ>&r2=zd^bMG&M7za|PD3!dE!#Vh@7SKxtqyu4&6Wd@j#kUql&^aVTQfP7 z_Xm0WMGq7mjdegZzIb30OZ_}RITe&fB@ol04}*kKk0}evs#CI4d8*$|qtiV@>jXtL zUKUR{Ohzg!uw2Yn74%lb0qVeQ-6IXdp<=2C>%Az|MS4w@UWT%M6t74nWHIl+pp-{_ zeXxZx=~pVP~Y?@wvlP1O9b2a^8V%2QT+FvnKpSL>`X7+jOo zi5qV{;n-{0m9b0XjOM5NCIk4&ZB89gfBk!N(CLGwh`^5YylzP*xzyqT7=C?4998l> zrw&a|%gZp&*l|g!jqSHrFIRaPY5@F|iO)em2ri2I+V?0 zN~S_+k0Qi4t5KwR8Z)N91B5O6q86N7UtMt|;G8l7DKo;*;VWaEs?SbS zkU)yQJ*PY8W;H&2AP91FeLW{|dVx8|j0kifrJ_CLK!)JR&n6FE-^6;R z)xxj1M167La+$V=#g;M73oO=w6OzbLdK(~QvR&EfkA=UK|=hgSm?djk=*r%EUT&uUy0vpcn zy#`dtg4h`}VLT9&>LJF7utf-2aG_v%00EC~G=}nw(BJVmV+TwQz_VPg5sBX3vaWFN z@q{5am4m4M3$wmSL*t)w$cd|PMRcrGCIBHUlR|uyn^47JJCrYb1+`o(lcgbOsZtG5 z2&bjX3G0ag@l8GWD{P07-2V+~I3<-Z+KB!4o_b`VGJ;MKCagN3yk4;zK{;U(P3}}c zcqx%}Zfr##TWqXbczt_^m|(zi+ugdS4s}|=$C`9lrMwgEI;=qx|9C|Kqe9?-m4K=- zTjF~BY}lBP?Hl((M_j-Dt^xCln~zh|WNtsMWCm4RyQtU>_F9rU3q9@YC9N=7({5Aq z--;vQrHR8TxpK3-a-R`?deF&zVcJ&v<1lG)Yvz*dDtstP$Je69`hIiNk2+q{u#ES@ z^Ic(yH9gcV(z+}?uc{N3OEWanc^<1|mb$BXIL=oZEb%YiNR;m=ktHa!ixRy7MM|oh z?L@jfMdOD@JQqpABTGciu}uPJTEwNQnFiS z0i!tp3DX<@A%-jyeTA!H4NlUwZP$PYL}I<3m3J{bIJSa}Yf>**@K(QSC0X(8IF3o` zON-=&3-)Yu>pi+nn9JtoC1s-G-6OZxxh;=Zl_Z^s&W+3x7geP$1I%|`+(*{Q@YR@m zy2PWMaFWjQdPYkm(?lxV1o>$_zuv=#1@}+DSaj3h|L}B~{%N{l`tkVwKfnLGoA*DY zl^H)StPsMNq+;%t$awo<>Hk++N!`bw!Gpqc@v`lL4lP$8HCxBoxyS<$i1xl^i{4aA zZ?!*vaC~U=MGq74w-F+vM{NspqKSGLI)bi-dfO?&*q~wpwz}F)2i2IlQ~itM8-t32 zl`CCcALQc4;T~&bKneK6+M1b$xgG_&il|PF{jQ&sj=$}wa&LZKeif}Aj|3!Ys==s; zlUHUPo$q?7Dl1RDX3KR;k~NL8O($$mVm%PGe@E9{ZiuGTkknx{o9R%2o7Vo)CWJpG(n55 z)s0A=oEI}cdpU2ZAjPozh+5qwoCP4Fg?-2*)|_hVar76dEs9cxlL=DwMPvzr^NlYl z%ryOax5wDTi#7q(eGLtRFjp2QHr(CSkl+_LbRQEOg*NxO{EP+{BZ z!JcOR6UGZ%^Jh<={OXX|mdjNXs}7#s4lbj549-qjSdmtM3jtWu>#u6bT9rf!=0sw- zU93T-rol{w<&zocI%0`(0}P};%9Jd?99J;75nSPK^52eac6>Vhx~R``jpBbC0%N}T zm-2pHNnlKOuXRN#TP)HW5qi?+siU(WXwclj&MrP@uu$(2pl$`3@Qa=?%;*8!980}x zNg|~}^+!F)Am<0#LvxhCWyFkD< zy<$RX*o=|#S~oWFpMxU$zdPK}^U=9SAEg4x=^~@nX}N%68@)1>6=Vp%O>80ODjb8yR;)}C0JdA<&9?_HDm+Sr;w))I z!sWv(dd@N^YPg_i&^tNHd7SCdO7@0N6(Uu6`44YKu&apstTz82MmW4Cp?v#CR0&G%U`t1zjY-CVA&ioR9V zU-3X?NTD`uX(1H>;iXUfQ@Gn2(Sx$Z99BVCr#-cIYRMgiJ%gtZhoOpTZeJ$Ceu!%m zN3&Q(0(&HAD*~^THVZ7vy?7(U39k!{K;iklOW*k&qcoLehcs`>TO4bg{{12V(Fb>J ztu;gkbsxv$I2A83N_%pW1m6We4)m8RB#>+gUx$DC9sKkeQR^SDocW*HFou8Mh8?PC z%Ko%r-qY1JL%0f|7@YPtX0%qo1?K5YYnO#L2uRJYV};@I{NJA!E9P-?Nm0EtSYA6T z>|axhUvNNvQIcIY*sOnxJ4=XX{t`Z z`a0^5gI9ksDItAyGno11F?&!0Uw+EqS@5W~tw@C=*rO|!^3C@HdB^lg;$ zPJRX}7{LnYlK10`voA~x8ya5}!cTjCLl#5(bgQIA^GQ~8d2d7bm+Ay>9|pL0z?x&} zxU!d7SH(L2ZYp(araLjKR$g-;>&9Q0k7Y8gTR)h)rUxDSE|rb7=IP5cI##)zIrfTdl2lPhWqnN==Hm-b3T5xBhjLC_{4#J*W|Kz1$5hZ2-%kin}9gh z5j8OnK^1Q#0?rjnsbGIO1)K*2ui~>q)$Lts{MsRrhV)stc>N7UdFZ>N zt(GIyC?Nj;D>6*>kLN96mu6oEi4c80YTzYe&%{|ws`Ff%DYue&(*Yb}H|!0*x+4}( z##ULJ1B>$Jl(wQH`W($>Tut|BB0F~{riC}Q8M@+`%B0z(Er$s^vp23|c8R)E5f-&@ zo0f(&=gTT5zgjR+gkMZAOnLYdC=AX>hn&yv<}9wKZ$u^uZ$$N+W)mO zru+9zRpbBmtLVkyj-xgfq{tBy=N}3l5=DJ`p~FiQ2#rQs zt}}w&u5H@7++Jek!}gu@UnCD+Y`(|ju0&!Qo7IYd7%tyqLSZ@sN9PF#B`pOtvsRL~ zX|1?~M_+H%yV~^+55N*36i3DJ;il^6?>NxEn~Llp6V)Y4b1#Fhn$v4;=_m9aiGpa_ z2jVWw0=7aok_|#$AEJ4JX~}$FSdzF>~#{ zC9NE6LRDt(YaV6~!w8KLG)R8hYCW>1ZjlB)FP8=iXT?$+S{FLtnrD=+DsK}@fQ$50 zcDfAo30$?kew|^RcsT-yCW_3BwUlbLj)Tn}u!}Iqegc+y5Ao>*R3ZH^;{+U1nM}7< zHtDc>{4nMIu=j9kiY=y}uuRvpoJY;cV-G)sgjuuS55xg=I0Z=v zTH0{cLSa1%N>eKDc3mT@3pJZuucCPmsj?I^pvLjugjoEw;G=_w*^FJvW}4szOvY!> zGqQmX#WcjvGzC;h0PtC$z(rp@H`|Z<`G{XveGD{G(V2Gy%GK*Gn^M7f4letqZ^MZT zQ(iXarf?QY&KTQwPsQr~WjDPGy5xYQuAItyW?U-V{pTg$L96NtwL@02zj@TBGa%^v>|pOh=yUdKs@u-DvriL z*K&oonfEdUNZI9seSy`JV=kqt6=_oFO$=!?j>Uf6DA92c*n+!K0)JG&?Ne*?WPGq* z?DkGm!OC&#!$l{859Qv)mk7YB?&4BY&?Paqxs8%m>B5M^07A0@9;gm!hq5jC*xTWO zJWPUy<-W3|1!1td-EdCWwktK8m0KA%EV1Qp1s$335rXe8FNrXzU?`a|PcF-Xy^2~o z!N;KtJfS9HmtvHKfMais$rN;FWmEEmzItEZ2%y|H*w_HDb_N6CJQClVzFzV-jpIixU;nH)nCRk}z8{#lWf1!#6*lK=Cat3C{a3J{_FhQ43Yh3S!aK z$0H934_^3<1`!S%sN zfW@y@^0=FC3vNw=dfp8>1T{>$R( z#;of~5NES}hWwVV^Gyv15XoK<5fY?K99#`sE}5_Wl{sKA1`(63!`6(IlHxGtEV2&F zJ)+SPid-xn9-AaRdvorIRe~;=GY)PLg9Y&jrZQ{OaJFNq%gV=98nGa)ABFlLPd|Yv z?=q{OFwr^lWqK9FVxJ=ygsIAY2Rtk*Rrj4%oD~@!ge~>Zf-eerMOJm~!t0X#L%&hg z5Z$!l-;INMtEd9ahpDWOA~Yc8CE`ce(Zh~`chhw5IjF{*?%^D;#*XFX^pn3=N#C@) z+zW@qe0os(>Pb5lp`1(b$zT=Xr*JoCB)yvhQc_zE9vpMJJ1<>Jp{B-HAGzcaIr3Fn z5K`oJRMqEbZTKfBq&~vJD3gA6WjH9Xj>@e@r6ub zZ3NZ@;pJEEX0}b~S|1j6*F`D1BhK_Bds--H>RjHP`d%QVVi_1@9|~5I|{B-f)-Bejb@c@9&yD0vqYp zwBoIUK+kKnSawyZJbLEt=`RF5utLyzW^QY7BJ1C9ffw#-_5n0&JM1*wBme$gYu3_@ zkVW6-;rBEG*qA})5ZF_*AZM^VRRe@W`b8OqqG1>*5$alF6UA8tbbe4Ymq&fMJtE7!n=Y_NW*Jiqwv z)|Sd)t{~c?*-YG$HM~~PNxuwonMTXhTMUo1YLb|NDObaNJfYK`9deuNQ@=@Josf4mLF5v zC|q>%1q+CEz!+tv6uMu8kSWiczc(Uo3=9XBh<{jRl5)A8N9)k1gpQY?Vh(`S)j$4V z@MrOHyJ(+uQ-7<`yj^vil(|s}=~nJ|gZ(6?1LGSssUT$Mzrzg!`+v?1|3_6B%m1e; zV`2NBgwX#TjwaQ|Z8TXCHqR+rtXNS@gBXbciTH5se&vArvxPT_pxIP_iQxQ>IV602 z&uUe`=2XBQOM;=jki5gagFCio6ATSPX^|fZ0}npph9usa^rLt~wO+yx^@lLr5THSw zMvA~z6_m%Zx6Czw%oY>}L9UUbAgR&7H-MYFY4B%NOM?U!pOwP{6pD*RVXBMP!!+kY z+95Zz7f-Q?0NYjm{i6C?u3w3OY6Yc_VaZ%tFsbJ^S%+UBq$WaL&kG1vOh}l4zLo!~ z=m;55KYI;|7(c8+JDcm|k%Q_*haRIpt)1}+p}sq_YLF!Y@C9sRtew-X*FfP^%yf5p z8YO}cF-@2c=v{gL3fQ6nXmChBUEda6gwc0>*xy;YQXV3)-!T|LaUxs3_@hpgBt}*^ zkxYb**-*zq+O~2zU}>d%jvzqV+P*C{R1fVq|WM`i{DkYy!yDT9on3 z`Qxu4!j=y9%!Yz;C~iY*HpCJFOdd-165F75U@d4^FRH+75i9wjwWMmZ)|ETty;Ot# zQhv2!HIU%-y4O5Fxbx+|G9X#eH8Qgm*seIxxoG-HQ@2;?kt#kw08$x( zR?*0HDw`8EcQ2k1xh`%5f}S%!fM`-d+7J!SU=#%jjDmOM!tpa92nfKy2IYZrQUQg+ z!-?#p?_%%-q3reI_p8*WgeG#imKq4Ap|_bsbKYH&hF$) zqw2HA=ytcq7_ueJM%z78wB_;1*clvsA2s{H&d!uVNAG0^nHSyv5r(ZEerz5X=*8)u zJdd8Pj@GXh+g$+PC_^#|D5FaSI}fbpZim{nj} zx`w**u4B{4@M_`WUC*VG17ZVfkg6rPV>mp~pG-A0?vhR_uCEW@q!@fnBmnSB>oKqO zzp`T*61r3=l-lyKJMN%?@gIXj zXTt_}%#^%h$LH`@l4WzL*QNjO$ULE2S?!)cgW*~j)TVaGJMbmPQ?OqXWP}xI-IA9t za)KO(@lct3Y|De6VtAt+UP=yZ)oX0#dxfRnki#@zzH*NJ+Aw=IqTb?JqOECZEsA@O zqYjD<_kn#@f+Y3qBE-3H)B3)bJAHa}rfEr5TmQw+_w|3ipTOJZ=M1m%R|Cq)UokSV z06t<5y4CdvCozv043(~= zCw}o_Fe4grL_l6Niq3wrE*s8=GyGfWfY;k8LYMa>4GnUnB(wbf9FCr;)w)8=jb)FuWr%O<1i`TSPWGcv~ zS{^#pND`N@Ui|a8m)OEgl1k9pMGvrAYM1Nf!tvruqDrNgO4ABm22|SY7;SE?qBz95 zm#(}FnzL?G0!4%G*HV%Bx0}?kSLw!YE`>b#C(0f*E_J@pB#kaXhZ=`U8k5$jP6M{3b4i6%v*S%4=S~%RLKAz5(w%^WFY?8D#wbiL3wD?G$E)f6ZW4sz@rX z(;;*ntC|VGKf$oXZJW6J0cAR`$w&&&{st#g@ei{u^hUY6rc{q3iU)_BKfo7WTW)^8 z6hWW@0Ko%K-tS$N#_(N<0wx34XXis$t3vms^KH83(97@-<-e2PETFvi{&>A04Pmy2 zC*+JssZ@dct7QaG=tTOKg0%euz+{7n}1RN8p$>M*n$E;d-Fk912t?#%Os5LxN$!) z@rxh<&sxsGYa_KlOkVXI;Q7aBQtgN0A-Edz*l!T>^N#Dhz(fM@I5C%5LW=7#Y6C%W zfx4ot&|81O=EX9@Fn5Ncir^k=#ib?f3lh;&8=)A;N*Q^gvZH}3TUKq#97-s7z#Ap= zi)_)yXqt6`T}JQ+i%ZC8?OLeB73QrZWnI96Y{kR5P`$sSEtB*X?f>$TKKP}!CuyG< z12e7^V<0omg*ag8$XF=7S@@&76{83F4Fwl%@+$!0l(=zgiCDYqb9tFbV$!|KypGJ{6aca(lGHAx&EezY>G>j{vkwE4* zoNX9+8hVnD`Xs0;uR~^O&YWqHOIRH8Wy_u4z9^osD;$$&HO@WbqBW<{uBpcHa{yd; zaweJ>Ez0)V#e51s&!Xo!?MwQmHcCDFbmb1-#o^Uk^g%k(s%UJRDQV4%T;aN%n<0(o zz;rtRSI8~Wc5v_1$5VJLZ*nZlcb7*Tg5f?2do@IhGcOvHRWkgczb8vOGUr8{#*s_$ zqNsI6%G`-@I&?ahd%l?rhsEl^x*@%XH)h)mILwu`Q67vHl*8K2qU!3B9b9+b{E8O& z@Atd89Q}#1*=^keDzcg1zUyq7_Qz$?HD=!fY_i3-qPXMdra9weW#Q!KU-6c*5A6T@BW0rdhr~!$mVf_9FO{`z(|-;e9jmHc;__itS@)z^(5nBK zM%u(R>pP9S?102md;WMn>~Bx&#q*`j7@e_5YsdxqojYE0AHV5$U!DTYDh?j`Zs#VZ~d52)y0`jmQE5KS!EFX+`8-b2w!BQtr!pc+UxeoKAnrvthMj%yIm7QmmmzUVb3eSDNWpX&zv}g#No+p^)(}p+cUZfqPVv>pX*` z;pW1JZ6ZTqiEcWK8u|dF=G9MvaVG_Rr8_qDL$2w&1lE#CXr4)mOlsZQ*AmFxJQBIh z`;v+M5yC7tQ~hZx`Eo)uXq>_heBf80hVkj+a}qlF+yd3e;;y;Q0#Z_?#LfKiD#t{U zFm6?n_rjfUGa_+W@$+Sa>;^LB7g#s3uUi^^&qg4FyMi!p{>oUIDPv*N`^LEqjXgAe zjqpxMFT+&cG&lE|%5~B5*I!=PWMq>}8tuU0-&|%STHxA=ohVI;t(Rizs{$%x zqObdT3ZCvM;K*Lw&#QVD((>ovcORj&+&9o>^rV-EK>7jdyYP$ih6J^>*QnFib103C ztKL1xf+#aV17YDC$m;vfr=h&b+6l5rKOLE8b~AIHWOR%AIT!pw+`ld+wzZRmwN_pR&_`(%?0=3@Y?epjX=6b4flgUm7*v zI3r(!k{XUkZXNZ{I|msHpmmi%*Sn$Jg&+BbKQRRg`{X&pf8eD$T~*abeL~mUY@63k z#aY$z0{#Nv{s*dv>7Nuk^bE}ZIvOwYXG6Wu0`n8%ZCA%V!bmB+pqYBryY9rXx_T;Q zSd7jJu5Mt}h;%6Nr|#<+6ml#Hg*T2E{1y=Cg>MJgIv%xl^g6%#e)iECBW5KGm<<1( zOu+ibq3;{$XZ>0wc!a5rk+*fnglLsi?W(|}>*AtS^X7K(0wy&aeSf{&%)c>PN0+(c zf*mmA;Amv&IRARmjrccL`lL5bkUBevm|8SkG~KA?HM2(rI~JWp11Va8@<9s&-H7GQ zvD)@U*{-7mI(SWGM;>Xd3bl1soegVD=a&%aMX5stTi!r|ZgyVT>&i21rHvIwmo-xf z3Yj_~5;k>wkTF{Yo44vK<9vUIQ;z~JcBCSLhzf%6b!dE;C<0EaPDm)~UmpLLp|pl6 zRzmRUHb6FzJeO7`!Xn^ReQ;OLzTpK{XT$kIC8FMm7|N(vl|zQ((77t1xxoFYxLtv{ z56+^dUIt4m_gZj%Codveb)q&w|LB*J2jrF zhHxZV3d16|;8SR&Y)5miyQX*#9je~&7r^Vj&h!Ou20quESYCn)9v%^3ID~~LIiDR| z;`ilU9Yy`7-TK>+n}&v)W;7UOGI0)brh14UAcKCe-DGNq|C>C=wwIyQI8b#x&VDvy@DHG*=C>CqW=;MvTW-a#`B3bZv(+p{Jq_w_{n8ji zbPC{Q3(_WLRS=;1LmA5-5eDI7SVRB2>J{}uC@M1JPvC@Ro4YrN->bPBTxMz{m!^%nl^U5hi0O!3FPEBChcg=!L7*zLjx^0QGpWr zRlP*U8iy@SaL<1mlguMI-n+(!aDyz9EO!sl&j{5TL-&*_arU zpr?Z$BB-U2A_X_^4VV|0=TvnW3|sI-&9{F(D^WF46`jQ@)zw_`P`fHui^d z>FOiS6#C6|jIY!5ucP;K3zRP4+J$|!vSWJ=0_P5Y>QmePjQ?3<{MNPZb26;>+^@Ac zZ<-BB=ew`)BZr7L+M?&4fNWj*kB`2G z!8%^h?)zCnh>vm$6%|>l0Al_4*7aR;k`P+U$`A+7f)ES6+(4q$TxZuipp?m7JEq>> zbli{%`5AXoSmz3I9tWuDz1L&kfJdkj{}9r|^m9q^9~Sd0|9Uassj?pRlUMEatO_B6 zN1S8eiul`n7M*ny1ab!L(*1q!0$4TA8nvyZ&1k>-TCTuql-0_&0SxArBZJ-4HE3m( zZRM5j-HqMjU1vZh!hrv8y%r~k;Q-KXAP~`1Nxf8NqGauJ!^gvu7r6+fDo;KYl1=kC zWhzbCh3ev%QjM;>hu z$pM(b1RrR%prsR_N`KK10~@|qVP^5nOAR(3pi#s$a|@v;S^B(*3mqHA@ZmPf_^l8~ z`6OWCqjhFrY}$3e0tL5(c3S6Qm85jQjmih|oh!tvEPhRZI<%QFPh%a*)T`;(=0Jk@ z7Gx?<90(!^WCKDss{;{jp&jg4^D=cIGf#qX9>b_zS)Kh}T^%WcBpEMg`2N!SV0#A^ z?KnP}%66{inguT!$MDiYQ*G73zZ+bWo!2Y{OA#32;wjl zCXd$AS+l0;oqftR=1bb|WPSxr@@zb(Xi~+MQ6)-?bY78dd)DX81xy+wZ*Ce7w)Znk z&V7`BPJ(yIOyX93E2q0HH4yE^-vX*iU-1?x#y@4?)%_99s=8{!OmjBib=n=yw`aRe z6I6{?rCsocEsz>%p>3q*Ix<>uP#;Z!K#1=9R(aaRN3k!rYqp$EeNd$SjOLssv$;Y< zZ*u49k8Quv`*@BnQY>kjiW6}W*ra!UFLhE*4`QmHlp$F)jW9O|g7wH~9|>US=MzXw zP4Ow|^levePEXIQlkzx$%q5S4pev*-iacwujh|LC8d*l>D<;sno*Rf3ncPXx zS9B7NSF z3siI`w7`&HmW92#hfLQ|flCsjq8yuPTgq%lY5@OMTJ?5jMxxe$+ls&pTBG%DT`$DI zt9FX(u(=9q<6O!j`j}&ro7J?yy#nS%F7dM_bc~dsiFvmQS_dK7IJZBmJBbk0Jj&_8 zBbdhc%-=xFDq;ZtF!ua(W&aI$*xA_r^={%)MKV5}?Y|DLlw@%8DbI-E>nNrNu-+Eb zC5jqfu(Lbr`Pz$N+5xD>`E*k^M)=VWh%c&K>R$#dl)NiGFP|l0tRji%On+%iSJ`+* z2QocaMOWZKnnrN+5p@lhoUa&V#zfk$T#u2fC#<$Nl-9MdTrd0RZo29Z%h1Vu0`MjJ zO%{$toLcj-o}6fCtk!wG!b&G?=X-Wbo@ec@xH=I5A^FylCCnp*%bS3QJYJ-lw?<%I zkAsmd=C&mD=vmo|2(k(dworvJ+0@nXb@EbU*LNh~oe%P~cTL?TSFVvA)xElWrUwj6 z_byEmjN&KQPiU*KQZB^B*t-PCkKo12NVMR2)f|_UY`zjnvV3@31#nsC5nB+>J79}m z5{SP3Wtr`#QI6e4Racz0KLv%W)fhQ{bxb%8OU$o%)AHsl_NjMm*JvU=UvD>_zHm~; zeLB8ywKTK@#)LA3JJfmr7Cl-1wjMM;Lzvm z`n{L|0oO=^opL>5@nqi+sB{``qwb(LjhxXUAV&)`EZMCX)U^$`!e;`)c;)-Y=0eKG zx6pjGickoXa<{g^4ry2JdYcft;IWG;uEDIqA~zO|^x|e07D{~xSLg)5u+6WNBeS-i+iHeRd3tZAUW=()QRo{^dtV6*yv-?6CzS{n^t?V4UZ0ka zOs{pYBy>FZ9CCszvx9OmsY|4F)FY6kn(o|*nYQ4$MEKi_wh0M^UDjbU8TrT>LWO6I zQvWkI78pw)p!W7+@VD;X+rbReVan|ptFv0+`bY6i94Sw#aydz1{QAd5BZE{GNB_v& zsjxpohjSV^Wt~AdgNgl$P&$&R72mw{^*8vb&mKQiruCTqrt#V@BbcJIgkfTh;;1Pt z$xhY$Ki2(^d-DKbqV3J)99_}M3Ht$9POjhb7I?b(Ef(-9IJ3GgZ|B%3LnAFaUzZ?7 z!*BtzOJJ;y?=!G8J|}RJkXhE>0I*Zte*XX#EdL}QVEXq_l0Vm({^P0!W;_8o5BKFy zXxEfcT!VCiP6oCfRMKn=NWUod_d8XMWLSdP;MD>TLJv<(`^yu-^qP9sA9arK_rKr5UfD-_X;p=%q3s;9@R z^`L-ef^|L#8t$fJtGcH)otit^y6!G`6&?d6C7NnBwuXhgv-Y8^RW@Ps6L;~K1h(CF zQpRg6;oR{KjQv{$CUxp^l`;pUC@;056)~z{5*zGbavpc9;pddjLuwaI@62;ow=C^H z(%}h~9HUC|r6N|hN}D^$MD}veQRsUxQyBHEG}ad+EpyIh#R%j?jv{KC`Z`IGo(eQ*1$Z3>0*q|m{7~=dtU;@( z_OKf!ywNYhm52@JVfjFhDz{;xxMK{1?MdBKynHfTnW?78wRAeW9}i8uF~J zI*VfqysgZy(AbrEv=rjMtz1uLW?M*c&807FDR~>*wqn61M5S9;W&(H)ib8#EI4T(+ zE$pOUuCfQX?c9+_O=r+rb?5|^PR0K62%Y&uHB<3mK-SAIe+wi@QjtYMC-dL+j;o)tR)8OyiHN2Pn zGtsjn&*cHS>Utlv6mH%$;po8WaMyR7pVS`HaEoWDf@d)9a>cmAJow2fsgbm^uED?#94X19H2f$7XnZ0M%?0mbjAeSo+7iKS)90(irJgWj%NtJ^TdA&(bdu#~ z+naH_yGQJR%8}7ei10f2xT7{1gdt_9HW`$srKX0<)660lEp6&Wxj+T4wU3VnqG^!a ziMvdkzsTezc$o3w9P5@&U}++dEjGoLbPQM+rV80TH_GW9kL`dva%D^rGy3=7A+g13lePCoOlHuocv46U_ka#lWA(=917y5K7O5j+8b>a1nR8^uNv*I|Ejv#t zVS6KQUB*wNW@}KHDQxlw;e0L8;HO`QL#{1ud+j8>;q~yW$MGXiZ%;cpe?Dll*u6d( zv!}8z4$I%O;@t{fV7cGjG%0keTZmnPoKdtgZB@T3xFF&!-4q8!#dike^-w3zuHr2d z?I2_S_)|4Hr#03Jz@Kr!=;>;*mh%=P@oF(w@GbtT0qPpgH5Hb>c+r1?Rimc^j&r5; zYKEMjY21E1$FEhVA>i^Z0L~+M-1U2I8MQ~mp)8B8I!AXES-lmHRcUlYOoTcougfHo zhY}o))It6+6|!mftU&n383oo}V-|tnZ&0DU$4ua(XL;-!%fK|5-H!i8vk_Trd9qTD z5wifx&2UzH&msr4<)BduCHwMiX2-QPT7-GT_oj^1x^Xwt5EI&#j3H}mKF6;s2LnJ; za9%L4Yb4H)?5I@d`AK?VQKlfaMaf5J*GmlJ)1gG&H?{9BKR~`Z*~DQpPVH1qDI5uY z!X61H<5?iNx)v8Y6xFW3yMgAWbd9bljdEC^FcDEa!CS&Dkkcme$XGd?k@biyu^=MP zbDi4_YP28$&WUwZ0M%rN!G<>Qp{0N=hEW%E+8VdrO3khef$bo2)qD_h07V^xxw)9D zV4zYj!_B*G`jP-;`h#;#LJ2QXcl6g=eg&<=T0Qrj{j}Qz7LRhRrEu)xRK&BYEh-UC z8qb8?T8a84bw9e%j`B{lNll10+#*T=T$mY{{E>}AEsQti_;N)a%|QIqcsFRy^%hR& zA$HWzpv;NN$L@@(SdxV0dV9gS%7)joC&_?A6l%EXwzDStu?zt>*aREr%W}mWD}yx< z^Nn9n>?2TuSNyS}#5vHAZ-*xixUu`!c-JPqRmk$(`k!`uCgEkI)%h+jHslzrk zOt$W;Z+fObUmBy*emM^%(C9gcqIQ)k{88Ox{IgH2g4sYz=(BkgE=#BlCJed_hmzH7lr$D9d4Z`>z%2wSfiN&0T2~~- zEhQ$2R6F3T&>H*$qY%p9!BnfF_?0Emb|Yc9to(wWAld0qA~$7B;D$#cPAD01qr`$1 z0+eDhG<;A9=@1N(Q+{d+H_9W4$uI#B?+}5gV!t6_C#hRX7eH*8VhULhF~X!Ui9lh= z2{9>AZxJixHZ&lsDIQSzm?o16Q;1MI2r&|FWOJAprLLUyshAPBk(l9Z6eXh`gJ?kq zSM;O_^uqacA;t$;Lxw*GAZo8uqFc0U8e2)46Qlz-pcDo>53l`(8mP5^`%^ z(DN@w2T^|uchqJK{a0sis%wYKRtds_-XMRQb<%cf1DqNxMH|_mfpSRUhzV@fC znH5v#``sQZsJMRBlN}Ro`dcgNQ&+~sM>fdxzJC97H9gQ($~HJV7`^|V)$KwmNOj(2 z{058$(`z-(Lh1^qP>2n_uWm>LY-7Hr89k_-i=wr$(CZQFKLmu+=bb=kIU+cv)G6LaoN+&L%ap8aFT zid=u!-YetH%=ej6_p8(}db@rVFkBm3i&W->Va>_S&+F-ijv3Pn5-TEh?CdkAW52Q> z;FOsX`{*m8V&}ZO=_gFkG`!_!beoYT6DyKG{;Sz#+!XR|%Vqx<6t~p&aaI7to80cP z=bQQ1L9(+y%g9LI^N4VQqn|guizmOYW8~Q$fE2#Es4(f+ur#4(fZv@jAAYLo&aFdl zi2gXcO@;aR*yyo1Jl1(QSGRbWQf%?4VB~6I_Y2xtZM=cK?R2u3MHU!AhUN_m3YPW; zdqC^~Zhw{rWsAo!*5qYKg_S!q(9YypSDo(fg$4-3#th@|xNi$K8)8a0?I^?n@^(`PaI9;fxF^u6Xa_$DFQ4}Jet3H z1e_!rX&-%X49EJJNqI%(Dg2D-70)A#J-F@JOy3zsw3T}BCUw&ISR*v=U2EEWcIEqU zCr{pUU?Y$r!aI_A+KjT#^ydy7&TXTK>A*BxnpEa34wR!=JBkq_4PbhUI7H%#0b7|n zd%gOcugnu%6+`w~Dt;xf4{ zhVt_Yo_dB=(MxMwEQN&2TUN(#zZ$4L7|iX7dt|;m4KPT%M}mhujD)nHyZeLvQ*qW4 z9zNPPi^6qe{eOwT2&-M2;>6^48ClTznk@C^(<7EQ4u9DKEWMfrtH=wzD-ZAC-5VOJ zj2@*sM?Tn$4DS;j*O_eJK(d`)X6Mh1BbFo?;|bnZl=snMw+}Z;x8U{B5NBKSboQcaHeYYxsVsXT(A|LpRx_?V^YP++Ag$-h>_;-{g$aZ}uNa~g^G z^n`5QsVfLN6@Eb(im)|K54RYPW{30F{L-yyl4qO|^dDXVHy;ct+#m_8493^K1|y-B zzGxDsNBK@Z|D5p8r+I@{NdM@&qPW~Ju>Gd(oc0e^`4xXB?9}y}p6euBgzX>3%LBIg zmT^$git-oB1D;r~wCOXPh`&b+(tOWU>tt+1k-@bvt|H^tpQlI{PCvkY746N)!UvTN zs?X-}fO`D_ZAuA01lDs>i+tv=$GkH^Ms~a1XWx;B;_fD1;IYkp-F47?9Sz%8ykELg zZ_np%Fnlq(hxZ#D<{6r1-%b$^dwIbh5zT1yG``GXQ&tpY1o_uUpI5BQ-k9Fd@8o+U zjBUOZ!xPgbXnAmoMENLi_rsmceeVX_cEeo+i09*KU_fvAhVZIzZ3$#}R;{q?it`QU zQY0!umOHYw|AxcEH3^+Yl(;vtm48y=@(q?10C+@AH3IvL5bc=i(J$ijUIuQBmi19-Vjbh<4G)H%#Gn9>o+o}$Vs|IC|(cR9>?QSZofB=xy_3l?0TbI?r{bO!k zFc`a#^*_Ea51sV^g7%A$eJ3w#M5RxHZ_zSDnIuINY!t!@6_iE0{imw*#z%6$w$7C< zN&?eFSI*H2NJ5@Zrd=^m59n~hU>oWfI;#a;55Qqg!UC zcgo9tuKKa&+tj(k&@A`tIi@{kkfmFPDgR==C2+)eI2R*f+ge1rqJ#P6;=ex}zLUoz z$k=Xk5xjgs*4ZlS#|3k-Si;o;3QwqZhATuA#;EfV2;L=RVCF$))7`GzwUO@g-r$%7 z!1;Oj4O^Gjc7mT(P`h|NlBFR_Et!L?CLOCPs3^AC8n}wLus^*$Tbt$zM^caF1khAX z?2jCIxTrSNdS8xI=Iwf%o%%KBJzjD-vlP*j;u_q9aAqx}0pTrCwo>%@x52Dn)O~d? zw^1wFZGKBEKg|6p`DDCC4hw#HGBwU^{94g@{dZ0enT$J@WE)lj>D{T6Z}NrRx+j7W zHJEa>`k7~IrWg#UKyLOEi`iZkrDr$Wsx>VwR`R*3sC4?@7eHUU7WbX@Myad9wXFQ^ zlJ0ne>y2`I^7cd9sLOl}XLW&Edq~qef%wfeBg`!5dH_*Nfx)WS=a{$KHnsep)s$OQ zm_Nh_*WqD|a(*C#Li%#-twU6S&^u2eXLk|mP0qw;c8`>yZs#@R0r}Tl*P({~yyd_1_a40gayeh!%8iZ_}w&y-0d zagOXun8|YciFBrE!u)j+7j`yLCbI$k3HP`~$v?3KPQfw~~U>m_CWw0mQu;D5={JjkB}IBh66awa12UL#je1`huq zPyC%ApPhIZmp3e0cOZ}-VcO(L1W^c3nVtz4W^^ZMr1SYEb@%_`^MmImUW*hW!}T7- zXh4?8OlBXLCn7MbknO8yj$g?to?J@I%~5Yqx;6r3B(wK=JYU3~bn5WRb$twp3fZ&P z6j(K||1u0{gy)c5nSPKgABvu-%2Ao8xRr&7(rEN^V%)!mTGu_6X` zIf9|E&cq+ns_EU!soh4TWD2RaDRvMI8J)4$V2_Di1(!sJ9GK4Ee~ zTZjc?_E1fY(GwafB)aw__1%>KZ2*j){xDLPliyez@w2KkXXz zep9@uI%86lt%yxDhivMaDJ_%v*hAwY1SJ3l8n#Djc7VsC*qf8Dxp-H2p0n5&&p?q{ z#Gl!6o2v0cP1T zMtH0oE?C^}2+|Wkmcl%JM#C+t1>~m#)Hfk0T*;khfS3`(%W(FSmGMbqDGhn?yKzld zp}-3R6_HbMm8PJSOfOCRBK8Utzm0Hu97LPcMMbs3p8d!P!!F7=w+e4(j&ZW9w!SUr7=48 zY{aW3)>n#jan}`O*Ye0?(W{)c!-SRg8{5c7pf ztj#t0ZYmMs5;!`Bn$Yn33Yt1t_xRWi~8(=m~{ zb}ZdeLVB5A%=<4HE*exk<`5uhK6mfrKONxZwpZ-;kI+^ZkaLqhCFeGj6vSLxJs!sM zR+|99prsDb16<`R6)M?k9*Ifcyo|7U*PEwd2NaUZA6!rTCbITmv0X;9@Xp;A>0J;A z`|lvjmySwpr;J*-QdRST)U@2nU^8SOe9lP&=SO1&$FaIItZS7=#*Xi)1-$`<-YD%# z6p%GnWiBrWd3@BB7|al(y^a|jtvOPL#>)vHOt_3q>Krr0m%jX=*TY2dq~uWt_k$1Z zk~(U3S4%+S`=!oiNB!F#l4ls+@X+X5a2pb{H4G=ryQi|$cY$Sy9!jy&DJ1f)4?zO- z7|y?;9j0q@)KV&vm->|!JKiYE?8!z)*D#Jk*TIGn=^Bzov^g#`$Hb4PcZx%xA7}xe z)w?SR+r#u9XIOOyv!dNjNv}Q+YafRhkG54dAGiS~`02*3Qj!sE8;xV9v;laoLN)7L z$?So+*>5te6>dj<(jpF?uSxJ|6186vd-s1|)=Sy`L?3rQPe^o@+E404cO8F{ivSid zTz6r)=j%52F@mMswCPw??AGUqtv+SfS>M0(vny|@Y@nv^CWhx}-7M-clA62iGxN&O z-6+auDVTEk@&EuzU3cCUY2pXr+Wl5IY_-tpkV061NMR%RO=rxeoGzrCRJF)=ymh#u z0YJ?a(X+L?R;}~dL`h@xHIq`c^GxhRq^id6+rQD9p~X2M5^!^}I&9Z$_I~qi2T&dV zvH!c`{VwY(7wEw9g*;=|BI$mZ;(qDwb&r^4#c=swFB&$E{|0oz&iOy@hM(4&O(^>3 z)cL9LbVg3o0uFp0x#`3t!KsyyLi`865X2NT@w0hh9+MSPH zjArC2(0`lfv2WUA%wH6L{EjcQ?;y(9VjDqp(vIPBk$}>a%Wn!D@biH7^Txnsz{L+! z6R5NzX~gQ%Al8vT>g9eEru)drfRa>dgnfdTc{I$lkv7f5X6Z=Wo$G&%P-pNvAsV9C zud^q=;5xR$)7qeqVhBceg-Y>G^5OWAh=CMswmne7hWDV^lPWz%S1?Hzd{VoFjRDbX zT8g|^f?0Vaw~qJrX*A?#xf!%5q|RBG0=4fMe<=uTb#5PF@jhl!cxVsHVq&fo`#~@8 zFw?!ya|2kU-spu&sdz8WoAQ(&4M|@~VgewTFaN2MoC)u_ny9hvlh3O>G1H-3UI1?~ zY{$4CpIxcZ{yVEBy2Ein`F3W1DeIvs|+Xad_EORlIk0M z+Lu6sP8A?o*T;k5RHt?IjiGSWd#p8LLiGR#H};f!Bb2OZ)`;}k)zF}e+u{0a?f|*7 z?fb8XvVy03>9)2M+!Do0!z+>^Oh{E= z&?LgH>v<`V0oGRGRo{c&fbwc!i3vv!F`QL4Zr<-Sx(K=7bWi1e_nVxi|M+Pe}Q zr&~5{6>U7}ZX|1r`|)R;*G@pQf875@!2cu1bFex5uC~M+)89 z1C;hkMD^giRTuaY+q^ovl8K!k__fDILSE#7HhqPgW8`uDO#;D&1KgzJ1Ll4d2Gf5% z`mF!k(f|L`H@W`bp=D-f*8gmo`acgXcW28app7Gs-hNX(SQ`9gA!dFcDolGJvXyCR z0zqg&hJ>>Vg=2w&uzKD6Bv@8rYs|>BU0L_Ts;c6lxkyjCpR%ryktEW9=7N-FYl^4I zkseV3RqLb=TK}W6w;*g!73sHn-570yFwrzA7yLW;5*J2^@C&`!2A&N$o@^=BW~>Hp z_00zF!FsUx{%ecc-kKdHABslwMX;T6M7kiE5dyI^*+~OZsDHE_(=ggE+0hsYsLb3n zafWPN3enbt)d->XDHlW%#RhMu7ycTX}{%hWuM-q1vz^NU1QabQ#m%erxLsPAYL|aQgfMA2QyAM);A{V6BSr z0T*{gX0#l+&9`bz5HrbJt9BAWzBhbX@QXevXtCtD%0km@9&_cUjSPJ0VOKR}O1TMn zaGB*8zC;nS3em!(iQr8mXf+r{M|}$)GMHW9`Hc9`X|~tRq0QWa*o06E2kG6b(7c(_ zC?oXcX5TL1SIVtNa>m35rBQ^U5AWh|?H>ogklsQT< z!i~t^!i-x);aK{F_u$-vS$IR7kB2{?&8?NEQmfb6%*EpZ&_9N2&0X$Djo;R8=8Ly~ z%I|Q+fjN9pUIGB40wT9c1(DihSrWQ_{;xN~H=VaV+!&3z5Ht`RXZvs=nI_W|#(h)9 z1DF)>C-e=zLicYU7v#L&XfFxV5rsp?e@4r=u(s}rbsUj;0|N+QY6h>e4^s#o0FR@W z8VZOU`(A5+uf@aq0Qa|Ja@z#&m&*vy9?$oa`b|LODE=RN{(h?TO^;8C2!+*rfgWyO z?SbWo`CWv%-JY-gkMuj;HX8AZMl`*!E(H4fIaoUXw*Bqyn^vt5fPDw1aD3@Qk>sQD;YWaxb|b$yV&!SCKIeD9E@H`Je%B`Jexcg zPm-id&?o5PxAQuC9X*U4C;i_6J^W5ycdx65wd00Klk`#gg#QRQdG*L&#FY1_ste#J z&@1TXwfzenJp7%Uq-W^ty87Q23VL}Ryl!3>4@<|DlPc-u^#2j)I(Uelq@k~C`_IKJ z-PT3_;ry{$`YBnmdb)<5{xpjU=xKNbDoj-e1gzPzrjV{EaciAKAEILsDz@Q|-Fa*dFt{p@ z5!Ht%*b*t-HWTFQ6cOljDB)X(8-Q}`pN7>~#K_!D2{R7)^{+fX9dF*Z;T<*p>sFVT zF0Q@ccUP>O@=a3o7BeN*Z*%`XMioRDh)o79Y#6K&FgNppo5-o}-vva_0Qgl@<=ONNT7qDP67Lltc5ELR|6QyA6z43fL)RbkV{sA*o?#i8Cmw`$S?ToC3|?f5{L^AjVTc@K&2|I8m>RQE!Y9sG zsI~U7Ct-_#ho&5-$IzGcU2BjiEvWMifAhLK4alo~kiHtNlGp_6BBA zO_bPMb4#QGWl*;I;O=0e>2ewwWa-b8*7@9SX2Xpxr%8tyje=j#5e^|nTZbe8$AUhu zIKE~h8L=1oXHowPp2*YxvQwxJje8s#iMe-mop43l9E^!g*^8-BsAhNyN%&Nw6&pPi z$__s(X&UF=j6IARE7cymD;bM+ndB;h6rtf}K91-CyGGe&%GV~XRQsy~Y0x??QeoZycrQ#; zz5d9#@H*0jsDY`*$a;v8Bf=*~n`niTEi{ouGgPDogUNL6oo;qyk8akCsOxy0u)x87KoMpr2v90v=K#gHZ@u|2oApqIDtqTOUfbt2J6{ zeT7a35xdPNA6p+dAa*ARm~)7PZQ*3(I7m4M)qlkI_Kn8oP9-AZ`iln>_i-y-!Zf>$ z#~j0#+L=5ra79wzD_uhFmbk(z9z9?=pmynSMVj6_!*D`xF%XC{PH!>nkw&)%m_l-h zbVY!Taa5y;4d`sm&}5wpttU7tNL`wC?dot;i(>P18B9=g`hGWk(VNnpUqz%j6Ybt@ z55V_(z(zn>ylI7!Hf3e}bnuWZDcT!Yiwvn?iU1e2-nO@;S8xd!rdjocnn*o zZ8$Gan^YlhvxSFe@6H#d@7htnDa6rkfu655cu`@h@7Tn2S+-F|c#p%WMf7?D$ z3%Y3FkWlnR#AV{e=jcu^3`4vLc=adQ0OjV;U0-|tTr*sNu{ytNBC|NZL#eocgB->2 z0#Dfjnaks2Amk+=Vvw8P1aNKe+yfoa$HvfhB1>nZpXnz}dipVhgryJ7@e!0q=> z{_HGZGxJ>_F9q;KO0|X%J1N?!7Cee|>nFY|DkR0{;Sc3qh zz5=96K0FGgJF)!gQCe79-(QnU8$(MW=TyfRhKE25%}o#CzD_$n45rsKH-OWwa_Ima zlmhW!Jc|L1m0Frvnw!A6xxfH3kd4eA4v+(aD>=IBDPYn$O&>X1vh+yc$iR(*<0R8BvAOYqfU`_%&OyI0I_@EbgRRX+J zAQHT<;sMf6Rq;Dy4Jg+7-+sWwzn5EF0Le|lg?Iq>N94Z`!Q_k3{b5?w;7srY2~ z($5Ou6VL_*B>Q^;0g5R{4csMG6CPhFj!cxz1BCg{va~wB=|&CAeO7x{-yE3$Dfff+ zKdYedU!9YX9x(#BzOriri~S&$uN(;pY?HnH2|_vmcz@YLM6vjU7Q3J1H-gX6D_cNc zf=vFs!cD?y@chj3%3Gby?w12urhs=VK;(iXtQ+sn;UqyE_a{R@nH!4>`1;3$WjzC6 z^DNMsd~Gs=AV?wOv)EhunUQ=*AWs15+= zt?xM^61W4Z{JUUc=`rN{dasuutuQ@4d%=B=9KVa(621U!M7eTTxj#GaqfOgC5CY_f zKahWYNuS?vzA7%>BaS30Fz3$m$pD8NOipee87Y$j_=gER=LTz24~GY!Abf%3j+3x2 z(&c=da|PSN6W8k`7xdF5gEROd7_h2~Z&xwJ|X^*IuMOHl#U)2;CiS ztL%m!I%Qs0Ido*j@%AElkzMUfX6dMT1i$ujOF?COLkkX!{I2WD_Ac0m9TTUF*`|MxS2p*cWiGpSS?6LTO!@%{Ww~P^C`~~xzjw$k8aVmymW+-ydPt`qj zyOtT6xk@svj=9?sJB?8{eK1xfFIxxjtePT~#U-Nx z4V;BOGAlDCChvT)RJen_O-IO&pxKLxawDdUsN2Q|DZ;`@$!hx)lA?XODf6_6{f62G zlX%fGNjKRu9a1Q~cQ_Z;%eXQ%!G^BBq^wZV8&SfU3m3*u45S;H#b`EpMts>~+}=KI zqSL8WtqoXnVO9lJ(HxleqUhNhUD7o=LPLz0Ac;>_|K3m?tvXu9=(z#=WAe$CpwiN# z{>*sBjhdBrWy>Ak#dL{md4(L!&Beu2e}y+|A8l-l1`oq4#jhd2z*2+?32<$GkkaEC z*Ct;%Ti2|KBXQhK2IG@J-x3|Vm{dmnwZwL#(!^fhYs8O^V6y!SZ@~noj;<#?xb=ip z8~)4*J&2>J((wnGU7yQdQTq&L0RPQ`XV%&u6&z}C-O|gv+Jb~f&H12CCunoDolmab z#bk@|{c+)K`>&o#QSH>>v+06F%a+>)R}c+rq)*OE*PM<zaORRSkDtO9PYSjF%YS)JQ;mRrM{%sO*=F3OkxIHhoM^x3Z)G43#d zRMw}>03sUo-8dx1;Ljrkwac$F>P|Tk2*3P{kUa#|^f;`)%1NUvkj?Zg9VMOfc8|M) z2~X(O7_Tn;FY~jUk1`&qbWP527z*>h!yQPs4hU;On0-t~R8$kQ=z8-w-CNdRbs^JZ z#*b%HMKx}ypJ5uq=00|AQV1hx3O;5iU}*0tm%pOll+vS;sHQLy=+}9F4KjUs) zu(pG`o;pao!TC+Gp(>Z|xxjE>E;Fx3D-Ek0tl7}#Ek_}eSLe5gsd4IZWqoVloaN%= zkxQ^^lXts!caV5Nr|+-LzDx1vp=1X#`<5Q=oBH^3y0-0DIs?WBLw&`!Fc3;nd{ZbS zm(0>mxminT^^J5g?@a83+?lIDa3vNHma#Mj&sA3s)_Q%@qCCL0Ik2ar5~AkjKPQCX z5aafGl-7~oJ@=YCvt8CiE9HedPb?v)Q#s_Iu`c4n3S-AVdZeolS93QiO2bE$^VB7; zgVu8ifmB6C1fO=1%?=4X`z~F$h_`CI`D-fV*RqI zw((AbRI2_h)r>N1=aM%~je{H3?sag|xYx;VZt8>Yr|l-K*ImBq%ZnOKHT86CVOi9c z=}#G@R;}Me{bq4&{8FvqAja0DBPGikx}RD3c`-fY{8p)dn@{{W9?IRJ{-P+bDp{;e z-xCKXNQur`rLKu@EBT&Sf3fU!2uP;OUc?(pi!Z2RDgvQ{~!~?Ghhe=L8%&HrS`$Li9Zjf~o3n$fgZ`={_E!-FPrE@Zf=N2`l9SQjIXje@_eex8dpD^1+ls2H+OGPxf;$LN)B zSTttlQwS*;YhM&b?R(ZO1^Q#gHBsIiYgBvYrq^Pg_BYR~?0gpGX@cv01Z-l%5#cow zH{Z63T2BcQsDC}W$yTH_^~!0dA#W1QHzGv6C^gHl7>-Q^u&rVlc!r)R5 zL;05xRi8!fW*HFa)NEzKuK&0>1iNSCkJzy#JDDPD+N=RY<4(fU=u}`=cUVrXPRcU= z3pMR#3`$wa=?GF%e(AxU{xtLyXd?kSinnkhW)3vjcT-bm>ssRy@aP~qO+#Ma!MbC7 zgqzSD4&o;&i&Iq`Xq=QmbktDdh6&mJYDIYx`(q7Z(__}0tqypF=5}Hpc)21UbwZJz z;~b}IasrJlLnJ}VZI&eR;d9}vlIIqTmODL8F|lytuu=)VTaLd$M|J&)^{S_=xp?)oMHqb8+{~TZ37&-a zinvinXp)yVBTxTWLgvdXD-O@(6qoW{il=!cO)jQPh(elQ*0I4h@imUa{LRGVDQHt9 z9YiiugJVFhutEwdDLqYP#i;hNpB;7=Il|p?Ez4=@-=qJ*&tf17j9P$=KE{yS=?6jc z1@2))C8e{7YLx$G8LwBrueH1NrAZ@$?c0kRF*H;(`dpYO0!79ySv}!Ubf`%xtZyug z%Ua8-*J_}iaBGYCWG1u&^u-owQYN|f6*(L3DY2XdS~*)3HmU<`gA4-J$*v z_NHPxi?$9W$tpDoe>nQSwgX2@&oWLRtVLi!t5AfmFS+&Ew7dS&JFkR8;huL`qKh3$ zx(wZCZEY@IlOaBQ%8F&81F1B6L+clz3wltOZR^o5DegSLb7C z$Rj);_rAP2@VFj|Bhb^dnps$3?B27L_WJ6End@lWL`)pY4#(sce=DOP0<9vf!7NIk z>=J4fhe;wJc)2n$bmQ9_x`F_2A{@i8B5f;u*Km%9pH!v(5#Ec1@1@dk^(!UemE4)f zaZOCm$5*=sEL!{7mT7Pvx#^Q;VoE!(RZR%ojslIk>5a#Ny3-W>mq(B6>j7a5-Pq*} zqSdOAaCZSU{G`?Cq3kq_H@E1(`p-TixB%TWD(Z>xg<-VlGx>fguaOrE65**e6>zES! z6RA@{-M@LI;jI=~`505KYfX%%uA^x|j!VIg$r(=mlrc|ZP9ieTv2&h+{F5+aMz@P9 zy-+-XDf2KJE`J=@eOb)o>0hhcDVI)y(O292r^#Y1q58lk=gR8e<~Sik+BTyBT*A$^ zw#PpHq5w*d^n)gWUv{!@aoOIXYB6C!U2kW4;JbEQm8D0Wh%f0;uYC(+l1T(_xLf+H zM>W^s0)ws!%{lo^#e-w~9MIZp3d4vZiOHC;z0bB=v&2>b`g8HkexFl?G3;9&fX81B zng;zK42>hveC`>el{gf|jtVFkgTj4(z>(#Nv!mF%JCdbNZ0)CBW8ofjf6-dO;_33v zgbB?CXJ3AA8g)aR>yczw-+8bnD62(gzmVC;uj8sc&tkcIF?oehFjjF@Qd*i|Sf z&8w=?)!i9eH)DDU0ms6rS(PRinT@AM-b}K1Zeld<4^O~bZYVXVT48k2x9AoV&4+pj z1=zzr{k}1@7}FAsOI;)v}CZKk1IeQSF^1({`iXJ?Y3Oj zsM7f@)UQi45Q>}crt#X83E)FM;?8%*sFQ-?)++04x*h%r7gN{;YH;dHVHHg&0zn)Y zQ1B!YFnx06Y!2alUUFhnS0>f3%2s^W!>ZfKb4&4!VI?jNN*Nc#@;SF2Orj_l8^6q_9C9)WR;w7>g_;wq=0v3)^^FSl zwa28hLLbcS#wN8HbJLiuUU_g+QnmA>q1p^Nm))A|Hfq9fzea9yG{14c$UQM^{!X3+ ztq13D>&zP(j#@pL6+e5u8!xgvW@P8*aC(i!jSOZoOoyv4ml04>c*c3+yvqN#fW0h$ z<%kkJl^6J!mebRH`9PjdSLTKLKuh)zk}wJSL5s)!z|M@FXa4OF5n~b#7t&?DYv1!z z(j7{U^6*L%HeT*^>}nv@VMy3c>W4K-Kt>lKRB3+oGoC4*yWHkfbItEYFE3N|)Ulc* zsX))GJ(EiMXl`j%S7aE}j&Qhu$ShDiF|1PGAPUE@c&7jQ5u}Q_Gs}J~(X3Sfq-?7< z76?(CV|^KEjn;b* zBmi~Bl<9*DD+zdxGb}FG!`O^2AJ;VhI90@Jdm^Hl*eo_s-LlTHA|_2vkuA;TM3y8N z^{C{cLr;~yt6{DZDZB0%%-|TsFZ&|b9}RK$2f}NQUSb4OnMG@CQjm?QkbK*a=6dCa z4+G;DNu>=^pjP$fJry&GUm7ChJFRNn;fo8^69oC6N$h~S!Oeg7;}1~+a0Q4JGkE8-peqDZ)7rJXNswDNHNvPU zry3;0p(sI4fus`HpewiNHZbSQTD9!B$f)-BSQ;U?$8}gqg+VBPC;goxcjn(y&qF%F zL~9B;n&?w#df0r-cXVf#8 zPDP;jkE@oXYsM{v8c)+Jy(fw6q~{Mk!7n0-qyw8qcrVrSxQh1Ahz0h`S@%pg;6D&} z(=}x>5otLn8h)A1*OA>neV6Vsn?7ibT(P>YR_{;AWaxpK>=t`1KJ|j^f6@&fPv89! z^GVBcTqonOCg^Kbo3_~Zh55rrRf{ri;3$RQ!Hu@FSSX`xqgu8Dw%$%eh&fSiC)_JL z#lC~*~jG+#f23QJ-cahD__L)#VenG z?N!(XrLncmz9{?xgu8htzEG6$Q4crK@@q0SbuTzC44+#8vzXWeM+PfDvpr#*2DCy9 zC$2c$O#yu~4zdjlq^Q$qJ$PP9uM?L3dTyNZ3;CyZ^u+DQ9Fz8iUc7s!fdRusOSlTn+E``tFbC9t5Vas!;wt1_Y6j ze2{RvgzDkbbbPDllYnQO)w13mVg|)x@))-lYN?IS)f!zo9)~Xdc)x?=PY!H z(Zm<)RFfge{_82DVLg_<2!mbna&D+XLKQBoP0lKjOAN~}dY3Y#9L25-@OK<@qJ?{f>ovxDtOj{7}Z z!SiQ*PnzzqnHmECUVXckEMRe8JdQj21xLa$+|7h9G_k6&`DK=s={}Sv7KgP3JGUtXTOs80u#5tVwtg0ZOokQ-eR5;SqDjL zA>e_6@f~u$^(PPVBs73NKALE(W-WK^@vZJRXCIFbB>8rUT6~t zP**yl?$I&!Pu81bQ$_FY%2J%6S?Mo?Hu}I1Jh5E|%b~~TVU`CL8j7Z%sNy)NTH+t8 z+BvPDkbf}q%CBs#@TU?Pc<=G~a0fwk%uOZAA5VWdx^*R?E9a5I;OcS=6AFLdLKIQ= zyH%bQg)o;Ez!&ML`c1jiI4S)-ftDu#R1=LwX`_>7H!%sg6cLndVqXd&D-KB1YYa1R zi!T3N<>uAH(Tm*h$byQCe}9=i_Zo1`m!eG-9eYO5SNEI^TR!^=#HC?2o(>wc<`SQE zz!zsO^I9Q@=&W5R4lGvtliaUTE-Yb$T9dc`$zLF2_^Cpb`zEbEKkOmE9;XzpX#BKiY^o@EcW;g0&x>PO4H8y^0cEAQpNwU1iv1>nWkPgnqS-Rr z(~fE_1H1nkT1I%u$zdL)5$IugwAdvD@a!_JYLB*8*3P@*#`{R-Q+Z&A!+U0^Fg%j<2K<4@Qw*tgxD zsLqrcMIATc96fJS{eU=aR~)~XrF=YRySvUjlyOG&Quh}|PYAyiWo`?BK$M2N*NsT% zZ&{GzvBOuO)eIGHSu(Cx;P<>axA)M)mA@JhH`dxgA@qN8~efFULKfk03KKw{zC%v3D0m-i9eL$TXKF zYEyZ=L@4~4Rey91d$08Xt*PqBzqq+r>oNrLoXV^vAbBtA@Q!^>`flOAO|&VIT<5Km zk4YgI6q3D z@vE^5q3-!X7p$AG*J}&lC^e1rd1G~eH!LYFD!*TSvK#Ka5EiEh!|9N>)WUn0#wWb& zcdunzf15#~Cn+Pg^%)#)Y>i_IztudB=?9PbiSCCNSK8vGo+kHPdD+AG3OtVTZmll)cu;~0pZ~|8*>VSUSx^^ht(9yAO$WkT3C$v7 zTelm(3(xrO%;fa|PGi#J*rU$J!PVy&bh+;Kh2@D{+4s3U7=3O38>A#9_0ls0N?B&R z_}kmgY?ejqsIh~6u2m#BNvinKg;WH4;x3d4s=rM@h+ocI*{{<91`LLlcbHAVOfoEo z80gE7sQAVx1&OcZh)179s;|2wI(K8H6HR!8IM+4CT4G}U315FC;n%b2Ojoa z4Oq_cl@Yl5C%60q`kbIrl|!Xye2lI2kQR1hcP|DvOb5)ca$!b2GE9#i-jckH0KKljJMByo% zB-p{fvK|RkqaBYpWlbdln!P{I(o$rJ{nKVcay}OJar!*p)L9v2m2sP$XDSX6)job9 z9I=yXv66P!I6QFVK5|q!80ab5Ve`1SMc~ac(7G-zL(iqd>vSMe4 zxN9s3%nDp!P}e21A$;cHjMrUI;5-@3OTQFf5j@dAHlhv#L+Y_}LWCGE?1P-X4STK3 zQtReaC0CCT3V5Cr@%R&Fw^v)chrb^oV)7aCTZK*f6IQH&9m?N9n9<>hF_vk| z(JzsOd6v?QRmvkVQ$`~`JuWnuDRrZWg&v2o8>cGmverMDP|3UwIgE)DjBoKX;C8L-3Xd8-11dpaAkf(-)3Vu%^+oDz3ASc$?A`POf;$^g z_53jWG4sujB6saWy(&{FX7b>JMIV;hbCgo_O1Xoy=>IW7l7D@JBF^Dpl`d zza8<+>!*+d)0gI18H_*%Gtp}8I1c&$Hc!={t82|`Nyo!Yp?LV`vE^kx*9EAESp&66 z(BQ*`c_xzPy;8BS`{ak|k%sjp9s5Rs(d?A=m?iy3T%k9r(>H>zcg$)8 z>N3SZS(n~B?~8wS(qA!Z|73ff%&2qDXg)_`MBe%hAVOyJ7Z3pQ12O(5 z+U+2DLRsr)jUa)xgYI7iWo)W8pz@x%1$k{;J*0-;_Ai8^g6X;sNa;ybAno>|i=K9> zlUqW`WEXlO6=vGC#qiATdjG~j-xnGL4mkdTrM#r$WE&SCy~?dhD~`8uh3qNymAX%N zDtA5ziEuzM0D|t?(RMUqIw5LKKD{qA8z!Ajo$TEHkwZOrAFFS)V{^&zKtW@GZ&6vc zQF*_^6-1t_*%0=AFKLOW7UqDFtp zziRILsxNlc?tY%NA|Ah^cE2f(3Z`Bi$E?8+qte$ste96HwfBFh<55IM6FKrKSqTx! z#TVX%Fe7W6DfHOp3o5fTJXyqBcVgS^N(Qt?j9!rywcmHVaIRyuW~Re{o&3ZtR@0?j z5a1BL6Rg3lPmmfv<*Sj&&VGZnsBLgpGiixTD5k@jY1%R;Vxc|afRoEHP-&`vy43AM zl=B(QF1g=%n&@vN0d4gUWAIUmF==qQ{#<=wC1xHEu)yccRYr<TvvHe%V>1V+?ni(6wU+bFKxvGk+UBY?T8jNq;eT>9{fCZ)0annh!^r6(HsZMXd zMb-WcHbTr$kdq#k0ER4$p2&~{D_AVmt!mLkhg!F`E@Gv)dx%08T}1Bf6gkg~L+M&+x^6!JADFf`5A>dE zB?cxriQLP9=>}*(`7}0%(LYu!fIC#!5emZ>vJUu@g>SXmIyIq8ew9Gv+2y?Ti#ayT2}=rwi$WeS z_G-k_rQN=k)4V&ZZ)_HdsTO1K&1$>53V7=UqT>WMre7=tvzBf7Ng3nfK4}BY*@U#u(nGp~4FvhD z?T~VmR?Jw#e{+@V(%pHaQe@6ae|1S@@$y=I`dpGB^5SD~Z{U5CW)<_ZX2BU!y^kXf zB#>J?SIE?a4Fcn2!P*XcU`Ic7FKXP=(V>Ex3Lr60Y?F}M0P}E3pTU>P+>03C+RI*s zfcWu|Ks2v==FlahxT$tU&R93=8xs8MRycVL{y5H)ygj;f9@b+UfRWT2R_ibhzNB3N z#8`>%lXdTLH<@XURz(V2qB8O zb+i16Ss$`KZF*){G1G*0rW5SLgmII&S{3;G(IOL+6}ehzb<7xTWRpKBs2!F47sBNk zxw$HHc~^UUZR69K(b45x9s)nSyfOy&+Jo{Quue?Ez)}^RSPNmysmxA)bvrLyaK9c2 z)tH(9OPLHc^Jm1F?4rAI5!msr@$@i^RUYFLRtS!p4V0~B(rzUcpc=|zlKf4V8E_dT z2?aGm!6D6y!ZMZjpEP&Vf8Ark zSG4XoL`zIJVS~bR-z2PE2wp0QjM5+kREn7uCH^2JG|6Rr{5oO(JgV0NFmnbmxU{V> z7+QK$QSQj#%v0T&C2;VDdbbh$-4-1FuICG|ml4Ci6SQW@wM{-LNh53u#9Vi->MlTR zrAnfub%{^uA6L@h-5jOYiD0g)3l4^751OOdcl2T}+LQA4Jv`Sa2XLH?u+)1Lsj`1e zVa7;$tMI=!R7AOw)Oq)LWGzLV9dnciEtOI#{N0MjBbdroMvgD^8iZ3%Xc3cR<-ZQ; zCKwiynn>jX2W{h2!oyk?>v|-jxQv-v?GV-0hb_&xCvHSbM@bJ~k5_TZcTKA6#3S6kzd)D?Lq(#2ywkH2&|S(`*i7A<9NIJi!J5m5RWL z)hAY?y0uj}w&`={1)Tv_YVuL%b5MNIp;PIzKhBAml3H%(ulUf^+Q~uc$t(o7r*U>K zNJ@Quiqbxg+1$dF5RM_bb7sZ@K{uHFSlpzY0ikaiZwE}7F2fif>8Q{tAIm3f+B=6& z%{VZM*<_K$#PV_pU%8xfg-P95KCE<6d+$hw^N1nJLa{ftD#ZDD+HmB%DHj0RxEl_B zy%emL;qGd0oX#+P>5_c+zYE)G-Nh6bx*>aG9kQKcx2jCmt(=gbARsNpiUVWQt;2}? z5%K$q50GURL{7~kQT^FAA-2}lenS1j0XrHolJcLThB}{hh7xET$4CyndNuQnE?mTF zsG?q8J6udbRd@WcThv>alK9Reml|xsX8XwWg*7N6FKou=3@1})KKKa!hTTt)=eEOg zkLeJ>@GXSpL(C3vndCl!`TMh1S`tDr%(Z%DIWQmdFP)weDr*{QD9C^Zr=La`J?8sa zc#izArqb)wU8gdRYnW7z40m8UBk-9E{t$ysxSnp6=-BPN%b}rikf8;}?3zVfV0n)C z#0Rs^SM+KoYirmMi^HvW>V3~VqQP}Ae0+&Fk|-9%qt!3QZ(d+d$!Wk zbDn~Ug?6BS8oMAhijX3tphI#=UIbz;l#{inmbRu=!FUk1sz)WZ=}y^$AaPKrDtOu6 zh%Nu7FGPkYuh{N(0q&|4n(_gn zo6o19U3x{Vo|b9~1N6TZlW<&SN0sHrIL~4ZxKd~(*b4l`gz<=d%&1ro&ajl4l?@1f z_{~KasxOXUgyAw(FxalhgNSTw8Ua#Ie@6rAZiR^OHG!2!kYynM&JcD0;{ol$gyK0Z zqPm;Hxy|3iSn4I4YF-B=DKmSkX=b6qu-;2h>Pcp;$V}~I51yNKd=#lozRqtqlLxU^Wg)1|`Iq<>>nRFE6$+F7dcGq**-j@H&I zr#KjY1~I5N0JBgNQP|lWsh`XoI&trG@DGw=BdJ-$lvwpZt9A^dhUs}q{ES3LIs|!B z!8`*m%-}o$9$#G1JYZ}E2KG+5@RN@8Fj7#>$n1q0u63ozw*~Ceyb8Lb<7=epIn|pP z44}kS>tN3{BG~4`tH#h()Y?2pS189VygybbtFMXB<(D8@o?+T821bEIAt zbh%gO{^Qfd<2%uFYDeG8$kw!bmAC&CvV1Z2qi3Y&9T~4b*MV(W8zPE0Vgb$wU9pkh z`oJ(5*9jYW!MBXzb#F|z((12R#tvWMls5K`edv0UZD5T#xjKI}yWJ6@*YN^_PY!nO zm!K%KH4F#J^x0t&5?r@Ut-JHlAUJe$K~U2lt!Axo77JuD7ph>>LS-3nM)vEfE|P|p z6eZ+Gi-a7$oUkUIGL-`k;wk}OR~HsiM?W9`UQ0u`Pl#tY_+=~t8N_p~g8cb4Q>$=? z6=~N75E7OL^?rOWBY>^jf(jUmHMp`(%);~G z$eS|DAijkLpM#Sn%mqUf+Bsv4`xY=+mtBdBc<#%$YN*7SeKNQd!aayV+gJ+!(?aX; zrIVa*5?NZ(Ub#T1>P7d={6*8-e}DgCyuI!#v_#5h#xo4i6}kC+DVIV#++fcwla{{L z*x9lFIbiMhGii^XrVeeC)Kg5yrWAyRdG$^BLSG$1+<^jDuTn{V73L!O1$i??QZ?DS z_}*Joo=5YZy*a*S@5kaH({KIP}pUsA#HiAGX2G%D_n0o0$Bag3Q5q@V;p8@|LK z_okY%tHZ){pHlWC6s?MDL&+5ItH-5yl;631onX4veDkYU^5Rj85N;>Q5i|PhxRdI* z^6sj;{fHBByiw8Sn4KtPxKsQTYg99*-iDk1*=e~O(+K6v7Dx>4(|6D`L%Z8-u! zY7EL`z=Viu6u{WNy3xyMZ{8s=7b_OgE{I=k2=rN?p2n>KT)J9avlC}RFrc|#DNwO> zVbwQjvW&8qam`N?ZKX_Z+HP{s!`sQlfAo0}Ig3Su);N=|$X~OuiddPI#fz9Y-@CrM zHg-X!u3eslYtr4ZQ!r<6UYLf(T+vmoMoMlQocZ+iu;5payE#2uI!-n<11W(;jz`R5 zdnR>%EYh(vB9+~}yzMh=v}3MR=NaZlSevLC0wq~`ipMiNfnNj?^Urb145812vs#wk z?tN=}l6-`AGh|bW#F@Mm^PJQRGy-b|o*8Spsc_*(${e*!In!fGfTWIkb zxlGV|wY%_Oovrr`*10APbp6<6NT`%zdt`3J8~&q!kDV8fURN1)`JEq8fJ``aseJq$ zv(ez~cz#mT=ExMUXOum=O{SzHunc4AcL_rpY`h^ZKef##VTq6Fh7g{v#uF4SGFW2l zL!mW)krjN^^dG_|ZjKvyJ93f#-5M)Y5x=j&Uq-R7-nw(mlztKwivI41z9n_&Q*4#R z1GxEPxOODvQ*GWwEAm%X+p`zL|I!5K*;rf(X1+Rd!sA@-XfEv~raOqs4Kd!*UGM#E ze=ejmSwAWbW-C3GtCjnNYOf!>C3Hzz37=2&4X9w3gQ<;4OWZ@zZ~$K0WdK?^ym)^x zQBxut6Ir;~Me>ZllbwspK?2khF~Qt|F;lf!wXsUp z@m!o~XEgs>iJHgQKU4CCh@Gdd6DDsykH}VH^B2JgI~v(2gGM5ehI71rbc%~((YZre zf~Bw6B8rNnQXTx@kriW6Xs#Bf*z-F@hItNj84nng>bdIouP6jJQ zKZ!?rvlA(LTVH#_oSsu!oJ<+f9bJ0x0v;D$Q<;WhJ%{i9Z8>)-Tw$5XndFe36zNac z7PFmrNyH=pHsV}hdHF4Ldr7y1l-FQfMfShNlAl4m6_@&q)V)0X>Y5Ua+^3z-W)>Jv zqoi;!)mS6v4D|d$X8HfckjZA_4t}-hP|Gm2CE&FkuY1X*dE1ssymuM-B$2Mtmgom8;jH(StYc8j@+o`ibV)vx2dU|Z!AUTg@A(+@Nu0mU* zz(wMdT$W+C4OfJcnsiZ@*}a2oUNiD4JMPk>mz^J} zy!N#-oXrgiv!+W8viGVw@x`xsvzy3pXvL(S0s=q&r5id=l%oi2mK(b5zA|*Ab0AxD z^)#}!oiRZZmSC644KQ+lBFG%RLyYqpU4>K|9EGj_!GqDX=TUkMaNLTrIMHVmDk zf_H-w2rM>5CHEwYDE5+O{aksNP)lR1<%lR1ad)b>_eHT_^wOV&30SMsc@a^>{N$)*2LsEU1hQ+OE7r5T@!lS75dO}3Zk`UZ-FiS!ATnOIp1 zq~a0WxrTcN?@;gM5IfG?%bD?qa#fu=qY<@uv_%{)yu5547)1YK>J_8@CXFrowh^WX z6Tp{Qh8!U_CUeE{@|2qIJyF}|?wWaSm;y5ll5T(cGQm+bv4mRRx1(*-`$ONqny}t3 zxhqoB=+O5;F4nNmdb(7&lan`-f*4#hs!Ft^bp13bQ84s$Os%>q;)#A#?eaRV8Z?+5PQ#Xx>OIKX$q!h{^Il`e9=A9NFzTg+M7d4YVj? zDC?(=b8iT#I(UaeIV%+Du+sjMm(=RyVy@4o3i25z9ovUFgBle55|P^g{pXMr@*UK0 zNV?vDiTEyq5*oHtWRUO{$$;@&p<{`KSLzJMV{#pfue&U17iOGGf|}FdZ~Vz-lPHOU zWXPZD%44DkSnO*{Ub&E?e~F5>XFpcs#RBilIT(JAmE;5?RbY0n8e03 zpx;f*!utzGbc-RE`Ecg&rzb;EUW_BbZdkf}n9`m#k zwV|{$Nsw<*Ba%{sJ2IgiJPgCrd*|_er~lI6=mt7z=6pE=X(?Qg6(FkQJoNPaHs#U4 zBAv^Jq&189d|2E`kAXLR3`bWoU;a(?^7;N*2FLvr$RWqPo?D@>;PA3PXwO|g(32Xa z|DJuH*2ma(xt{08Lle!_eNnMSVHjhg2QqY zL-H!#4gK&8xh5f{HXP{=92~e#qqajnGs!hlz}&yk#(6HAR$EwlybG{YLwMlnGg=Ck zSshRWUoKo7ML&_IHN7#(^`}R{8m5QDq0wE5nLkf~rOwtDLMtmUlOo9E!Kid}td?<1iPJZvVwVE5xHDV>l^sQZv% z8L~?ikn0yjD3_B6F`p1GLaQ2XHs&sdhax-_m%*Bb6B(j7s@GuhFZwkk%A1jZX#{k? z*G|^oK9NJtfU=jdre#WzrBptExo%v(FDzk~x-&V(W@5X=dLeLFr6lhAg3M!c%~Ppm zTH#-#oHg&LJPL!Z%z+RGp1bTMod+-)mW-aC<^gO0tl(cx9SQe?s0Ki?85ybdaS!C> z0usT=-~^)v&@4W%o2x*y);~JexQ~SY_S|G7{gj110FzKB(V@?lZKSTbRDZWx`f|dy z_s;o_f(04%_Gow(48j;JG0bUZ4rD`vG9N7YqXq7*UoNTdkdHBoVyds6)Uu+r2)7<) z;-}mJ5rUDO5!J}DtL<9NEKJ@L*=*s?7Dur=PX9H^k)s{M1^`n|P<_lTi$SZkMBKHBzfR>+ z2C-pD1;ITIgrQ41dt2ZLX`Cb@Xw20a!_&Ps1#|(ypltPnL4Gs7h8H>|i&Agx<x(;EQ4PR|F7QPn$YJxcW zhi^O4c4>E1R)vNn+>eV+E*c(O#VKq{{=ohw;L*L|aLE7}cwOVDE40%Bg~6g}Jqe-- z|K1ABI4?dFvb43gYjypi8x^@D%2AK9AG-Km*!r3IN^Zco|=0Cm<{FBA9?1UMx0!UZ(BkFa47VSg-t+x1H8}G#HNNg2N6rws;#y@ zzZ7uilB8k9l3?mn7yC)Nm?l{fyOBPPTRP3zjaS#eJM@7O5q#6Vh!)OJAnGSm_c9`W z_BDApv`LEYtz8kJwt+osQAUs4Cv`Qvz&jjAu{;j$P*qM2wcg>J0}K4IQ2Ab&!>w)` z(Pg<8vAHkbW}1~uJ;iD72ciuAy{lCsmf&<(U#Kux2_8G)*b1tnpy7G8kf!w6Bl53o z8vk*>QTwA5ZR&;F2@J_X4a%XzT8He7$cVn3lz64K47N){#0}B9)P(7V!omr4?y4x3 zuI6cM%XtO$l#905Zdxo`V{I|huH3MZO1GIH;Vp-%4sD9dz$19UmFxO zn4{}F^(@>ZAqF*7fti{Co$kuv^Lpx>BZOXJZ5d%twlkiZqpW zoj(UnT;?>q$#O}2jeYJ~w?VJ~NLab9ZHOhNUXaM+nRim+hlE3sf@*pqfa(X= zalcT|OH3DRK(+H&{_B<)s}Wu&iB2&0p>TDv8B&q5&Ljime7}6vTyymG!y=x8_G^~> zBqZBnc_v5>1~f7|Z?PsC3Zzw>FwS4cEW5liu+{%j1XIqs?ywSvK%cfH6u9(x(&XJXBXjk=G&1P&TlsU<>E&tJ8uMqLX!+MCYLB6(hz-|6 zt!d>r6s1TR0dsm@8A`6@o685$a`XTc8Z{Jca2mfpXt==MGczCepz(sV()YwKc02--Z;PC`z(+ zgTMCsJL_rig#wCxo#YJ0U(^H?MHYJJ+W`Il3~0CYlQdwCgNM!bB;M?%c1az`ys*Ce z)5i^bLtfZJgRm1Cq!p*xtohbg+(6t;FrgP4CmfWw*ePMz@UUQha-Ws%)AY$4hLyUe zP53>O(6;+*kz8@`pvpwX#9y<4Vq8(izC1us$J*U9a|Jyjl3dj0u_37kd~SuFA9@IE zcLj&gQ5lu}%O`jCsf)@)cfRuFkX_4xjdJmnf7v2wIbnIb4I5m0*%N0`xcA!A>Fj{= z(=(Fc-^Gi|YKcydy=W$iyb^zeU1~G4Nv)HlG#e@-a+b;nFzsJ(bU#RqG=8#TLp$KK zK|%-FYN?nS-NMf95G95tJ!~elZwT!keF7ot_iC~?!b6&Lj%U%_;GSZnFNT}Am0Bv; z{IR@68$`xW7&A8B`Z(-6OTX3F6POoJRoh&mwMVSy{%sz8z?Z=jW6|Dl}NCxzIpIl zA5ptzcr{ShYOxI^mwqdY9~kgNq}@1{=86T}d1}JdP>qFUlHnuSQ?p|KqoD(nOsUtv zPkCkk*G*JaCx)s89AI354!F1H>r1<&*6W0z9C9ka*texw4yE3NbE={gNkba3tIcIm z|DQNfoc{wSiiw^1|AL|Z<3urWFmn7KIMn~ciDG8^-@4KNKPRf%-Aq;YI)VP?MjjLx z1T1yWu74X3$Fd67&24oLWeXGx7UNH#h{G$=);9gF+sRbA>&=#c^XaI*O>eQnvWorl zg`7-r!3?cAFgvJp5T0(@y4Knour#3;i-rYTT{lXaLVy;sB``?Wc)OCN6g9q%r06-NI1ektB(4TA!0V-Zmeg3Vct z_8N$~#vDNC><=>b=WGwo6i72L8wl{r2{hG@fRWcL?QHH5MRo$m2+k?uf0D<+kr&2= z^pJW13IyWP0LjJE+YKr>14Kii0-4&1-{ucY22O7v3uuFTj>tf%p z+BZW#b0SX|4!cKJ8Cmos;LxF&+3}UUiTzXp;ZL_qOV@W&Gpc+woY- z4g6c|sRA`L^Js5>x2yge0eo}-*VJe#WOV92X?63EvI%qKKk%_yudhZ3R&ef5xna`)pm!aVtlKmH4g_FIee)hm4a zOVIv1Gw;_v^xOOTzAGZrxv@@_zR?TcCjfxkvmH<42HJUn69m3nEpTl9?bVgN76Rn_ zGL-tYu0Z^NR&%b+9PGO0>dNkF6Q3A9i^Jl=ZVChwT3E$H&IyAb8Qa0vu{L{MuI@U? zLBi%G;*9~nja=^1fipHX)_-Tp58{~GUEW~=Z~ZC)_dADz7P~s2GadJ-f3VtI@Uqzv_q;?qVgQc z2SmS~M-Omk;Ui|Q+?_!b-qk1$p;ot6 zIb;yja^t1c5Pttte7fRpo`GQUKYc=&J&@pX*wA(Tu~55yef_7d*Y@vIaVp8d>;YdF zT0~#?&sHu)B*^8|S6gyU@HDeqVE~@S_UGK!fsyy9Lr1zktVMtT(=<{_q$@SpzZoi% zVw{Z=y@-*s@4-dqcl4e+I*)Dvolh(FG=xuZNTDZbLZ%2KNs1cJ!RXvOi+gz2{Y7nj zfydQx0U7qO9LnIsykf4d=`qDc;%P@VSL9cEWMd&aVDsn*CB=SR@-n-n zX-4NGsqZ6a4`pM;a2bQ|UuO1NBx5XdYLt~hRR&xWAx%q;53AZi4X7v{fTekRofH7@ z{4GE4PeGFgyxIzIO&eZ-WcK<$oKad+Zk0o2un5_L-X+m)p@uB+(J}E#=yO0~tx9M^ z&a_W+KL|AYBF6$o0x3v6ZL)T5v>co-m$h$?xO>|k0#*ri?x@a6vnBmeWgpp5g(-)0|N$W(pKw8ty|5~!}Cc;}2{aVTC$0^^QZ z%^8L*UlHo9M=JWvSbT@s*Ex^R)^75NW{ZPeiedCbOp&J^28L=|{jICDTA_D3EbcU1 za@waK3h`$_d?T3u-X=%~KbLD|cD*#oA) zYM%kt`NLNk7&#Gd@`#M#Trlik-dLtV?Dtp4!lU_vXS)dR?`mp@2mVDFg}~F*nUiDG zN=KUZuu&0vGCwKI_m^^)%Gny=fDGg-vkrNdj>tzL6OO(o>#qp6+9-oC9K1X5B6r?n z4er9%5v*RqUL{jTI3;}E1)o54bsr*jOszNEIS84c2gIBGcVa1zM{kpC;%l*T_VecC zGt@uD6yiTCdTk6E1b8bVmB>9#DTRdymYXFdQtttL?PFRn-W-&Hb2kRyHTfpJme#I2 z%F&^7i(}OP3XzVuR+7u|&x~>0)jtwEZ-fxB_!yOch!F=a>_CsUa43 z8#4{w|0YL;x^^h=mS|+uwh#6S}R7gmle zCTjF*R;sp%@SM}>FD_|WK|@ym;B06heGKC+I)r$tu*fF~n&Y|xoYZ5)JYLWvKAXGO z=1unt#K(|pAat~_#n7qU2p@t&-CpXk#zH}X8^#|OTh^S@laOd zJ?|R|?*(hTMomD*`UeZ>s2|5l?>V|W>GfaRVWwlhTmRrcd3`oM{MQJ=z zMKzJlRt`3-$IeF9#oLK7jU? z>89Exq(Li7{xNyx5RU)iOg@E)-#)r=8%u7i>u)1ZEJ0>+6f{lC(fvEFK3@$S;IlTc zG_yJChd@tV)X}F9GNrbzhBQ+Cz9_d=x0=bGS~2`3SOu8DRgs8pJ<2gsS-QAdV8YYO z#D>^ci*xpuRBc+yNp|*=_rC!l)#A(!;J94|d1PU$Bh<*l`9?md@nHlcsKeNCz3?Ge zr()g}IRMYNkD<7k{sC9-VF}x9TvbVO9Cn~i&meqQ%lhgrg5>pLp^{xak{!4OazZ{a_8Ix7ZZ`toyfjW~HSFBGjnKWIOuT zziq6J%1RztW1;ZVcCPz)OL`PAn!7L3j(!{}-I+yN%muUNuq3krN`*>9)v|pTBJ1+E8y53#9}N@un}4EpHq7V!W>nJ z>LB)vMfZHj(@%EbzC@QsjV(RN$falZ2y9J^l+H4qOsi60Ldb~pl%6em{(Fy&s;Mq17_=n-;xz6@Yo}$o$ zc}k0i;c>eJh-MxUKxCkXQ@F;rgb;s&DnW}GL@;ha26Tr%Jely0SN-}f#pQC}qC#V? zlYN_SRrj}2i{va|X0#i9P|~Tf>z>JWAnZAowk&H7(q{&bu=Gm=w-fPV{lNuKEN;uN zO5M9rY(n#^%nQO>S?&#BLxa*`d+{Bu2^@TSOxD49HbDXCWK?LiVMY?ne{679)E3g5 zooU9bUD5z=oas+Q^5!2BoyP8B=VZcvh7RutS=}4T*odS3R!ejeh}D}L?K73QJpg3r zugLc?nWC4~1}SV88vP|Z5Amem1AaiXU$nYJ|BJ`@X`=UChbck_==@B~Fk6y(pLn^F z#v-U?&Q-6GVVk;}^=N5>xS1uZ77Z@*e(bo-hdrLCM4T!y_2f%#KCdH4TXbh=o%(Of z1(s(LW*&V`h&DCAk?0}(sJ-ePIIgm z4qL0jF>e%RC&T&h%H~bEEy8rSZ03A>qOs_6_+?2BWl-=$4BknQ5VZ=#=Wo@As_FVO z0=(Rv_M(JEMPy?d#I4kCZPEcTw}6fm_Vd-JoYZs%1wN`1 z>*w{vmTn}O&~8Q!SW1G=)g7ikL=qVKtUl-pZy>)1X%r*i%u$FWwjP;Oq9DgbsX$d6qbNv^5a_Rdj zu+?M5Ue@0Z=$_SJUp(%EdyV4|w#naTcj=44qJzZUzQ7Rlg{25i_k1RcWu1Xt0Lg)Lz%b{Q@fbSj@S9%FCKK(iQ&oa{RLBJ)4yoZ-1?I0K1(bcT; z6!1SD1Cqx6&(-i3A1_)mQvR>eKaRYmwKL;+e!0WgV$Qv7K3~#)v%{>b4H| zGh?veT`~X~Zb`)KnzB$-w5Q%M=}->2HuWwq!m_F`STDf8VrU|fyp`kCWc@jZ&Bk0r z;LUDitAdnwcxpw4a9y6gj9xuLW<4_RoiqQFe8rxdKRW7{q>g2C;DBxiIa8 zvrZ5C$KtGm%6X;U0OP+QvbB%xE~jE~#Jk^iYEU~GEW39oLTw3EC!&jP6UrQN1&=fjPLKTH$o$?394y`x&u6Z_5>xa;=`!O zvb1yxNW7%d9B##Svc}L;#Ddf|*)8;mD)msNQ&>GJ z&Ul8-)(X;QxT9Vzo7HU5mcKdT6!y1BKlN^5Vocrqv_%r9TA3~xvj>W%U@wD8% z2j>7d*-&@7+CtZVPP$3a<-C0^l(4tc{JeGRpP;%FJ;809RgV4q7IIDOYYJ{354L|^VADCC?d&g& z1UE)UPYV~HaL!#dNTeg$Io07lcV7=dyinC%lOQ$Cj@mp!k%9LO4)nnsZ6%D;VDIxu zpF=3FWZP~76*^b2Wn5t|f0nW`05d)b59W?~-{3l}(>-aN=WsN!Zeo3ro{N;Rehy`hhH1n$D zbC`}X&S86J)S$${=GVdGj?>%5Gb(!AJqV{{Krog2w|BB|=4>=8(N6T$2$aktrd1?D zXK|Xo^oR{(yX-ojs9^H_Gqtb#BA<0A2O-w!I(mw4 zf7iDnd%NdCl;}!It}U^CRn&mU!jb4AsuibGlddo_YL@9&B~jNG_6Gk$nILe$chAcB zZ6}&D_I+kZm%fv7e6z$ggAoo{y8TqMu0^lu(+5!(BqBr44&PbUXkH>})gRaQ`aqGv z;-oV>@ALf^bG9Vg%b*}3#((mH2KM4(u?w{R`$;6I%^J^$P`v(S7Yw%qOmOPN+Bsl7 zvwx$MaciZjV0Xz~+d^eecpN4vQXVGm!xs7c^;ca!`|YENE7{F9yuS%tf@{lT?S~Mh z&Tijik+tUt+%cjd^9a;tFQCEr-*umwa2(MOpZ(d}^I9s-RX2S4oS`f>7Ib z`MpR9M(v~9&R~;BxgxeXG=hkceS}VN6^R~t(CAlL3c20aetw=zih(GW zSmWpcxSH)?uSz*~`$64>;*55g6FOObbFbAz4=p({8iHMc<_Cuiz#>d+NH=Kaq%3rWan;i9ZNxmqH4% z6B1K@IPsx0b#Hq1UEV5^V>KE!bApERCfCQBRr2dnjvI+FB|HNB!pC<4-naiKSrl#T zQ~SJIjgad_^3uFn`fQ*D{Pvh)W!W8US2sN|;b_JNFETo8lh=@zgP=MY*^JOGYO;A# zO62(j1{Y+mb23S>VJf3O6!X`4%o1E;%acc(w&DdVDALCZe5_|yPg8;VQ@i}r0H@ip zgUyC@E{@Pqc>82Wq3@t!W!+ib;kR8b||Y1{AENa0gpbd;u@WVm;#;nZy=VSTNr zI=(oYCi9#?HfTM>nWI$;k$`(dJFTVR%5VSHeBWnZa6=B?1(r5@MEmx~X;BV&UHvu6x%fs9%iziXP` ztw0$_n)(?fxn=|8kXT%IsLMt;#drzk#FxNsyf<%}@1}emGy13%#AsHhtaduaclyis zkTu4FZbP$as4sg%l)CH-JU%lAqLioYkc0x^it(86eI>0phmMT17g}cOJ{aXuXMdde z9St~X!CP9>%I%k*H_f`Pp@q=X#tKJ#Qj2^O%U!c+)W41M6%+J0W<=v2u#}ePQ~sdc ztTv`HzGu#Y;9-X@C|{ivTM)CZMFQ&$gb0EXQ%vZQU+0(Xu&c)F8!jJ8`8PL+A5HFYFty_N`HxbZ8>^_cWBb^Y#d8o+HhV%r8Eh}5e?+021pL>n++l=ur-lM zyAeZ8rZT2S(Mz<|q}pdAjv5S8*=ohu%%uCoBr}$`Qew z<8W?sV{(i78f4z2DkvP0f%L0+RX~;g?Td68UK%nx6~Znida2O4yZ}Kc)cuFzv(Tw5 zC-%C3zFJn<$pq|~`?_xAlokB9!fLtU*u!AA)R`#hmHkAKI5V5@^Q3;xbo(QYUA?9+ z=)wgC?c(Ka*-i$_N^wXVd&Ori&^9ZFe`|OM?8!%Rz`Jg-7D{t7+{0*+5IhwSYQ|^4 zQc_)TZ(^~mLL^5cXd@TJIEm@}UgNUX&tnE@;WoY+PTEjUTEpy$~{C`GKsscMfDlE)Clo-%qhf~-?Xzz%CNmrOf1Ja>}IKD;+w-Kv~SWs!( zV_*DwW)lc2=%)h^VZ2=j*}b{?fA zMx|vm;^a3h_}u;m1`JB$Zpj=hRs%Ds{HBBmZ`nU0dxq_6NFs=$(EyzPPV$_d$?xQJ zcU}J*QRvndMOqA;hagybn))aT0>~sRg{4u0sE+{u97(=xZFc@(#QLIzf;ZhIc%7NY z0>2{qw5f@!&Ei|jUFi`-PhPZ~4r36Q8fi{Yf|WmO6uOOW5sw%=@> zf0FZ>f6m?y6>#Ge?Lu?b7~%3~-ysO~FmaXP`z{?|^}z;wK65>8+t<7#1uKAEykS(6 zSqJZo7t16TN_n&oB7?D z2LFgRPTQZFmBfA#Q|%RpU=}51nTlmcpf)lD5GM^Q_XO*64h8fuXIxm%(;$b;_)v(T zZ#7*ojvb2o%;opz{A{gqipCTy@T}ouURko52_>i1Cp92PFl6JuyF5Idm-ikRagb62 zEp`bT#%xL-4BFkMe=lWAGM#*Cxfm4F|1x!cs{P(~3=U}|wTF@o1w|r|DcC=bf@P$XRp2b8G7pH zZqd&+1RZe6*}0b(&Gx&rJ8qfoY#Am^uxAc?-B3>n%?DB(7@QM)O^6h7|L`S0F|46k z(;Thj&|%(}_<;#`Stc%G4?bA7!xQ>OIWH^IAUq>%^<2F{G({yMLtpH}4i-0i565qf zfE0#N4|nc3^Z(auA?ui2v!7wYJz$P!I$@=nu~!}xOaB?0A_0hRqjB6LntoGk&=fImfVWufg&nL$pyi z%*MG*}-ijJr7bbao%sUe&-Ir7u`UFuK1skaZW`(qd?5%yZHH3xA zC%fWVn8f~SbmBdAn>n)ZBQM@k4Z9&UqT`x_d|6B$_A+oQcV1$5$<9m)8R9OUON%(XJ>T;SVO@?$$*z zdcnMOPjb%dV@<~Ybv~wdu2J!o1lbv1jR_B%A(Pb_s&geEtQ!@9T2rctz7jNeX(RdkD-2?1< zGd|D^EwrysZ6Rgx30Y zQ0#BXZ6dXAR*8j6J&uW{9>*QGXKd!;@7H%25x)h!%bTV(F5cWv!kp2Pw3z{ZvYg_j zqw<<@Calk_MnS>a6_Jt7nfdpUh2SU83%D;$5Q3tk4U>ebNxh%ScqD3sw!j~WB`&5$ zQi~!L-Ej-L=_KhyBzKgT0UMvB+vF(YbAydNk7b$3#m&j;*m;VAw$b8_TLX2P8$|=2 z%0CN!2QSl49fG)?j?L8-p4a9?Y9VZ^a{jNX(y!p$;Y|g;e_io6j3JrbE?mV>Xp(pb z$?w3uOxE20q=K8r5AEXLQuXZp7Z0m~(XYz#50MV43T#ZmNL$p&;tV}SPz;`GpUZHv z*y*3gxXw<1ioe*qQz(2E-w%!_zE85c{Q#7R$r2t;l@?-Vo8r?asf^_kE)Pen z(e>KZk@(?vT0WjIf*u-lY)6uNUW7*e1dQ{FY=9JF*!&S@`*%9}$b5;mVcMuki}!Ty zuoV1rm+ClE`zKT}hqLORgVdLfqeM=}^B7e$Su(SWk%M%SGz zi&1lFkJE#!$-6&h^;*}`z8z3>@lTMia9x+BVtwpXM(Gv>N9ipcad!I7Z)u0b&Uo9= za)B}R6>W7{NW=|PvP6ya(h*+h&Gj*M4*|38sWz78o~$@TH=OqTm1#84W;uOENLlKGgn=8G zajSk*AEaN^uXbl6BBZysT{Ohsbu0sq?M#3MP?cQ25;!|O&*ZkLHG5;XVateMc851H zl1Y5(r$X@?{b(}ovd>9jtx8-Z;Lm5pNVs}Qaz4erGtrYu2bORAyuq?dIu9gBIYW>q ziJW~F-B^p9TSeyoG6f3TIm_KR;&eHv-rWKHD&Ocon$}{^#0jkn-Eaf9cxaL z6|%n!^iqxY3WIcGZ3M_JMXXb=nh}9)X^I%GMSNl;iG`^zgDqCzCSr`>YurQ;#qX;H zY4h|TuAK}>3yR?ck0p#XJ#0t_9cBKVwL*#NEIzlxkbNEPKV&qR_57rdvkvW8F)x^2 z6v`8-3NwLcM2p%Hmw1>zY;mSw#_kfl?sBIncp$t0-Rx}Hyt&N;7^~E-0GUGxS_QCV06GnrAo$m{h*#^9e{)VmX^!*t1pkz z{|+FS41{qEupd-1cy?C5|$&5unE zoOPv1C@hMw#@Iij zxr)gXtr7?hG0!gZJR&wM$L}J*ozcuF9AAt|`4*;-*M%QvAm0)c(YB(DU~ztwUdEZ? zk=Q=lvWN6A6Zx@?<^q9Q-|}ty@d*1b4{ZPdYE}^=nXxS1m01vG>hsw#;60n z+oa!bqtW#x584VdEV8KJTZf_$wwF4Y36^yXi*9&Q;_hI|WT(>|C3T4HXx`>6Xu~T1 zkPFs$)#0-3KFwI3ElAfGO5g8Vu+dE5v+Y>OqZbj2KkM9*%-3lr{x4KN3>y}e3 zJ=hScgAXyLz)fQ%4Y3!x29XTe=iJ~3ZjxB^#4!CFLtJx$j05f$bs?S7XTJy$%kTGR z@jMLjM0SJ)5`qz0x^@_dmVW7rMHT-{ zScqOF42XBb<5%9vnh@iIUOhpLg|h4x$$Y+9RL1GmvCuO>?OQ@#dm&-g>yO^5$jR$C zE-xRM_z*EC8&6em2kw2ecrzr$9-{HPg*{o7W>kzkP`IZn`!+yI*Yz$@>M?CRBd?<2 z;XWUy72y)~)@)HvdU%;ZI0#lw56sR>q|ukvr=%cp5XaECO5cgUkbi$)K0tJN!_&Fo ziViL;JugxAl8j`^kWs-a6mzA3Vd(NEGB^-HH<|Q~mNmd9?$7t2zAV&ir2q_xPPTgl z)EsNFeC+*I3&rkdoNw|IDP6?dj%Xa-(V-Aa8g4!Sj)CULslEG=zoSbNewH}lBlY(J z!nSPR*)y)=+^(TJbBYoCQYk_H93Db)R=SjJ1}++fO~cOnwow)?d6eQDg> z4W*O~rpNFUVFY)3%vmF@W!t$D3^~^Hm|YVh*(iUt4e6WZJkuj&t5c%7_4WLEk8DN* z|HLAwf2;P1L4IKfn6@265!ar{0ya=9BMvSy-Ixs!1mJD_f;Zk$CQ%CkDu(9RE&O(9UyoR4L23u`(off zJ|ptRH?d|Hp~km!BI*_C3R`1_pM8Q}k|qArM_kfktyCBBIWW9zH`CV1__th9p!{#3 zZU0q|%>AM)Q+3>_)vOLKlmxysZ%X+@HdU3EgTE>cVJPwVNU_}4`*@%Iu4Wo;T8 zE_Tw5Lk}?|*lQ%br-Y8G{_-6F(fN}N`g%H(#`i}s?PTfU;MK_?x98e`V|gONeGmzr zrP0@I{g?U;4ArTeFs-;EvN5uvT3VhJf9t}EfxbWBFz|f&ZgT{gqg$itB$aj(gp*~* zGgq12tbotowxA!*Z&wgdvT8&XzR;m=Ime&2Q}9GLi1qX+!?vHcQ+@6`ixX=&F$A+V)wCpME;)3o2-9Z08IRb>Elo?m^DD_w0{O zAxQ_*S*$b@E;lFBbjs4Zq`6b+e^nfX%5oHQ#1YUxxN=!sY`%#8{=eF1XC9#S7hv~Q|MRY+S(4Mxk2(Ta27)%`?5FM1;`qg; zhiX8Y>csfGPnM$Q)zaX&YC6#*?D&S<&5NluKy|W*(^mF15R8tl!?)&9gnN$oLP3vx zoZDAqmYQfie6g)KBnGQpF$RNpn}2RXr1#3zA^4Fq|5GtG%}pdhs<7RFc5BTj79Pa) zys2mgg{se)BKtP%1C3YgGGgfBA0F4w6_b0dfbCLoFvYVZBiM#}?&_@M5cLCL=RGf(n z!M5ljfG`ftQkbzk34Vb#YKhcjv!q4oMpZJ^>!qF`vUonYuaz!E+==xyOm6aw;cl3f z-Q|rSE7qvtm3R1EbC{>S>8@+w-$RSxIMq2j z23^%Jh@=bAX7=UNh!a!bJPdN*gJOw|t`vig7U(-ZjC+TX@o~)S# z%I`ln#e~c^K|_j^RRlnC-h->>yY);fF)OB8EuwO}%0Sn$T~6PW0`Sy<(|E#d4q0JB zNg)~KR5JB8f8Sq>jN4|LD^3_6RXoCt(dbR%P#23}=qZOI#KN~=n&wM*p@e!5HuHx7OEIN#EH{u54>1hg7>fAGlIFUQrd;xi5OP$%5u5TLMqbpp>hLVq?%>! zX?L9ubA8Krip7{AkwL!T<*cx85z3&Vu`k}_4vS#siaETbUsAx1%j<2xe68&BrdrRH zY&}r!L|`ILSmh?pP&pet&z_hb-Z_hkJ z?U2LjYVP3a^%DFR_uo)PL}dUpwBa9t;f3irW@UBL--tZj;KxbMLv?cAm4USrxCn}b zMhYdI|5PL?GAU&^SCIH>D{AN)bfczvCnGaC4`@{$7^;~AN?NK6#;fipUJ7fpF~TYM zKN-qb8EbI{Cw8HU9tPpja@$p)g-`Bptes(#n8)01lsOM#NzS;<=;e(5Q$$1B;gb~n z5Bh?O@qf}6EdS5N{U3e7&c?|3Kj{k&7B=?(PfK@oo3V?TZX0>FN@A4lZiDS+#agTL zXlqiGt%}Bfuhwgosk+=(zU{Kn_s(CJJOb~S9`f2q>)MV{auOwlQWWL}7G|_IQ0_&h zc@`(oBU;;7o$TZ*o8zl?lk;SmXj6XLkiu$fdhK}BJ6WxIgR3TVNlCCqAdDN7X=78bwC5Ao3d#t!{0e!RFfGeLom{PlHYZLh9u zWdmpYiGJ$vQe%p)$+ta_2{^@sQZ1*8Ix;KAX8-A+4V#xH*jIWQc%`fa= z{U=ihDu3&HbZKRD`Jre{I@V|VH*-~25}DI5DM0ou{fco?x3WHmdXY(GyE0Ft>5oR0ZR$KlxUOTewJ zJnGLD@sO8M@R1c#5Q#T80%~An1u;lye)`2h8u0KNXZrEWpZJSI`D0J?))%_-%i;7( zBmO%{_T%3(`-`TvH9R6VGxu@}^yNJY^h1v&Ot^QO3p@t$qshu17WXSaApD7y!^-5^ z+yIvObNr%j3qHrh#QcMi6BSz0z;;J~y!KPW44(P53iGq@T=#`VT8xU;Y-0Jt0sEpK z2ICLeuQ@#UV{iAXIE}!Q^y~QsDWL7W3 zwfM)bJ%n9nK7e?iyZGUl;i7z|L%Kt-cSyfQwA%Hn5r~; zV7L^Qr%_&Q$3qjIh|C~UsJ;_J|9weAx#TH2j8m$OTvOAcvWImr2Ii$Y$e3t}YSpzG zOJ4Yd`d$~t%vd;6>y`lPLhf0vMhz{nS9$+DD^I;>SI=3RXrK@^W|a_|By{mcQ2Cg`WhGRmY$lxE!qU;`@Te;MAs%3VRk*VzfVUc|(AL{kqHNC}kLe#4d^g7gcei(V<9 zj$9=4Wzqn~rZ}*GFte_V`t>tSDsMN9(OvTK!1OnlzV1QvX)g+G?4TIIrESPyI~Mt& zJzAIJ^tPoi@T5)YeVBXOw;bm380L!P5Rc%DjNUbz2noO zeZD8F-9A1K&KM~K2M&urFk9Y%=C9B1v(FzC47|rdbSvP>S=>WW2{$>Wu%mK{PQ_A3 zKIehzK|T2@JH3$n%()h5dHx9Ij@I^;A&wkxtT4I1Xvj-U`XvEaqk6KisPJ}G+aUaV zTFMbW$)uQB$4%yf9+Q=DUc4aah{cFumYQmSshWHV0l3zR7WD!SuQx8jM@ZaehFkP(0g&WuU)n$*b!Z`HpCtL8=er#I9$utNa5eQ>Fd6o!wlA zuz+OQ4pY`#`a)BiahHmWvEyUtmnb|s81Rb*H5@S<%2za_3^-6OLT~JX3_H}G)46b9 zgvA#{HMcnJSC5ZUfk2@N3v;;hs=$onD;lWurnv|a7!?XWE5qP5cs>)=4Nu`nW5;su zP3SHI9fyo}>~yiG-?O&&3S)tg_KEK%@!dXcSIK~GG?k7XcBJeG;$ zu0GzY4jZJudXnmG;VmDxoWIazXl92=qGghogX04#bU*d(q*N4 z84A@>US#eR(F83F_Q~b)u>8a<(ys*UE_vY6VhSx^Hb%Q&?e9VV-KI#TMk@dZWYPSf z1G2Y&B25}5>WM&FQq$EGEgzxzuF9E>Q^EXjt=cX=TI_KFMnJBvJuG+R+Maz>M+?{>Q>CRw~;Y{U%%+>)Jz@3cf^U z2y{NYy%K(|q9l5~`u*O~;G_2)O!w$cRKACgWG3@DqIiD{s-P<0inI_)%G98ac~G)F zyG0BMaN%jhC90#G(L&H(N49%RetPhyAh_A)nV`He+WrtkmAjuW>;;bz7p)ODMMvQY z+fss*L~nBy&5;E!GDE+4GlfnWPI3y2l7dpe7Sp5^GfXZn%w4>k1Xjb``mP4n@Rk)* zMv0*Upe+G+c*HJRmD=t2#@sSMN9B5eKnTXDS1 z0p;KrqE9K;#3-^-6-LOiWq4=PYBqj_xT}Yd*Yr?P9>kn%cgioNg?jy?P?2>ukU`+| zSH-v0S|i1FnN-j*;a?^jZ1$NsvgmF zo6jGea+&Jb3z5TC$N*Iz)c#_(Nyd>rA=zL@%YbI$X*?^ml)>RER?Y6;0&8w6k%|So z)8DS#?shbms#v47Qtv3Q$NH1e#s8CEKTx*L#%k54=)umVRZJq*Sk-`@I>Q0~?_AQ= zi6x-rw?jdvwrhA(2&LI#%=dT$+U~;RYGc1iYAK?udufmT%%(FwAM){mDP8!MV<59l{=P zR5$ilAtP6s08(l?l6Z)URcuM59D-@%#JF~jLIKbkjSPJ4+Vm*1KC~Sb)q^D(PDz%b z6`HBKBhEBH!x!S9lhnYMD%p@c5g>B;Q*Bx`#i-p$~a#}Qqxp=Z7e zzv@+sYv0SJxe}`Yd3nbPW_eyMikf|wr)2(|5r=^zZv{ol!$GXj*+iJ2m`H7Wo1rAO zFVDMfhP)^-MB}`UIJh7hVwgh(je*;OiVFS4RL ztA&p(Osh`S3<5c_Uu_UIcRmXRInZ~?8lz5@;6Fx&Vc{j4rh^I!9A1VO{jES`o&9^z zL@zAEGZ_n+{x=GZI!h5;-VE70iF<6~I2LLbtXA~av?%bNU3zXEeT_T5#UEtME zgJO`}pju7Dgj$!mpo?N%72h5R+$vZ0eV2-ptrxt0QUAJ;ku)d?5>)Z=cN&r%wS?NEUF&6 zEhHVgV#HWI_Hu~he;q0smYX_>Rz>z?K&l}N`fja|i1GlWqDzAEr!4tDL*KP$1>LxB zfxDII5%<)842z4jJXT_cBfvU;9C*w3btvyDgOTLY_p&yp5{p{JU#1Y!lMB#D`LU1E z7rZ6=sb)_#B=_Jj1mU47*CC4R3MEzxw3OaX=nLSw)VMse0q2)9-QdUgmkxlX{-dtd z@BXjnNRkv3x%c3L-yjUO36|6mmi3%f`QQm=Ph{E}eR(Dw{W!?R)T-o5S9Frkzg3Y+xU?%{Y0&TrhDF*QTV;oTy;vDEA{*_$d1)O%QFmlR)H8xe^uLh0n2 zR0g!bA|orgK#nR>Ovo7^?`!W4;}=ZA*ci2~91;sP?#wy;g0wh!$WBzOm$_$ z9Cz-ssOP?jWM{R)Fmkc7dxXffxz1;K;WsSsp{+^zjQMu;$<0 zOmqJgtc9 zGSv$G{la+9!+ebIsq}yjVFv1*3O;6LfX!tDQ!zYhQi9;tsg#9p0>jAN$!C>P+8zYF z^z43&p~qqe)WWGfX5^!_YS7et!F)FcoW zdqK7rET!@W{zWv}y7jS5X|Ia1OeICzTsD&|$fQS6?r?La01|b`URQSi+esw}19Y?K zb3N}=>DVC+;c$cPMp8KGVm&Wr#g4?{ReAV`JtSZMZfk-Y^R~15lDr~Qr#eiCSxJj5 zUhHqFL+uVhfz?{MaTO;tU)|jTzj;Ffbb_skhkZNbOkjmp*F39>=7K$y(LV_M22yf0 zc|WOo5QsnodsWTX=F-lS7oZ$Bm6E{eWu>FhxI}3@v(rcwU-f&$JLcLEZ~&q19a2Oc zkNQx;BH>}zHoLpjqf?%Cc$}LUfHoQ= zx@v1uQ+Q(GHp1wN*fFadzHLFU@LdK$Y|`_1C+i;?(IDUwD8a8#zs4MgC8I*1pAr+gw2s032& zoG*(hsFWLGQJ4>#5^T_#tB!J|2_xDH0lZ(te-N@xS-ebP+uTN5yS zLEwM%ss)h%gb~!{CJ}-(T=9?3Jf5Fh;K#0zdgw9P)y#H`6nm`?Huvs~nnvrI&Lnzd{Y3y+QfLvz z{8wF<`R>{bW&7``5OGapS0_8mJFC&#-RYe;5~0wk|8nXtk33l71{g19pjy_O%m){m@`y#n{v zpUjL%p+{I`#f9!?%+_*y*m7{AIY1&U>`XIBKfb%AKq8$pOfU;l)pC76FL}!UMh>*L z-_L(a=MsQAbcIH3O`Wj@a?zbuDY^(f}=Gw+LxUcuS)-u@B`8)8EC02NidvAqexSbW_ z6+ViK9+!4QYtDQ{gK#z@)sO2w`?$d6pT2*-XG%G!$B7ST^58y@{gJqFSMv44q>#mE zJ26(hZ#X6$v;eM6T=pa#8b*8v$)&}Jj}~dqXVDD*r0Fq|-7wV>dKwRgAuA;L*6AMP zd>FisC~QKNRrZf_6XhAOXoRu{4tdZCp?z?f4_hKR9_eP8V*{-?+E~Eac|QIMs{go# zd0xLxk*0ui(ku~_!FzhM))bh9%tGk&I4BJ}&1r$FyVu|0dYkRouWYt&ugPdQ!(qN# z%J%}&gyw+KhSfoj=B)tOrgQHKnOYUU-pY5Gj1Cjb3etGRInUnM0onv--wxI?B4IiIr4 zu96W-$r15wzXhaq1uK8iFQNeg+gzWZzJf#$7F92s8KA5k%yAnnw1PP;E=nyx(wg7N`SY3MkJEX&T2LE zcM<;L49XFg{CJCTyTXBWFL6tg!PY`k#U)}k5m0kj*FR})dprylamM)kmM^4eo>77$ zVbrif@x%dHz zgGm%W`ECLZSGBcyvyV^PEkXj{4fiy&i2CYRMhBPBLH}kXoHR>p&C$5=YtvqmUU2y# zsp)guTUyK@-jy6@^|-iBfUI^dR>DQ|;96Tgb7MHJ49XRdD`Yls4Epy)WgqZQ6k6Y) zr(Xl7fi&MmBXteR+lp%&#vHain_xYefMWobIJzB( zi>rWC^8p-O8NvC|%(ExTByQ3pb%shYqQNqvlu4Tg*Ln?>cWNDyrft@>K?KU~v) zl1C<93w9_h^ifhYw?FK0WxLhyKhdb=)n;S)!6=DVt}PSn`rU|3U*E0tSU8!qnA3V_ zp=~)%kxk^L6hs8S8D$?g8_h$dkHSv=PwG+#T4yX+J8+`SMVH_oTLvz2n_*a(6#R~%7fO#T%kUqevOnD+%To(V!bew*B5MV#a11faoZ}toXncKGIcOqHL_Ae9oTA*d$mX04Ne?+TI)aG(Y+q9OBe0;1Q1gU~ zAW|%fc$yzg5YD9v9=@aZwf~t)aH!N(`5A(ah>Rx5qZzf{mwR;BX1u+eVO1`5<;Jns z3T66J3Qd0aOxw_AQDkWfA56h^`Q#l^ zL_d1Dt^iOT9c}S{W4g!1>7QvfyibZotA`e+w*f6u;`+9JF*M5XlH&{F3!w#t zrm5Y9?rbUqs;5|!$j_B-Q^?nfof?yUR0HtM(nvX|mdglXV@?uL1(qdg+X?LTyhyAML} z>!IUf4I6^T9mmzFq4aC;m$@`g*H`8ci$SSQa%mDI%p!Jn?MtQCFzrU)^_w%~9gx>b zB#29*CHK}W>SLKwNl#q-E<%;AlBu(X@iSJx9l+ZCGz@|^S;+aY1jLWI>ZD&;(; zXfwl`KToTIu_=D3U>JelP(dOfWsq)=2KZvkh0Pr^Qa|LfzV!G?$x=weogZe zTfr?2@#godXqwgtl zX@;aAE0JN^4Zkp-)#cu|#1;ONk8T(N68DMVWGYLhBu1gRWloFiQXBVyp&k{%5dcNKtfw8N zJIp@C(T#$NKPK_FZ;a}MV=OAca2c;*uHoZFkr;WDuFMY2d{q_|9ZD>%3U_I{eZ7Wr z*Z+b3aj=x_zOQorDrRcyHw66ZRCo)n2Pn|uU%(r54Gir1O>mI3a34}-LV~Jk*6-vp zO-9RZ64E(dx=lu18`J-Ee~oV;#n{S69694nKRWT_Y;4<7a^7>oFBQZa(~a8?v`Zd< z)+(p?6 z>^p;aL-RunO6A1+8EVDXLSndGPkGe_N+~_;pt>U9j-fF`;ANDI=!KZQ8&cOOe;qwk z8##7&LpofgCI^4qI7KnPgzN=a%UR4dR*H{;&eFRJ%TIF3Vy+0{D9IRHGp z_mZQV#s1`jB*!gV_*HL{Z>;Rr(-G4Ylt5(UGJCdud97CA|r=^BKuy+}Q^E4gJ^iSiM~Jt+{vT ziR4zy>Msw+rVM3S=9*Xn$TafXF^LK=C&NVtO z&%2mXzDOi{*U3h+QxZ``J+xq~Qp3Sg|Lk#50U-<{uIXFVbm zi+uC3G@)kiVIQ}BYw%OE2;InxF88+mpuLu5zdSTughpfr6(lv!v8%5q*GhQY_zF-X zL=$*$0=gK!n|K>>iHv#JVS2G#YC#rDs`8w*n$+A>vE%L3$U`oTL@Cv%buSg3jouzV z+7$3Y*Q^y66}RaMPRHbBMz|sUS#V|V-|6BKZaW?4oTf9{GMfp+^xP+kKS7eMxhA$# zI@36Yo?_#6KB^amRyKoht@4X-emVjp^?bYsc_!4CTenFp8covBMU6LG+Y1bu4qon~S zT8gn(WG6up@;iSW$Q}rAD%WiGWTNzL# zf4Vx|!Jc&NWMPq5k!E3OeGlb*&#P$EB0e5%F?2b_?&0KFcn%BSb^FqV>1EN;=`{Vv zcH`rmMMbX8%nCgn*HDvf;z%VP)1 zB!4UZQu{6{O*a(&{%Zg(e|n*=45cd0eOfGE5ol5C`xyPgw3)1hpng0$xpk~`5jXr zV1i!D$d%LIK`PRME!Nf2p*0xJK7ZFp@C=uraGZujd}O}vjb#a$E9@ku1<5yO#)NiY z+VH#4^r|99=xzj$kBd%+bxlvzDp+_<$`@5IBLutBH@H&zP(52Ydz0P*uCs|;7{qZy zOr#xl7q>4hYwfmXw@i>BHPSVb?^^Tch9uPqt6XA9r%~s^#r@m;@nXGJrm7Xfi342s zYW_u@PvQmDGpxwp{QYsj(aOMGjN-wPtdCBr{$;*;v4T4#LFd>jsX&Kd-37p|ww*nr z%#5@jswi@ChRer8s)llItctu?bYune>`m$#B7=4e-Ax*@v-I*I7~|q(;Eg7V$Iz=c z+BmGv85GLB^oks>JbInQ8K(PQhn|ji7YhYq+V9)%gk>pmwa-mdfYB+Iw)0Z!*sB=8 zlp~dO5}e&|SNCxDw^h!Fy-#P^&f$}yk)eWeWP*Cg_Q)kAp7(+joBpqReMEf^FsM24 z3@dYp0Uly|>jeRz9ok`);0fU>PqCK24;EM~sKr-H*w|{ci;ZKTz4Nt;;PAM?gW-ho ztYNd}t?Yz9tx4<0qy>{(lw1G+sgY0jM}9noJFKX_CN<^1!h)JIsP96cm5&GV+s3G^ z&9f67bF^kd5g|7(#cC0<9GjuR0 zPsa7xjkPU=LbS1OH2Vb@or@jCy4su-vme7pXb`fjv%{qxHNts}eq+WVqwPyos4OgA zuaNT$c8~Q?$*;`q4hriZjl{IhHZ#H#-BsV+d%a2oWKi>Lc-JuIroT7W4s^BZhGA=d zl>eBW7pmw?rA}%(zJf=u_|%mqS%0wM5I!O%%QfGY)hv89p(3V%qPtv>6{rtT5bnzBXE4;_uvk0p^*c(M z9OnH4XdAoavXt5~@~N2=@SIZE=v4J&?EvNq{NsKzLZw9}FTwR5=cLF=x zyrg0n97FT|ib=J;xPuF?&W4Q*VNQ9)Gg+BnUeu?|iK3fOn1;(N(-cwbMnx-`1Kx&iM4sT!PZ z{03OVF5d~lpP#G6sI-ktQ(C=CT8KuA=r$HBrFWTv>D5r)sg<>7nvj~+Zr z`COHK|UTRy9fQ`j45BcZkj1pZ^O;P{CE5Q9upfS+bqYMQw^H;iuGF*nW#0_pN2s0 z>7LR!JF4!7;-v_PkK^==AJ%^IT~HVMru8+f-uI^dP&~l;jk*B0H}yOiEQ`FBE)38Z zJOAfCME$F0)GtZ-`7UQ$j8iE}$93I$3rM^5MJyY%>~`)bW3VQrz=sewaEoQg$f)m& zE2(9TcP$kc@J-Es#Kue`TA+a-v6+;fB=82@$KNKw8d+8M!*%J8(ck;-bF-N$l7vq< z!4-IisLS+ZyuX89^wYBoNA3bGJtyN@w|~peHpfI+*T-mMnT$Of=s~7iu{u_V z!SXm%nFLOe)pjDGuuy+0J5wXWjXiEh>%!05ijsN1U7ku)SX;+mre5hbC+|fIDz1Xd z+Sb$D7g=lXgE39<<=7a~0R?bpx$CmcGtgdQihKL8&)KIyKAdIq)qrYTNQv z;IvNIz)s1N_4F6LRUxh#?>&y<6q0I_y42AxE8jh>gl~>b=M7w;PIpRJFxJa8`w(D)iA}EAQ?Px~il$JD98;h@R-Fy~{!pGBKBML=*~EeR5?3XDACre;Dtbvp%n}ZmXNN~TyD<$2kcz#sX?jy% z^Nk{+z-nS+titNa*YeE`=Aa@?5H)PTW$bb^nU!EIojkvef1R7solm()H(5{0fbCB# zZWpLvzM~34J`j5}%NCo{QFG52EfmO(aa=P1mHr`iPNUw!GvK$#k-HP%>u)yO={CeL zT8+tdWt(znpRv$b7Srps1HY5|#*<7qG8ZcoXE83L?8wYAX&!$2?oCYwe{xQc2BWp& zIB&WRZWA!dCYlW*XL7+AR+d_tHIE{A>pCPYw7;Zc@qB@Y{}eW??U8)FubafN=*_>~ zf=7r;`x z{HU{@T{Yx$c@!YR)*%aq$Tol<*bK)OG5-%^=ddM;vTfV6ZQHhO+qP}nww<}swr$(C zZQfmZwNrRM5XERQN6gWCX8GJGsko6>dg9;_7h`m8X+Zf*;PonJUGcj2kWUkq1=W#W zGZ7+Gxvd7&PJ}7z9m3d;1hvp)x@9El$&(jLPP=<=aDXo4W|W+4HvQ7D6&L2mR(5aV zK_RPObQLE`u!-aPLwqaX|R{*0kzu*HFctaB7`c=Pb~F`OOJy@A-HFO4xV7w zDaA?QF4(X58*v^BzV`7B{d7MFgyE+nmLrv|N;R12_WmalS7tu(Jq20u1pC}<0i461K)#HzH$-@=5W8L%FXz(s{neY~e=;DY8GNb0PTHK*!)M z$tJyqU)xPQ*+28X-t8JRCP`89(WPsPO8D)C8o`93B1JojHC$m{#<_*$dKI^b=CJM8qlm!ZY_ukOpU(4Ge#Qo_p)&P% zD?LeS^kNLfN2jb4vy1YYTeae&PFJg3FVlvCzk(-?rBj5HTWHfxh2;4gn62k~NiDKb21dFmenv$IAO3KKad=znVhVg#-#g1XULx2cuu-zieC_B?yT0E|*hz26ew9 z{h!3jnZ|iHT+eqIUiEly8Xgg4_CnAO!0wiA9M=cJ_X;0{Du_^yfAZ~_NxHJR2v`i8JEFJp6o5|820T_uW5XcbRh6JQcbtUz^2 zJsK1?P7LvZA-(m8^{OK_K`g0lg#5)sI__v&e3bMqPj^7E>^uhUkPEW(|!S7bXicbX?IU2GnP1CIwq9popss!cs*q9# zpv5=->HmWr(AlL)cA@f^L|Z^=pA+=zUn~>jOf&I*4+W}VtA5OJLk9{?}3|`g~1i7;DQU=DeaVi6~k>$c_ z2@g0jkpPq(R)@sH`d@{NKU!Nj{IZ&7m%$vX44xqlw)@psmTCtog2cJ|fU5ZmB1~Li zwea!Zj@8+~EOOnud4ubiY7Q0M8+jFa3Q}}S4VO=0`4eK1FKpiBWENBsBH2v%;c2qj z(|XF_CxmDEhmDHfVd0PM6{CGid_pKD^%eDoo=%r^7}R(H^R>=^m$9FKiw?9MW|N}d zF`%dLYuk%orMg&;{I7#u_&@R$c#)JDQeRsk7$k6UDF}X!G+K3D`7;MYQ1&x^YpxVK z(Ch%}vAV@1+>m64ki5Eefm}USVO|u#pM|f_&R_m>12^5HNM@5pOw*t!YLjRRVfbNw z1GY`9=^klA!~_~}HBP}_8P^H=%-n2TGVU%$k@f|3ZGR=zzMWyn?lyBzbVt{x^t~B= zGnK0u$Pd->$`iw`8MWGEeOnj4Jo#|^g<57oDDg{6k4gKa?%0+wcWWNfoJ^$~E2&~6 zPYCpJb-C0Ay$*Sf#1>Wlry@0IymiQK*DV2b>i3KGu5)whnHLH14|EA;T7;_js+&q| z2|61e`9O3yp)b<&uIpEyOl<*YM5(f&xokh z5?52wWV28YH^X@}VQkv_1Gs^FH|D!UV3F+Gb*j<{2Q}U_0-$m1x=DRr9EWryFekaK z`Dr@bOJDYsF}Z7pm4`ad+Dd<)2;lh5ZTb+Py%MmZi)hni(k}}M5X@m$aJy;G1fI`z zzsE@C^c#Lo_^-TfNaR!DiJ%eSX>RBxA#KRY;5<*cc7fD_i~SJK7V9AbksNdksG6Dr z*Zd;5hZN)x?c*xqc( z%cg2Q7v}x9)^q7852Mr{cJTLd6vSVpb?)YRrnXb|?|?BveglMOysx`2RKsE|gRFWW z#4a)_ZDkw7Xy(!9%dGJj3P4S?M0o2^dK5t-GuiY`*abJ~(j$aVGrT9EYKbRl!h_g?}6C#*CND}={7FDCYSe*xdZs! z4A?(ELZ_Z$GABcHWUr*s{D+|pd7kJ&uZ`7P5%5vOWrz3EcAcME{aTFRCFZ$aw%KUs zTseawSYX&>QSIMMTkr?#2SBMSG_SEx2>%+vridUJnyHt#c9Dlt<^>P#ssIa;`ls~O-M>%P%?{Zrz zWeTU2m*#`>-K&~cOv>Jn0MEqZwMljr({-;xXWIOgKGmRW^c1(T0LL4*4s;bJEtTv< z2p%7{L4_`-N}#JtqtRy(`P6Wdgq#~pdEO;I4Wn_@p-@gpK_*JL?*y_zYAk)@w%a=e zyF{fsJ5F;Oz>>1Zpb#m#8zbIlpoQI)o}E7x^;@YhaNFzNi{Dre&zgy7%cNn@h)Y<> zoF4(`a+R|wdKhuOv*so3N^txEfxAVzjBEDFH`&+UIT6g-V<`m~n6sR^yQO5C!i;cq zorNCkIEdKFoffm(-$OFC3lAp)zO}UUsO%`cSfbaR3l*FGfuh(Oz zh`;5)Ni)<@ahVlr!9Ra01rlB{rfQ1A&bEPFd@zJ3+EpMm@?xe)wpUPchamrCH7b|= zZvj2|B_4^jJXAt~+91d{Dr)5T+5V9)bn<+t+Yjt}(~4EXm^Of1J|-bRap4S6tx`sJ z^JD1nc)ut6O~UZx%Qm4Bg4)x0PXXJ?uJI)ke!u~r+2LxRfBI9LLMMi(&O~V^q)0-i(hD@UCl0 zn^GMAfZs_h-)J=u`fN=)|(tL0Wj;smZTS!Y>${%II-yZs&HK%ZIRsiqQKTPqf9vs%$*>%+0#tI1<6Dgg5V-ycJ3D$A{oovkpfD zi-B?Ww_GVh>7fGi8usSw^Z5navTjIP_30px2OHl7$-=4|smQDWSnaE5^WTkD`*aIh zn4S2M|GaoM`O4f^y+F^Bo?>yZip?znauyXN9tgT~dCQhs4aK;L7SWExYR?QL7h&@9 z_hH#;oShVov<{+*CwsR3w*cEESd-1>;oL zOO>~A#~H?<2`)}P#bW;xgXp-yMZPG$ZV2g7ncCF{dU%cGCMNN}u+BFQC|k~+Wyv{< zpHvn4T{)4Yxx$ENyb7$y*xlRI9L`YGP4aam` zh(hn^?TjFF<$>!VgLHlWbrk?RJr@A3u9RGLAjATpK_RDU2VE&_bTqKT)!8fLUNuW6 zHDwCciN_WQkBOF8VHH)2{6kO05xH_UoTBsEW___)n)k0uGL0vTLCyMh1CmOThsxqT2 z;c$5;r^4DTLYQ1-dajBh>9346IS;Gmg38&bjATf#e?fk9c!?$(I>^@Hu&usEj4r#P2F;&BYT9GmHqislQ8^R5*vjs_Tdm#j%rpIf`cM2hK6=`6$ zKr@C+U)zTiGm} zN{x!^&OMxr4?CvdFF>|oX96{riXfq~Fb?{$K7_*N@APhIfz?KND`C4V&iD1a1PW}= z8kbk2iK@eho&_HNyI^o@n(8${1+BYqhFG5+`RmWPG4_R#xeSQm3VYd&&gygPYW zJ_jZ*tcxzD-fUk>k65bWTlKd*QR!l1EuO@ts;6xaeVGi*?sycSv_Xtyyj?I{Q%+#d z4J>VU{Jf@`_ zn!fy;6X(Gl@F3Z=n;jQ+H@y8^Fr^dNptt%hRnngw0VmsinSCu*9G;nNjZMvl=xjY3 zP)^irgPda zZpnKGq81(7`zbXRo_YIXVTa~onXJ?Aqow=o`F`t=X)kFSoU@M$48C}$=6c-Y#fz2UYn%ya&=jC> z4-R^s)77mW#wyRGAywpzpqq*FL|9Iw9U((b^i^5-RkPPluYeey87TN_o4%oCbYy5W zOToe>jvg{g@iGB65*UL^NG9LfkjhVTL9A5*sboVGt4|!r%tyuVZbNbS@o}3{;6#9* z2ZL~8LqPFy%emivZ@EXD<269sj$#<(sQL1UrmQkq7-`9mv_(Yv3h&&5G+i`YHp(0WHB;k5Qtai49Ixs>K@Ft^ zlT)Q%u{i{;dr45CrtoTW1V;4Yp#kUL#EzC7iF$jPO38?iiFja+jr{l-CEdb{Q8*yP zVw!jQ)9>qYg|mcrf{n^o@aq*xDI5rm9|_3nlsC88uXwAF!|JRAqQ94brYqI}0aE;+ z>mCpoL*)@sb;o!}x&ju^YP})&5?j3)6(%mVYZLUTk!zIsQ0uipI>w;V^4WsOx?v_7 zU|f3TdU1v7<}G+d-j9>ZJrW<6*14|gLp&@dX_5|4kVS2y7;$3f{_^x*YWtF8FPchi zD8S+MmKgbQEd?b)(>ZUA{L>5Ez2U~Y@)UCG$9LgtX?7&bEh0&M71XZFxEnq6DAvvs z1MVz-b9Eh1SfZWjdCF}NYFI>=d?$M{$pEKgT-M-?9r0%I8X}(g~cy~=RV5BdB z|F`@u*--J7|4!;sJ12cQU6vJBcbGTx`ee$_Y~@vx&ODuRIS=s7#lMRIl*X8w*Y>+! zBDdi2&zWHl-M~M95)vz=MQ-ondlCx95~(d{T-EcfVO9US#@1e{pF^DG{AGC4s%tEB zW9D`GQ{6`7oqf9ek!0eeV<_iw{LCgn3=$qD!-h1dm;;(fN9Qk6{MUavZ||hbf~KM| zGvN%T63{z4e>LBq*~<>i%0L-U4RP#?f9S(N+&}hAe=S17NTQ-PwiD~2gWDbtQ-~_3 z+)r)^q*&qlk~sDg(#y^%D>bIee-Qb>huepuq|Ln`xkiCz|=lT zq_wJR{yz$8E;*?cU((no?E(;lkWm`buY8*KxfA!&2%G{Pz(;TwYkGx9n>bDKw}`~H z@h5l?UD+Fzx^y_<`(gV|#r*H9bR0w~c4@a26V+0)H^I!+CIWcU57*Ei@%(Cx)~g>d z=ip&mAU(m2u@PxJ`!D>+=!1u=O^K4~JVjxZCaBky7XkEum3iXW&JyjYzZJHlLC&42 zG8g@5?!P`#bg+m!2ZRT0G0>K*0+|#uC(l6jg(7g2oO%C}e!)$SBff@hdHaeJb(CwO zw9gIFp8!R(GEde58)CP}9{ALfF`aW>&F3xne!9kS@5eJRR9n(7n|*8rq;KuhWH`Pm zBN_wn->20+*$lx>bR0M-PA`sp6GZ_F6*I^wHR$UYvc%jtHFOspt`gOv(ROKSb3+<% zdJQ#OP9;Z}?6_*JsYiT0cp#EBDxA!<5;ba*ANKOKxBDJo`YWi$-d#!k*Dx2^6F@?O z%j`0^x7scAliut|g!$sDR#4Y@Me8f$(z@Py-Aw_6tsaV>yLpqXbla+?q}Q7R9;9=# zv}5eH7C2J4H4*Tn)$OXhohMX$WGy{v9x`Z?+($uxVKjnME>*1@@sUdbQKY>Y!Xq}< zlvR~PRL}y2%31&pWmsIrE{}x?kVVmrjI0=-cTYf+8bai?`VQQ$=giewT^>~X)9;tX0+O5%N){Nb7#&n9({?8gL&!4H zPD{SIPYR6$8BwYU&M1<*oLPS_t{vS2uKZpneE93uGxH2-cvHyQUL~2}2HF9I znj;{9g>gs#8WI2oz>NbDfHHwQH~_4Fe0=CH0gw>J;msOQTmQEfd{qp`OH91vulcJ7 znBn;i{&)xps?7;tq3@?7=!PKfodA3tdib}Y2n+($Uo8kAU5^VvP*GV*UPttw6jXHq zXgmlHRaWX$-*d1!u)eRMa3385puwlZ5|GjTLwk{b9eM^D3OES2 z003hg_mw>j6T$#6jB68+SI?*~fs-rvPjUzp%B}vh4kiO&mVmmTDHIn1%D2$-;CCzc zuM+vbPX*q^rTOW74Eu4e=5HDhCOGJtMpLiJxqFx;yl1!-h`ZbDhnxBlE)4;Id#mpn zjV|slup=nv&k|v0FSF2J637D3vHl4_BY;M~sZzjzo)FOG&z`F3`z`W&kKn;Sy8n;% z@%JzC>kjLOKK}jhjrWhcB_=vI7i#|36yUeT7=T_H>>R*jgBgIde^1mH+~s%AC*ak9 zJN_?wt#5A?@P~Tm4?2?v=6w;(5xffBGUG$D{eAuY4>X{V$-q4!6br-bKYJ_4X3z5t zepgyB==cWQHGtQ`TmC9g#>U3_FYHn?SoRjzH)_zAKEn9G;a-(T;&ncj#*69k@$m@e z-y7*vwc#6+4cRqM_n(uZHzssOX*e;&J^#@Kg)q&39@lgQA)rIJdn2>617HT{`-Z;m z(e&ka&UT+)_<=t{qrbW)CWKQMH*k#lhWdtvzJ%YO#-G@qe6WCpz6A;HjQ`GnO9F#A zH+W$3{LZzt)Gee3OROKci>%Er&9!z(@A5dd=W<@Yz-~SjRjkX#Sed1LB(XzY-SR z`@nP$ZB0#gBu`jr$6)?ZAm6+)5wnDq%nz6KHa8aeDRx{Ks&Y53$(b!DUwi&lsm=d^ zEU&|9@R?DzKH6V zScd;GAuO924NtDEEyE?{nVnJ^}Fy4lGA{0mc1ynE0T-8nX zEg#(`hY>T0GyFS2^E@CKCL=2~N1k-R@C|i(YY3rMb5V}?FZlbHr%>dwTFrg@}`O?OQJ?PmrkwucaLa2T3y-Jn>RsVHRsS1LsKP6MB2ogWX>#kuS>Rn z84~S~ysD}~&2I|9yv)0ZX3f>wh9z%^@VgkY5;bF|U#Ns$gGR7ki7#qnpy{2APiY&E zV9wTeQ1;Bw8AIe5UvLwipmN%pvv!RkDt*)*dU|u2#fhDtuKf^Zb;bR0ZCo!c9<0v9 zlelYASZJ)DPqFlBZ3!=Ui=l~9zIc( z|M4uh62H(~`?TZP@XNV!mL+K;S#y^XOlpkB281*wZWriB;aA%Aigec>wT05Nnpb(X zldd4O5o2p(U^y;=JkK+q)obV1cbTqhdJe^X2-44GEcey zk3gfCZB{g&P`&pB`rR{8JLg};|IQGfdUalWZLcVUgigWHyy&)6bQxzhrrc*0MA5Dd zk53i*Zl1Kcnu)-{;_tvFbH*)dcytymo+!vQBElX6AS}@rT zKf8c{@vy(qBsc@ultrSImwg0vzLiV?-T}8=37YE?PlYq(4hUD;5G9*>Gt`0s z{`m0%zh(_9o{CjjI2QjCg%Ng$5igWhQkY*rbD)ZtO+;I?%I0#+<&FyOs8 znHto!t5{L(=qSrq4dsG5hv{=fr4H^M%uC8I&$B_-#U5$~9M{Jbm@G9DUQ|@7HqaV`HgEM~E~x(;0EG*-^uRlPg&{9;5UZJeFoS*r@CWeL5_hP&wt#rnI-{SIKqdeoEo z`A{T@7+oYfg4a(|J`Crj!&%|*(_NVMh9)QcFsutpArK9iOkYLh1t9CU^XM5o%6^r~ zTO|Qs1SX}=8ThuQ!Bg?R6R2y8yj<4A+S~)(_S}j)(57)_dB;E0C6T8nw%+UD%9bfD z?)mU1d*TG(b>eMf72$r%%hE}c^Y<{CzN!XvxbSlW@E`V0@w)kM*^zP)iCqCqKNY5vP89>2ilRtIq?M-f>$Mt*2 z*RHHb3~o_3<%@SZ2+Gf5MZLzIwA|GVTF*pToeF&}V+N`^noPB+ouRTKX--DkW1iJM z)IJ}(L@`DC6E9|3NO4NxIM#dR-V%Skqx}N(7d}v8&aX zG{{jzbtLsHa*Xh?wa>L8;;dU!56e0KoL5bG2 zC3|>e^!f>$;?`cbO-dR7TA3a646&g@zXp8e=@4^m=_>rkAd7k>NwB+)(SiDUZlGDQ zek3!Jj%n3A(n8m49#AN5Ea=G@_p*@;-BOC`J)3g^3|=J9BStsI`qq8{DJd-A^vc%V z+KY1FOW8#;Cq;%F$Q7r}(ud>4M2YHvsny30`%CKc;h{|sNOZcOWJT6{_G zX8i$7?xT?Zu;J?3_*Vl~#8v?dj!rHoHi(A+3tw;EW$&}>OK5JrYTKh>8dDC`7nD{J zY4X$Injgypo#V>9gtI|`_JJ1V)%1JgJE<74?EG8pKmCiv8DWWniF|E+2t2 zcNt!qRK`Z9q(CelO1rs16MBr#af;yluyqUS54fo0h`mi8`-P+1Kn~K%DvEPvw%hX$q z)a0=iFj>m)XO|OMxsm%z+QQ&#vEh_&vj>}=b>bq6=IY(3O90#}+xE9YiGc9F5X8)W zQSmI?%q>!+<6fI9IfEhhm~0i#9MP)sy z{h+@r4{+?Rs6Q386QMH)x|WRha%F6#bcJr~r`)q`bb8vFjCLb|CKs=!MSj| zvp6Ll%?@87oZw@6l#@t#GVdMp4Lf?-qoq5^-y6Z~XgCcy1f|6fir>7JDR{I^NlakR z4{KmkEE1X{iz{iC(JFLks_z8QK&_2+3Gss~$2QDBX}O_VO`is2l(guh16bQvO3dpz z#X+jE;ra?pFT|g1PNMtrI2|e>TU9lU@pRD`?SJ)ESbLOz$}4#Lr4Ve%acua4kC?)W*jc4 zl==qv%_(FT<7+RWNZS~K`}q{-1|cN0zADp^RcLt;M-X3W(P7r9MwSSF(#F$+@!B5W z?ox1BcQ@Cn+p_>)yO!?a6JZPgWNbcO?OcdE%ebp%rnXkT8Ye|`Z*Mmb!(%SC?lBCq zTOM}}Z!>?Up}Gq9+mgkwf7&^P*JP7bDeH^CUe7)*-k!`+kS@LtURW-?ivxH(uOjPq z_57=n9NpBGRIg81-f0VUn8KF$vI?27Nv_;QN~! zmEG0!V@5e*GDCW#oT8gm&#Ux8?FjO-lLz%;`C%Pt$rC1JKkqnfqP(`6Ba-3yJ|>`I z3mnC8<$crnG%%jL8Yn+`?sNz2*0F4Y!F8t#GJHlYzgA5YvfIOj&W@i$L1jsw+V`M# zLs3d5MjM@iuGq(+h|nkx9v=}(h<~semnnM}t+|aMZi{M44*Qvbk`HUd#fBifan;>8 zY%}B=WVel@(?PS;2c1WK?(=f5ff^TH-CaRJ05T$(lGf{ej_KoPy*8bM7*QVQjM7?d z4IG1E#K0@e%WXS(VHkjnQ;Vl(~LAM}7?o4=yi`OeF;Eh=F3CTjk#|Xy7YF)h{ zw8wkUr|BmVK3>nj!pDx))3dO4%^?d_Rj46oU?@@w-iGI~;>I8A4AwMy|0w1&6CBMi(P#OK)Ur z;VZ4;8X|ZpKTOw@NY+8*l&el#j#-A66qBXS%AC{<-fO^|dNncF_tKK;^`c7n$y)eM z>bth4&b3|+mY zHDAMw;j^W_#|G4#oHR$}s6kaAfSzvmOMB*`{Z89fS%3GWa6^vO#7{Yco=hwN#kR$t zH2REeLtXxoY(K>x-e9vy|8Oxnsy4?~2ZjQR;5wc4;_zRG`?K!*IYZ&b(ekjuxJ7sv z z*`Av2Bnp)k+YsjdZK66mZm=-QIQEC;D#}YXTV?tNrQfGd$#A78BA1V=42_2jE$spy zY7Q;FY-<0PcSoAE`}TaJd7{FOicV;E&rzvZ&JU~{FAFB$EAzK5gr#Hjl=^MM8f5QBrXy+exq#LWP_ z&vGNe6j@Yl)`s3X)l#0Jm}DidLzLD{OOAw1>)z^i8mcjr8S1F4v- zp6>!e-6F`Dn7CQ_N96 zP4i-cpbd=I`TD0WR|9(qBZ;l&r~`5EGVbAgbcbLfN3?|PhrLwK8?QKNS8%aDp=eL5 zZffk*);b3{rWJ~-O*oj9&ST;`y3PN-6r+8|>Gpcn+As5DA^dbXe!-icH;5g9cP%Ox zX))~5?%^*|KtyY5pdim8zAG--q%=sY$l0fagg$Atc#I-UPL4f(pe7h~8K+zjl}OYj zf?@;Bdu9cNP zU;dk_38W#$LR}eM29>;+4QX5eFta4HPkiD%{WK-UEBqo82R#|ACXX1bUsU}h<&awq zyrSMwTeQGi0S_NX(<;cAiF0xaVv?#+*>JfU7}62{^Po@>CwCtI{mh_A6O{!nf3TlkL6tcq}g2HDGf8e ze~>Htne^FCi=_4Ad#tNZi{UEHef-Gjnf~1H!A_>GQTy#6IBb>(3vG0xq@Vz+B zTHEHwDN&0{3lf~Fgx4;cejQ|;lFY<%56PRO$Cy%Q;l9?gZ-;jFg>GQp>k@-SK&%DQ zaZ~XfOZc{V&E~lu%??hO&jx8<4USuTtI8wHH?LCEVlFVRFO)H25&Ih$-0L{rqVi&jXBPBh zwQ1iLvGcF4NqRluN+Dp|-TTd#a8Qvei&9yHhKZ&gJc>h@NH(hB>RByX0{N5i-K~?6 zP3!iUh`ds14jnLid~!@kT*VHu5EbPB;43l=wXDCgdRBfXnj+AaL(#aAy>M+#I;|ISM(TR@6 z#%~kOBqy5dn@N(p%*XSzRf44zXY#i9qSnOQvn`_%0h@gVL07lu@V7kIG&XJonvgq2 zH&Rj0YuSvA?=0y6HLf9u$lH2FPb&0!vsBpxFWzl3C5CjnWDXR|p;KDF84K zR2`~H1V@7ASv~ngXwTyZf<_KOamV^bH-#tqo`h#yzB`G1La)Rpi90{0z7m(t^o9Z6 zsRGEkW%3U;f-kfBY|(~);KvA+uhfGI$mtKe9%da0?OO$3g=sLt14VVC$K&>@ToJtJ z?&ECgpEvvz3<}N0WFlQJSlw~ooYJaQ{@qYA$OeVkFidZ`NU`#(eQYcPp;r)TOgFc6 z=}XwokqEffHq2RPgw(T2)0MAO0bjHGR_jG;s|n4qh%T%8DYd%m3_ z_P#6k70OWDGz59Vu{~Aot{ucb%K*H_qZ;rY!vtumZ3tsNxe*d*aC zdP!CibQrX;6f|c_UkhA?|M=!!bvB+wS*19yG~`~%%mCruZhAAj3xW|Y*#w7xMI4ruZ&nZdTqj+>FhGm4O9t3=b!dSk*tUbsO zKg`>|1#PEG#Gap*YI^;F?`#^U?M{!bW8xK-OvEFSu%^j!eodhcL>r{4Lf4iQtR-LS zOebK%u-xl_6RP~6GY~oCgQ&c>n}Sl9w@u^?ttB% zU@`a0N0_x~cr`fkzWdi5L*%OAFE$Tb9E6|;yNVNgpu_-meQD;+j2vAY&{}TXYt@{iVYGQC&F;-j(62ddBNC?G#zBAPb-Q}RyC z!LF%Dy;4q1pBX~!wbG+{u_E24x_zhKXe$r%1=U(pcT-)GR9hrc>z@GaAq})yHe|DP zKRaDMhdLP8=8fQ|_C!UTmCAuflR{xzUhvj$c>R^+V@O5x#ZKPI$ChUdGYkhjcmJ%E z=(oV4Ryd6>=m{Rzl01i<9a@B%xL!i9WY3#~NxxkC?GMhFuzE;IM^OyBV{O z+(T}ON(D(zIVCbIYTM4~b~nN8*mPfBx>!59^W#WGkm9qYX^+BXen0ZIP5E?=LU{ey4?x|HGPNoI;_CztxjlLF^xWL zlHRe%k|hs%&2lN0guHqRJxS5tpLW*dHA9xqCU?qA^Qlw;^?p~yTAM#{HMvvKp)`x! zPn3m#^*jUkGuR-Ro_VHBKX`&Dby-lEM8-wMlh){}Gjh=DWODJ{0r!8dU-v(SVs~O? z3olP9vA_==+9rd?U2on6m2uSF_^d0$+ohOL_EfqK!0yzy*HN!db6Ic{3Yc^H8@S2w z+-XXJr@J4+j&5ah;AqiVuU*zezX4dJnoMRwF3Q}&IB}Ql;u7kVcR2c>7*2{G8tr$c zlN!W743sxC+DhG?RgBq0iBj1N5wm_v??@EyINK-{aI-sN_r~kC84=0y!logWdAJXv zUe7+62^L(?a@5x|b=jRCRlZS-M?^`U;bAZ`H;9NWJ%4Nf$!>x6rw0+Qzj<6kU*`W_ zL!b#dJI3cXI(z#PAjDGn(h{TwNVU&TR4(SmPmnNE_=h5kAod~0Tzp-hW}ZEdQr7R- zC{lTLdPgla9gbOM$oki&#Z2E@$x((#Rm>#Bh<<=%lt<}~3n~@8#g-L5qFHCo_G`J@ z#2&)8&U+ZOc4->Gn|SU0&c}4+Pcm$*0-<8j)bcvTRDcKH(R}XXRv9dob0a_DFDS@A z?($R9zgdSLIXYSvk_ONru(#1s1}i_`P)4Ud>TdNORF?7^G>T)v3Qwz=*cRy&sowpJ z-&XpG3G^_Qa5K@Kg#A#flm30pR^CL$eMN zx*p(6hpGWw1U@E*kJz`4E{Ez&2~$K?eiTC)7tuHoE;tj3AgnNQUL;MW(=qMdgDtJZ z$D1B%M3$#$GW9Vq%%Ef(hb}H5863ErGv&Mgc`%U=*f?t&V0C|D9aGXRc`2aq5CVBK z2f*U@jb!>wp1cfN}{G^>x9NU7Ti( zo@jgF62b~)e~yXH1j~_dM zu@gns!f};6s>m$VK(e}%^6oI_aMzljy1^)R$VI=Q5y=&fjfpm_;orC3ZIt>i8R-Gr zReVO4UZ3oQbbfuxWN1@uvC+>htUlv_UI2d|yFAmbW*Fq=84+puZWSc&fF-7iJ(|HM zykM9aXP~r%TdQ7)NkNFftlY$zL2h1)k$RKPXo9^)TrF|A?-{ONCKj=&nZT51^$q6r zOW4$BG6z9WfGztbuAdk!s7A6rLxoo1rM%y+SzkK~Cp%DXUQ2ZV-Y1wa0w4e}?Te4o zx?NREz`N+PeMLQQp^_@%M<9E{=G-|9N$>cc4>idV7jI5)4+|NzIM!;p!(_W%))Q6c zJs@kfvyCxnTF9xobu%q17`I89laQ|JK=13;+YDpdXunW2HK0ORZEr66h*6N9+PovF zE7p=Lk1q_Y$k-#vTMzC|zMv(0%xrT7m#Bp-9M7L?vfeSj9_@h~G$mX> zrFl=U+2C(l2dpZ_SQqKy%izaC#&#Q{_azVd6I zOhMb0eztSf9eQWzmUG;+MRtJRUHjK^4`XsMN$=u$OjUhYh-i}rfvus>Q$-%4bW&9F z=mk3rp3hV*d#jVL6#mjv`G z@col-p3{`?EH5gkAIenfNzZmMsj7TitwL~=U)tMBqYLUvE7epu`aA7^kH>H(lautV zX$RVSw#!(?i$F>~ox^(-Ps^G+9X0KLsQ>_FQZ7esd|D1!L(W?PDUWx-THv-WLpebp z*BW7<*x{K0)*s?W5t8b}lYLG@0?rwaK-VKZmwY){Rayn|CfvJMLq*~y!|)u@oYpQ% z2S!UP1+{YARviYV<%?k0YM4bDY@6^sI>mCbY^hSt0HJqrPEWvs#^Aa0(4jj42~nx` z@0fVLFo_G=qb13<|5IEhbk@F1N28}(!UZ0Tyo6)wo`YBcCAgC16@b|-+j zIsJKWeha>wKF8>|q2ps&5l{DBwy$)yx>pO)Gmi0DPu6LJ_-VS!@qgOcqe*$@1JTt_ zsn_6ln$V!Y(_mDSDG$NxGdVGf!6D5LN;And(y{291)J?6;LfX>V_H>{Wku`Gc;w3g zQxNdxAVi~~v9)wu_|Tz83jK018s*rt+ot$`7g>qB3RY;XJV}{(f@pLhLB;nx<7Ir* z9nAE_4Hp&TNk&tZ{+j@UGvlc=ppovi=OEO!2F7^p_SFIeSMvt9N+8m>Zs}GCLpiN| z_UXClaFP{r5gpT7d`b$gtLQn+2A#DqU*i(xj`#@;K6vB)xEM1vlsmrZ#FO_gjcvH; zkps&G5x*d{apmPMWY%5|;S1DwLD3MWT@RQLGVlh&mS;t=sy!VXayc0`?@F6q&O@m9D8)BD;O;L!1A{3& z|H+Gs2ILQA5(lw!+ao~@RQp!w2DLH?9>zTJU>rQC9&utNlW=rfW*zgPg!RL z<2QY)H$F!fnoAcCkp2bV`Mh2%U&I-v)s;MYcTpwGxg7#Yj z#!|3G=|29Cv2*AWC0f*E*|u%lwr$(CZQD3y+dgI6wry9vb9=3RlfHw_Y5swox#NqV zH}H~~5E2;+jA%g8T;6_%7~F?5bn-gEf8%$yk#{jm8|S-JLM$_zK;*Th18TMIiCTvPg&l;{Mv=1ft>b==ln8QLc=alE977Rmf4u#1H<;ugP7c(%lxkbn+FdiT2DwcvP_$}$D+zB!W`XQ`A|s@NYTuZv=m63rSRVAB$r;%V4vr8IA{ICSACrZtc25i(czf{G_W zv@$!r+k`W?A{@-XYVGfCTr9hGK;qjcAh@_aSZ}p|)79la6cR$3K2ebiKKc%-1}nPr z1`gYR!0C89&!H|kb=~4nsX0P#QQZ{M+wkMV5*p(lUf<4ZM?_2#5qoKWdACWR7_Nq? zy~dyvMfNHcW;rQt6$;Ye3D4}wT$bd_QKQnQuMy#M55~ZQy{-wzcaFY?udgo#Rb)KO zVqw~Mn3!9MmM5oLg`BOBRC!C1!0c*0G9fGIw$VPL(Q!#x+)b{Q{c3XDe}SzgeJwW@hyCD5m^9C-pc#tZ$TG%G$C$ z_|P0vAD=KsJ7Q7&9Bs>Pm`BhylwU?r#v`hA0U}J+eP1|GdOQL%%8d%onvh7hGe#Dv za9zgAIm6(}m;=sL&E$2Eg<1!mtUO(TkH0fP=+DP(?X~CBu>ZSFDnKt%ME%eoiHUX| z*FPTxL*$ue!bQ>NBq?Hluf488*VFIq8kKs1^hHr{Nl_(YBY<8LVvJ7+BRn(K$Le?S zkWKl4!6|PiS=Wer=hi!E9b+^swoUVzrEj}wdR;tC(MCD2fm+0$HLWGh>w{eo&Av_) zq)|N^sBrrj!dS;giu(HtFa$IY_TTtsmjBK-|1Z$|k8fsSVCVe5xHB`s|K=0_z2IbK z{r}~goB#36x=o}oAZ>ee|A^-QJgjr=UE~4|?*DnquAg|?dU4w;G*Jq9$+fb)a;mQ$zB5b zFu-|0Lovn%hL%SVDeMlc`l06<8Neg7GXOO-0cm)6c3bLhJ(Ni&LM!-em?;ioI$cSzZSEg5B2E~ z(E}j=4v!B^o!DoDmSu)6@+0v69S1rxI6QcG#Wpwust3vh(EZ&BtRnskW?^<~_9GAI zf1MWhOEm_0^tL*uhF}P1u$i+^Doud{d4kf+YHk9u8wI($0ktqTOEK0 z&{)p|n7OIl-u_kcKKVU+{bimX@LS`JOiu1y=P%0rGkNL1Y;bsCWN1GQF+1?VUY2>e zyQRh^;8E&-A_``44q;&U)3&`eea_F|4n5aL7xD2gl=!Y464^mKw*zfpX9zi4e0KK1 zP8#s>D`z_L%a{0zP4Z)p_|_--FO=x`TP60pN&MsQJNuiewJ^P-H$SxhpHSlLzfd9; z^1o1GE#MgNk0#p-8NpwE=+Tj@Uu3HT1LNE0f1Sa)9WAuq+7ExHAN99gN|69He^eub zeS@R7w)GLwg^|Spo%NCBDJ%m^qu0fJjf7efSa2YEkql1M7m)~&PPkQs?KIQ$&n`0BexBSdz6rAbb)qQ*_ zMMZJ>0C-?%a`=G2)adtH0Rm4lr92xSF5q zj>Ys^{Ie)_x*|8dE|2xJWB_0i1QA@(22Zj}G{(`a(0sjM9XkZv?o%@hKCtChi;1;$ zx$OxbYC$E{ksz~bkI-YzYA5s1BHOxMs_~7(S}o^?WI|Z^i)^cC$pPOnAU!mx>z0W< zoO<;kud;-mH1m4rWbn{*9p$gZJY52+H42kU?#~J%e2|rk0kL4QxNxy^UOR zW0&)s0Xx;vU?m?iHG<=>xwCGZ_@2isR=aw=%u3?rNHGogfya;R?C^e%a_LWE7rSz9 zU=v)N5VN@&Szk^7eRj}zhXQie3RT(ixTHWO@jq;U137;og;)^PcIYl-jLA3vpy^S= zk$J)Oz|FTDIBiG0cNf%a2m0d5(PQ>kHo+W@R`C1Be3&~Z$Mo2c1kyvybF!Ky7N=KO z}UYgxMCrRt97$V*nCo%H1tqC?82>BnJ{K_5PY*O&csC0XNPq&`9|Tymf!$J zcSo2B56%-nVVZqzwENJ(P;3&gFc4kw=$DO2J$34Wom~_a%xZu7W#_yhl*N(= zLOKdshBL|nYf~>dhD0oOTT0P!|7Od^??a|O4E_g0_q9~+gznN-w9Fo(=vPGw0S_?^ zgE}h`=3~cK>D!@sPmlhN>XStLOdq5)W^{By5c}dUuWS^53FFz#@XpSMBVl_mnQ0fz zxq&qis+*+ha}f$NxNu)ib4io&b5?^(bOq~uQ^_X}u^(fxf19`j$3HdhlMe$3PSj@1 z8`Nq&{{0sBXrtriJf({>b;^e_*R;b+G7uvd0kBzQN>K;bU zS%sP2SIiqUn{xb$&m%aV%H`Ij5qhcUUj|tyF9h?mQn|l~KY0iW(zLVEx;!O~SwDg& zj}#~0ix#w+c!F#hwj6qYnut6&^y~n!<4h_HnNTcnZaL)%TC7@%5zqZ9HzN^}9vZmE zEJT)e zO(ztY_oE;EunBR<;o*X|M#d5H#B^F(La_Bd7}QLCrb8>F^~C zL++rzmt9xeI zoLqba0?-}dGJB)m=NcrmxLrn3+TD6lj6+=G(=s_@$LWk#c`8h}Uu?OWJZ_1#*4mv0 z%g7)kb)VzT*M9{<%@4g304G=_Yhp&9GHMH!ap2ijMp*8-2J_u9gSYY$ z{!dP8Jk9-_`Hoo|)`&g*e$E+WJUzaCG;) z2anv~Iku+kB8j!3T_bu+zTq}T2QGhiNURy$sAZA`5ejA{O)^zdzOh0=>Nxj5W$?={ zQNfzp%5Gv-(&E%)-!uw^%UppcyIFQtH>%^Xm{DX4e-aiDp0hB@u@_X#y>Mxz=$s1V z3P%L76RBdEXFHh~JWunqv2 zZ*Brh^=*~*6>ojW8jf@>7HU{_ZMYIH7s?2U^zaoUR?+7A|=r=(VQ-&z!__KnNBoDn1iblS|!h;g=ve3Vp3CG-+tH1*-Aq zb1Z1=@RTbDON-#|kCBAKAr>rhVV2>vsH=U~txE#(;SjZ3GSd}BxFH$YKgD8C+GF@z z1565?sUHZAr{FpzpjFHrIFlLcITiJZ?H>7e>iR!Z0j+F7N~7)SUc^+%2_UMg_Qd8N zlD28U971^?gWb*;H){E3SLdEw${Pn(j`LWXtm`p~VZGwhqg$H}=C9Z=J+!oazG+@1 zYP{US)+K>FP^A#(t=)0^Ds3*6ZLc{72Ot(}E7c=>N*YF76Ynbqa#5Y4(pEY#f{DAG zG$WxjHRYwq4J$_O#R1e`v}{01XvRhuCUr^0?8<{31KxOm4RJYmtku_TYt2gLXNu{i z{(}8YhCpDXl;C~=UlYUMtBo<|;MrQc{=7~}1s|;?!-lPQf+Kq;+ zqoX5)Wa`x;qB*H&oMVPaY}0CI&DsjtBUhe(|?3SJ3K-$lq{2!*tvt%pV`|-y@;)I#H=6X#*E@BLS-~ z`aF2u*xtYsS5b(i#6l#~RP~BOeo#!49^t^GoNMMEog&t9A<&}e$+zj*_=L^o^TA};<@#YF1ASp4AB zJL3fFPQz8FI(8)1Px`(qOh=Rohsq65h1m&V#!}#_UivH$6!omjiETN9TTNp4noPvNe3BOzuEYvE`^T6an@v_`N53Jt(vpg%Ml7MFBjC%m6BYhD?b^?)54s`hrgZ>Oacu`I6bQNxm3Hz0`mvAP$LXo-1`x$aK*4vmjaRv$9f zmigU06urq6>ErG+HP0Q=r9m7<*_=|7Z#xsW4=DItTV+i}>&O^%yQqoXpQiHo%S7BX zrut9l2yZ1t6YZ9bO#B1=Dm<|Eq($lxRde*ta^VOacne9)`5vE$Eq)eM^KCX{E2+OX zo+NFMjRvL6!PpNN6BJ^j#Hwps=T%F)Y{kh$Uouh`8s0-oQ?@uAM9gP9Y8T7>p?OT7 zb7->4sv0G2wGb}m3t{X}9=d^4Rzq|yW7E;!DB3a(Ct_`FY|2~38cRoiy}7zzH(80A&?6PBkH-%3Y<+I-(jRfR-9AHNy!pS=moQqOH3j+4R5 z^Rpv8E&zV2r4x+QMOf~%MCf(UtxUEB8K+#@kuxGV2{E2Ns!g$UBAEz>xF2mXKzPYx zT5prrqK`tWA)n1nga00cGW)p;`j4>_4`D^E12BNMo_Z1_C6mf#Z*j8sUgcS^9!ot~ z6BAIpQT{}}yU^x8miTC>0EqrNWkP-LpW{gCVNxG#zKh4yeYd7-0#d7s^jc34DS&gC z%4zSinX#h&+ZfpP9zEFk2>A<>xR^HcyHeH#R^ySk(4bIB=*#myxCRT)P)NN7q`T_u>|)S;#Fx8szJvK-u>y* zX>Ou16^Y}#zxe~)-vglcNNXpy^JP(`xmu(zp;jOBW0=bKdq18;u5#KF2#K$ne6ta~qOI%p>0##7vSm=@z_8zM%Ti zWruoe3?CCO!-CVdeUFABLw%vTXd%w5y+XHbrAv-{Tf>KzJB<;Y$3~C-Y_l@LoJ)42 zICtXND5|_}6TQ4u$?9eSNl0gePe8lc0qe!@nH|Max|+PIMPU}MD!zT-1&y@j2Y!pM zWWZQY<^N(VCBxc1l2kBaLy-YwsnL^YMk z8V-7Iw>LE@`bYqY)&NnS7k6Zu&!(BcZ!`MuOx1x?R_`5FFejE=!wI_>Z_Ha2L$~zs zt6?G0GCM2j(A;z1HqgQ|cMUc@SI{>W9yy*tXk-UJuvdPoxeOG@n}2aLs-FdtqqUWR za%MIA;rOrM4O;i&6_?l6imP9cjGTEdY4_U1&<%YL41)yp2Y%SVRAY7yNEA>JvM~Tb zPCZ%73p*O+RoTyqN0EPy_SvrZPvwG(woLrR7>-=AEJv3A&EGlN0C7gf)y4%jeetozmWtN0UHZ3-IVa~df#Xh6VY zk56Co7?K&9OMm>>tmLytRPnPH9)oV@dNbm61TMa|lX!Z-4X56Fd$pX+wG)KYvEF8# z<(Rq{%)vIrE9MZy^B&~mp4Rf-qj-h?>bjj^2k<*lDj%5Dv4{4o<>swR2lS(NY>4n& zxPa25?)9Aio5})$^UJNx(ueWbQKtH92qW|qRH`u^3oG4BTjZyyINI8USDkq=%OT() zNwP*^%SdfnMaC`Q>QZ|k5iG=Cz(iWsq^f7ZT*RyFNgnEY%mifKtcw9}49QO52zLHdah3Q$&ahS^xa*n9ToPJ>NZI||gF*fiv8N&=_u ztZJUV9g9tA!D50duKut?k2Xy29I$x&$-Pt5*!X1oF)2JXwSfy}F_u8E3v#uSAnFmB zmKs<>vghMY{1)WO0m;X-2MqPjA?)tOC$yuc5^Yc1bX7e(PN9vp8}w-U5pfrr(XC`ErBp|9yTT?8ir4JH+&`QGnqqd1T$PH*yN9(a zs@}f*?D;3sWM3*gKYH_cnpC+et8YWPNqby(igDIiW+f*&=!N^|+v&!vB$=x@4!Pwf z9TfW3F;k{X8+OBa)u4MQ^9r+(cFT0wX~B#TNF$!NmpAXJ{Y*$7JgetP01F5Prxa7A z-3KI)q=Nc!d*yTvmne+5*dLMwBF)%LTLz5QF^f2B48%60 z2tjeLl#O!5^W#m&P8@8{jXRGJ`PDD6?~~#xi6iPPb=Kp>`SFzQ`u?46r&!9#u~}^f|aX~oM&m38T`-H-F&yl zH;7MkFjGl0fDP|JMjveL0XHN+qohn$CCLx$`eRK-Ax4=y{Ap#Qa0(7mjoe{(WF-U$KLSMJ8n(x#-VSOU z+e0qRf(97d-hhY1L_m(Yh6i|04hWV z6@zE{izpw+C^{S)p8kAWXN0+&T%&X@A-_Ho!W_cKSz8Sp;Pftzd`x}!Ne6&);k8rGPXi@r7XIfd_Paw z{Bw43)XH(VZm_q#+EK*5^*PN@_~{&=7*C#b9ZeOmPq3B4N7Pi%U4&EAdqqj1#2cty z5V6)`F@~d1DoV=HnRK-{3|Hvz;Qi~ra;#C|mB3yJ-wo=yzRp^GfGm{js(mXh%#0fo zRfIY_-m$EiyOufdT|GJn*l_dI0|~L85wvbO{+h?qo4+Rc{F?dPACX$`lFwYUk$Nta z3^tgfR9V@)Q~<_`nru*%Uc{GrgP)YoPa*!~ehv*1K|}LJm(bjm5sdLojxKpNb|!tW zYT>*bdZ<4a0eqBFF^uJ|tsXnGaT2;E6$eTQ$31_2FVah?UoX|*+Mf^3<*&zxSS!B3 zR#zs7h4Pxsh}ao8szE|>zd~*ZudZ#|Fp5}r{VWlgDW<6&@Il<8rcew~qU1TMEa??| zt&L95M_SSE!?=_Tk9JrkiWsr&=hAkQ1y5sA6~r_Xfeb`J$HrXWg|xs zVl7T#ma3kmYI3WkGL852Q_alf5JTG_EKRG4qFV<B+L9>vshpgqj)D;?KP4v9d{+rWWqD9Q4+mOd-B5 zc~XTWY;SDUAaP&@W$6M}h6#9BQ4k zh3#*eAF_CxDFJnFHq%`=9+ z@vv$tfAowLrr>0DLNufm-iZw?mIZqHxS~2F#69!D+{u7D&ljxU#7j2bQTJ)c>TmR8 z0-C9SJV^)K-CX*MzV2J^nS2bo49XA;JQ`Y}y03swEKe%|U{|$RtP4vTe3exsY+ku9|osAna4#}{xaU!y|;I9X`iTH z9}mM+*%4p(G0Lxn>NuPx6@=Rty3#;43?9ZD?*mDH2_^4P=+YtbUA%3H z1^W;N9<3bAURNYeYQkP9O3tn`0tbII36dHQ5M?OpnGt*JuC*B(Hy6L7QsKw4ZmuZ7 zz+v6Ux0a*7Mwb*2D<)$^)M72MR#yk(0k9B^>c|b7vYT0Z9?c`o*oz&R_j`qEr|%zD zKTT-5z@LSSI_J7I963-mL0{ywzV$GXJ^%Hkus-DZez*Q|%3zH;s zKN(W2fM2C3o|I3-`(7kZeDVhaEpsP{6>}D7jEYZF!|p3kvBlAQaH;mclzZ3?aDb&DJQzwh8Mt4VbDqlpojY+= zj9{d~tg3&&E;N2A5h>^p=;yH>Ut86^ln2Uhh_6^B1wio+ATjL-v*_q*cwSP+AwKG`LpSpiuS(r84J_+EVxPeoEosiBSW^S0|z z=pSFLGBw3>%6WQlOtuw(3?^S?YCS{53wjA%=KTr5f(6z45o(-gKTVhjW?Hig0$pbr zt_G#+M9Sj4GOPY~58jEaLsxrw9c#`YI;mk-mc zex0BKftU1}_dJ#_d!;V>mJ;PTWd2ysLr^pblKdGm=Fzn{;s6}zdW#^35alB+OvMB0 zVqw~ynxUm8CPGk%+dZEBGZYrC~-PiC8AMzb}1JtY&5#AUF^9@N~Z!ww6ojA6oUU@+~Xn_IlOh z{HV^>JgYp>LRGmvr+;D2nys_1D@7Z37~T!3V2gPd1Z~7ECd^F6ZYEL?r6?k?88yw# zUAj!|@%|tlB0qVQbPihdZkAgS0wER4xDrA!-LM$gEv#Q;ail@#3-&W4W`p3hLL^ed zg>yXY)UgsT3$3I(cY7ruL!wlJO9k3ELUYT4;pQcR8T$IypZ4_AG^B-Z2Yp!Ytt?L- z5fRx$E0$&2K%xphPDj_p4ymSZG@%yqmaN>@Y7fyqBs%Lp_Uv9HH51PrA0bo)b@=uR zLl20_3&te=jK~svl4=@;3Mv>Kq1U8~E7?Yc^1dE3$hjExmKG82o5u0%=fx{;Hu+X_@^p@^7vBC;!MIq0)$)s%J@sA*% za>nE0i8rQ)9_f*W=$Pg5QY1y%ui6|B?`DAVj*+U@6EwC}C_61P$@38(6vvof$7Nhd zvixN22kQD2s)(uQ?$&Uj9v>s4V^`8MbgwLW@}5%DWwIenTZ(iE^7`jfmWAw_-jj%_ zM<~^LjZR+WR&HO^n%P*+KObZ;j{-bg!t(`Ksu^2w3hr*|=4=x&<2%f%nB6j`iD2E^ zfMu~`aJ?Q!Kc)Q~Np2q9IAZ8P6*XD{eK{npI%x_;1Ik^N^F?27Ft?h6fodnlR!6K#yD53?JuiZJ+pQft|9T%d$|W8! zClh@}lDt=x^bi)$h^phe2rih3@x6T<5`>;j6;(sxa~ZZeiTFn$NU0pNRToe|-Jdy^ zcfP1BE|el628jCIN>ld9wh^rNYf8T2Y30gu`U(F*fdMC%NErlyCFPq1w^ z$NW77Au8;L3j9DE{j-Qz&m(^XMsx>yDs-zE-^~ri>c8j-tCG~}?m)8?7YH>`@EwS$ ztLCxmxrsdpxjU9nxk@Xx>htMNano7jhG!uFHob{Hj{Ub|+3?LwVtpw^z|4mT?>dPJ z-q(90C*I_^z-|0w;|wnth>RZ&<+au8BQ;8mxmjccBkGKi$1s8>T17D;naAS_U$~5a zxmSF^jR7)@0X{DR7O(PvNq5<}@QS04IIn_4a+-x~M;DXof1L@vf!1g184G3E8$Kzz zRiztn(*P9$fvE9M4li0Yv?|#rUj}tY^(wR&6Pbs^<8e0|2~=htp_V@xu8o%beTJlG zR?l+MNff+A^s?{KN6r~GkMXc<`OUU9v!WrIekh*_Mqeqeg5|%gTs#gT9wGFnRN@zL zRzmoDeTxSXb1xBaD&pi1{n}ep3&QL`oa*S_VkasPcjs(&N~pSfCmu1g^|R~rb2DqBS-4e;ba zNn!YnToo+wB-G>26Ch3@6tnbKLa$pNSU9aIe&+FJlkKxPG$QJb7Q0v1#p&nqCgi&z zB%STR!XhOPffoln7=AEBj{{rV_&@4tAd1g_0{h?U--GH3khA{@a?6Z7^9vWzHSleoL|Dz-enZ*Y8cYqqbfPh$6TO1%g}ZnwNuwg-i9v*%6q|wZ)~!f9zeAqwqML9KN6>%6@ zUbdqS>!igk1%2YnH`&gmJcvU@1bWpWYX9L6VS!%VFFGPR#L^fg9!kR zKM|Cfr!QY&KFDjz!}!jGafNSTDMUX@1N6d)kR-SIc|@kB%Q2xu;Hd!m*7*FE(^qJg z;0U(l>dwM_$ORm=TstTCxX+o2GViz_zyG7ND^(0oUGj*+Ip9@ST97X?yR6H1MlBN!6nV<%i+yE z(r<&&vnE3~bqfxTb@^0Ju;e3=({Dh) z{T@3un2=~dMlO`udWN705^y7@Vho|sV2LKprFHysCjiHZJlDHUsHuuNcIEkDJQmy9 z2O;g{iVmpaOQttMZEjyk6QFXAfp{S8duWum<-c-|y=jIK54^W7vs3HO4H}D5ks5PQ zTFJ;aEhm!|!D7-OC4+nuIJ*G(e0j6JnS5Vqctb;zd|*x6M>Xs*K;+FEDg84xgZ-m* zmwHH}s|`V>Gedn9TSrpR*Z#zH%HSup1|54S%EThMx~IJ`G?eLa6*2 zp_h_NUR(u~b_B|rUIjo*q4IZ*JN#L1l5wNK*sK@rT?BXh!Rtl#m1IhdvN2?fRr1`g0&v)wyVRnRr4?=W5VEc7Pp&1VLQc=gt!Z?O$oMDCv`-|x6@xgKoL@c zvva0#_cnDodc{a?#+?)8ec9MA3<*d3d4iPojLCoa$JDizc1IVA2Xk74MrE{0Bfx($ z$L+!~P;*xUMbr@w|GXu)H=wU&5r^Ui#TP&Yu&u(nI@T-kgUZnNrG(sMuNl;b(KKh} zN+mKY4jdugJ4ht+DL+Y`-q5-+@BAo!PnUW@d4uBXjssU5^~yKNNdSK$owXoo#%XbY zxgLIuX48LtjOqk6KCF9jru=BW!QUYJU0vE!3OQpPFlYa9Y9lFX989^s`ZLtgUea)ug_yeq8#raZq6!#kkp?Xe+AFZ z`%0R0aSh5HR|@A2r*JD6PihIAPp>lFW{u+7@d~u_@%dg9TXAqLR1_0SYgCUD5YyH+ z1e!w-B8GSshwtz8l`0IHLI8uv?s61$B4O(b020 zr0!Bx9)b@q)*vKWGH|U6h7~#+hGw4y?Z*w>_YIi~C|i2ikzm3yyLnq;OBLtNq6LD3 z)t=0ouCoO&O@qtG%ldGY91PlfIR_|nh)i_Qk1s4|&xLgmjTu9N;1(}v+>w#(mEWfj zk53~nRhgeKbO%?R$Rf$H%d=c^^6zJBE)4BpC%Li+D1}U9L(USU&i8x)Na;h-qZ8+W zUlfM}CKOf~2xALBCF_>qJL~Qpn9rosz{2TL{6e>{&n}6c^+_-A1fYf0#a4(2zbMRH(aB-l<@3MO(=xZk z7?uz2nd(4^%87XEgb(c$(|G6~sz#)@ray}Z;4Nh67jAjagW~McM}|cnf7h|eOI%#w z*jQ3XTC+F`>A!rGA~OCU&7`m-EHJF2+IgQ@a`U?4y{{3x`fW`>#lz*UvUygo1k zgqPXLk}GX(h+k`6k!!_y&ygmuxN!kuf!=o*hX5G|(xF=>NgvN0rX@&J5R5H-ybL0L zj_~ZUe~~k8TF>7mAIosD@ZbrT=&~LGj^5mcoMhI56Vop&=FiJS%-10HO=OTU&L86H za%lYhYs3Ar5P`;IQS-E%LeiXA1d}1M21*)Y-r$7lyf;dwx)+rH9P?Un^Ev^H52n=3=7Sw1!^GL>_Fe0MfO%ic*O-eG$==?mnqln$qD z1%Q`$qTs4Gcx6ec3nKo-HInUUum$qG2DnwHB>Tlv8=?lfJo;-x)9QN(Nz?wre1mSL z%>7m0G&`?*e{6%zETeVXY9vdLJ3whTwyUXV|=ky{v2H4N(bySz!R5Wo^Pi zdEgBT>ywy{tYashpQyqIE*LvBxGn#cs)emW5p2}pAn}Jes*4BM76z&holT2z5MFF| z?$B^n3un4Ng=in$*q6yx-?MOe{}%lrq$&MLcAM`0sXH?JMaLIyH1ML z`nwoP)aC}iG{F0rO>#u_U`}Vg7>fO0b9>dG@Z~{2qA2cVx0l(>7PiAg{UN<<9fi1? zgGJMzPb@uknlKybCJ47scQmQ5|DYxQP2-hcY%a{%&3;-^!fz7g`yrXK!H>NFluEia zlDQ%2(XtBvq>9-(<6_pzEwzA-kT8ZVU!h)$_Z60!&&`M}{s4`<4g?cTiCPxCOvztY zaQWKnh^5SnJe$jYR6txWE%taMTDDK#@B+b zX?T#+S&Kvmd&cyoUipr+PZ@J0b)cxMmFz*g zx(IQ?TjI;*?j@1zMj}Fv*DA7v_%(@2EO==JU1 zRT1q{R1OP(AG5d61C4kus8cxC=yBL^dD3XVY(E~N8oAKOvb>*;3lGZw%lN8^4`O`L z>>?PxWx}6N`Yn!UC35HZWr^TeaDv|WIX*|5B48IKt{U5b>2sQyE}I{ZumM_mYhvkg z3q7RkN<&R;R|vcj(b0ghGoQQBm7+y;{aO4uSeqFSds@9%E}{0i@QKb}0PpVzp+B;r zm_XoYW)^BNjMZ#TuVc|PHH*oAj25nXdb@9CTbohhGvvc}X?U)8zB8V3&0hPdI{L`6=u6!v=^39zu| zc9T(B#A!Ra?4!@abjQnxYns9n8a8~6mZ=Zmr??6h`V*M+d1hHvM!11Y{;V>P!t4ib zOJb8R0N~m6o~BDT)NWHm6P&3D7U(2R1U}ZLooZ&>ma|J}t%jZp6r!w)x+NFeEe0e( zXE!oiU2-(_`+|U^&&niq9gTfR{7w2-T>81rN8L_V1m!+t8^ZbVnw>?!O};juYxV}zNOHRE9#VI91>YddSY4aHgEM3N)5}Eq^a(8wYQQ; zRuzsf_^L%(B2($9ejq4jB4y7w3ji zvI=ry5JRC8Xtto39BMK#aq!5;CHERC17aCja#vVG`C`X}BSW$M7tjW}jHoy3k*do$zi`CzJWL2uI7Ny|fX{M(=-UvH?UR!eY&5Iq+fY_USfar+ojCbJe-%bb;k%KeU4P z7^F=3MJd*IRQ_@zjKKZNAxr0BDX&YvQ9&tvvnN(KyqX)jOn%q~>_3sdU0o%_cHZaD zwqW2wzf*;k`yVrw%fp+qrKeAY)$7&xor;82u_YDVYq{@Qr@>lZ=YFBf60MYDCI{PZ z+u0$dMt&V9QGij90&bK86k&qs;*OVIH)>Q+si7C2(IG zQr$v1QaOZrk}&gJ=H{{xRjh~q)81D`#Svxe;x54*n&94O;{*s0oM4T6<1UT6MX(sI z3GVJe1HmP@OK^9W+hk_$o4GUZ&HeG-pSSL+u3g{Rb!^qCug|Gnr}h!bCf@+z$$|!G zWTOICRLax+b$$IAA4o!FKlM%;QbzzcS{pAm(KH7C6*i$ zZV8I=c&;!R&Rnhj6&FDN@3>%HGe!7sxL~wE-#E3?mDYHw)*%1jwuA}-$$-;hOQ~qm ziVXc{#KiJ9vx;gRHS4Z(r>h6O;xs@{~BUTUiaG$-<;J%!!!>@O<9Z=e3*ltj`g`INKT$qo#*O zbU@ee&MTBmuUi-L1(z}EMw1G)F_Kx)=uT9&Cd^z_>HUaYe~mh@R+!_k|KmaCi*1tz z%^DFk-sE$aKzG|4|NPyHgKwU!Yc+WMTHq#)*0T9>rzL~(5uXBLNCTFEe&8H$#ph;f z&Ia`L9U*E<%Xp+>yacQPOoXVM>FhJKP7B!=Z!T!3Y+yIBtO14z`YWt1H^*!OzM7s| z6Z9PVXl4~FtVBvU9`#-z9z2KVJ=ZR{ zE+jw`Y=%Q;=6iyQ7D0{s8Qe9*D-WIQBl^#;@o!FrZw#cH<0UPf<$kK81~@Pn(W)>E zJu9P+uuiM0Vho!|KBiR1K21UUMzMiQ*WK#Oq%+)7{9T;j@xA0X`8Dhge_j%mdTX8- z{?jrfE0s|hreHJDqHn2o_jc>kt!`Tw_f3d_Um3dnv{$jni&xTV@5-~*+Hm`MlL*O+ zB?w0>&4suV$KE9f{q!UEK*ARItv6{74v`LB4>dJAK)<)(o+^dNZg2>tOIqzT#AV!E zcBArs(d!l?xr6cGCOaK-Q-I?K$T??#XfyS<1dB5y{HohZQ}isONW%Zh*`>jtEObW{ z%U$CL`$rvI%VVy`lw#qbkLGcPQ(gc4+X)S_JLG%<*Sdej1;Kyj0tg8Fztu1N0~eH= z3}OAk&w*ypa5q?j`l(+qnx}7^*y*Ke8vDbADO4~R#s!>Gs>3HP1o$><#7cu57V=9^ zl`Cvgjw3#T9L}MI3qre(@@$v0)d?^z>{?y={)&yvs^|<0Ab&eNcqNOzw8(-mj;xk? z*N^=(*Y5Ch!-O6|x#MoL$cr29L?0i1G0a(zgP0fg4)Qw$g2KiE+16Dn4*;%Ov%f^l zLAlMPVYyEJHo}Th|z{eo|)sMm6 zl0g-ODW9oL69>@HM#a~JmAT=2-YCMe!@te)8j5xg$t9j4X3zSZjn}mu1^)^0g)A!> z<8y#?Ec+%kj1pVm0c0HlwIC=58LW3e-XJ!$d&Tv^u#_}25zZpvd6XHcJM{Ual~tic zQ?MUgE6#hu^e`R;sX!yS1pXg(WELo%?(81RQ`)OUtD37=#|ma|CWS=oq;yKihG{2& zt#5&irVl`~I|9#;^S!azUEX6b7P<0s5wy!e1HqNAy@Hbit@x=zG9+n8?@WthTuaaA z`YM*5$gmhJF^X?4&gO!GJ?T9BEMQvAbvbf9NeKgck_N-Nsv?ziz^1D|)m%JUI0Pld zg=4pZtv###q#ek885U5PXg9?}cN$MQoXLA`(4%_aa@?+z6YnyN9H>4VE?%(N(V&cZ zjBUW;)+MxgrHWyoOWSfxMudC6xuZ%WZeYMgb1CUTj?&0_g|n&;2OHHk#@hXb42N~6 z4DTkSVPv2Hy8rlBWDxrQg$z~yLx%q$!+(HHr$qhh| zoA1BfGk9pVJEpvNdSaN9&R$#gBEe$+0I`9mTOXlU_*w`?on%qRBCf^Vp7LB85d4z7 zVX}Md#e2FzHc7HXoo-o5VSLBlFu5~I(>*qRqkHaO70b!FQz5p0=iGeSa=LJRup%p_ zWPZCAyHnX%;uQJdMf9Ui`WCu#r+XgwdfWJRr3}e!e7)*XNF;gYFo1jTtk`&2YMAeA z`2Lt*IzUN!e_sozYWw(3P0P;D(a@X5PIo$oV{U{Fc+}J$en9s!pl>! zb92EAK3h1D0x}2qNKoD%K&N9yT?;m1S2k7zzkeDlvJQ~&2-t}PdtCP#*5A6%9xjQd zGEld#H0ZKSB;Vk@@Xo7l^YU2j#(iOQ3e0X-u|9pF1K@pEvj6 zOfi{IqQ!x<)2jVJV}N5i5W~Oyfp-h@BBMhU1_~jMWKgc@Koy^hj1TGl8%GA^!<0!R zdmOZ4zPxA7r=Jd&m*i`w`{ip{$}JShdx`JUEZ$pn%GV~Y)9YJo(d++uRXaT;UwgDi zufGRV?d`(Uu;UKbOh@Y{`<1HC_S|)!?X$RGeq#EDUaY>IxfP7k$Z9IpTMg37Tw4=Guez8heXqC`;wJj%)OpAR4*nF~_lpbz;gI zg73GB^G=DF>?E#YTSM>b<%s;Z0@vVcw=>ZCu^l0YXnu3F2twZVlk$<^Agu{l9;p-`Cf5o9mhIpDJtn_T}@; ztv3G`)-rRjXpBVfr=%#wFJD=7%p#ui8&Hb0J~ZW3ln0{#dXq#MYOrs4}Otk znx!&(nWnObsk>{1SI3t&s?icYPwZe$CUEy41%-e43QQ-#F*hQV(o+Q$KI^_F_|0De z8zZMk*~U_Udolq87&)-Dxt@i)MvNnASr@#*-TxN-gE4D_mNol}!Uvxl(%m0#-zd~@ zgkguThe_$kSqsLFl$`L%G#1k$(pzjvg!43)$2jtF)KP71eh3|dCd{JV*b$iKcIHj)Qhe+$Ryg{**des77z~)>mqiqn<&? z3gLtDvp4MWuEC!~UU9~?_Iz&RUttS*)&gkj5UJF~b5*zMEzhJ{Sq| z&P}Gx&;oAn<0DdCayQcP55#*rI*$;nDujx!IieL(!7Ab0&y}AcBdcNJ@oC4E(KB7@ zOZvVd`)Q3^AV2#qD1UXd$$c{j?jb(7rxw3LAu3G=L9sMXr^Z6`TD%)^KdUYB%bUm- z@aAuovuyYmMyd7Ct+T}3qmX5Mtrb7m<2jOZo2~eCVoOwD1V@wBtl63JnO2=ClRmTR zB}4PAR3D{gtS5c*Lu_!2YF`p#*>1LzT*`)jbyDwF9>eqL!cT`SBBqC}i}A?5l}1h% zOnY}nE;OyJx}||)rmCR1e%ISzjjtz|7w^7X4vW8meS@3!<-Py0q?g!lj0QFA6zeSoR99&07I0 zt9b>4F00R^1c0?e^ydSDUCEjO#HW+*$?^!ls`GtYPKV11kb4#_lAXrVw>e4GH$ifHTEh~ zfGw5zGwQEvud=VMcXkDw$AWpz%t5RlSLhz2Pc=!H%U8e0Pf%ZZ-5lWGyQmKR#)%d! z9a$=F*d5ynj@bx31{CR$NLXZiQyBOADJG6b(?zjiN^_J`Immw?b2@m*9O*)C=k>OE z^vjOT`=a(YV##*46bHvP-G<+5&1nS7&OyRKcwoQP^w$Y*!K^-SnaJ1Dv(>wqS7VG3 z3giu^lObORx_Tp>T$IdHv#P4D;hf|6D+J;2D=9)KezujzAKi%Kj|+Z<>g}lM{F*m! zMxWfWrqFw@5y>|-Zpv|Svxq&tV4@@>PwC~NRQBlqKt}^Kkh9fjTRv?LqCF`z8@akJ zMPSUQvBxC6^dtuE9hD&OwTh}1N};s497bZ0($9uWl$hkJpCLo@#O>dIBa6as#CiF) zvoE)LaW^sayk;tzo1+kO|B$5IZM#sO*Y3t-4jNf~6ZCCik;DP_R3pt2 zMT4+~y4Yx(rVTlhSLz<6d$nMtAq4jJkFORiWC>DFLDUX zee}0{v@o6qUzE8v36)p}Hqf_3#qK-Rh0=KL7G*qM{Jzb2xPp409+!*E%{MQEfno!h zxe`J-{iE{ceq!J{p)H$uuTHj!IARy*Z_|4ID3Ln-QKpS`TXSMFm4SJJe{Ck8USC>( zx|_nCOxNTBT+|Bvu)Ur@H}_$4II|Y!vlgvrsr8}Nv$c7<;+;W~iPlYoRsn&wAxJms zl`au9Ov~w)#R{%+e8!u_w+7d*R9{2VdAv)y%_Tz14@m?O7D*Z^pPRuk#+63(DCAl=>)y2MRW)ksU*C9Cm^%SDn+MN(Wb_vHTAhM zK+Vj(UuT8T*HF;c-E0M-H~bEuZl&%tbGHm_f zj;`Du`h_4+%x&-PYO-9@rp+|#ln7zkO|0Nsv{*-DG43s zdbjkjsh;TJhkjmA-E87%nMv7m5SC$kU<}=F-QL&GAg zOerlhr5XYgKnq5pc_P zxIk=ei&|@+c_%}j(PMh@Z6Vaiyt)8>LLz#rFzD>_{d&3aC~Zs8@A7;$ybj<)H)ZRD zemHdd;}Gthx}LH`J8r>*gPkf>`eE(*<`sbldD6M9hrwW;Hh4(b)aiIkIkceYeWW%? z-KR!(xv6KIjxmjE*_`P+s{yYPtlcMaoOQJP@%fY8OIfNlBUy5H7h7NdKqagxj%4}e z-{(!5IbRob%hKWB=SiA5S7(3AQt97ULz6jMr_{ufYuHy!1DLIO*~IeIP@$S;d8S6R zi6z~kuZm)MrdD+Bze1`fZ3;`ea$gk;R{t01(N{&btXn6#%aZ<&korkm#FDPnR|SJL z{{=$&s>qjhYeoB6(*F@sK55^xq|5YGQ7#J!VKT*be6|v5b8}@?ncS=%!X5D|CfATm zWF=d^@_L5DR`AZa5$Eu8K9TpCUzL|%ONP^B-j!nhbbzSvZFTx5kuX)lt~9u$i5*6yvW7dTJeH*vD6AzAMMv z@r?)d`wxd`o_%%NcHv|N`LA28A3&vt$H#BS5Zi6;e#gmw$Y+e|zYB^yNA4-?8_p*D zEI&cgX-0HI?8&kHMpehqVMSP<($s`CYQQuLpYD^58k$FfnkGax`?(f$e%8>|vC)2D z=Ov@#JpWO1b7KK}0@NBov6?)YHnVW&c~w$<&w1_^t=k;Z7s`sVNDq_a#4mDq?0jY> zZgAQ@*3UV)rFjVxPy5mI$Rrq^X`SUSa5>?ytrh*IyMVsFB#D{T8#I5bg{V($QcxAj z>+*Uvd3~^I(8rMTqJJ=1+nZOE2s823=Fnwie;FDDujL#b#Hu$_>)c{K7tu6y!Bf@o zt?bIx^1vPzmz-7IX;;}IX~h@ zb3*A~9My|VEi8QU_ebz+6)Prjw@BqGo7B`#4^X!KpyK9Z04!88TP-)jo2SEv$ZeFD z`&=Bljc`MpR{)5S`e?7eh-{=y%1=X1@q)>S^M|O?(napK>qXBtjr~gdQfghjSgCys zu*t+t+DA^%cVm0fcAPTWx|a|yEyu`N>xRM_9piDGzYFu$Gs(>W|9k zehlo$PvRKY7O&c^RpF=I%`QgCYzXMriha@j-uEeb=M>CRDbc3nVMKuw51d?(6 zIEk~&Sm%CW)h;ggJpHhoP+xIh#OQavnGaZsSpAZjNZ;6!vXm`}&eoc2v3BiAIqh!F zET+w-Ejw{KIVmnkFZ{O*l?<<05D}^&_FpR;RR$~wDf_YTvOP5LKbktTyG>*&9i!i^ zR5M8g)5u5{4Ya;eDsjy=(OZAjUfuU0#3ro@uCJOB1ee%&LV)rLn6@H^V3*cKWE(lD zYmgOW{fP~Jj1i2`7e)P(OVxK(<4Cf)SBkv1RGIh}{>wQ^yf?KCx`0{BMj~=8Zuq5C zXcyBm+mStQDu(DByC0z!luQLV-7tngw8;QOdP=Z@_@}Nfs)tFn0JEEMFhCo;6*rS3 zSv?>tsS6~y+P6^+Kxjo7qm{NO_ptoZWsNen@8M0Wx6f-&#VG&8H=)oztt--lwRc;-pHH2t`<4Sng*j{Pd z-1ueYIsa~$Rh}qNl2Pv|9s;OBv<2gGd5S1{)RS_AKWbVg#ZZ2MrXD!HQ?X>Ol(f`> zyJj)0Y<~piX|hDmZ6k&BKr!lzXk9M zZ)i;k7d0)>_+@#4DBteYc!|Fy8AXmBqk+=inavYAtFcu%NIFcibqta%5szEme?zX( zy|r%t_43kMc%doHc9A20P)`oiR!c%0hH%I*ZL2s3LuQNRt4!o$X~b&BYUT=Z7ee$F zm?%v%y7CZfW^7hplpGKoyl{Z>2$oxP)6GL0JwRHWRQdd5q-u7R4w5DN352M&4oeW6 z@!6JsN}bBz3|$_L?jVoxZ|qh{+ma=_=Es==Mg7#{mJD5?v&Cs=CcV+93QTSHVX?9P~u>tBCe%B4M>GW+(^xDGe5&jBxt%=9vd)u8I2AQ5XnJ!GpJGk zXC|EsPap0wpXD|lS@2CfXeQ3#y>{v)olqvh=KU7B^^fbTD#@+XC0f&p8xeN>4CmU? zids&z+6R}h$=CL7a_52W1B*u>5zUL4oBg1Y3`2)|CimI^GPCfOT@Rm|#l1)P012GM zf3~p*@c+G&Z#7pZ3lDSH90+D-3rkIi4hJ_UACQwrhy{a7(!<@_$(7lF7bF1NK?Xn| zQ1VGQJPFe$;rJvho`lVR1|d(#0LTa1fk3$@;rb;0#CLu|e*}buOVh^P9`X;l|H4sU zRs0X~X5rHCFtdf2yEC(JNyBD{xWlfFk}2$>0X%JBb|`C@xyscQV#&g#2=VrGatSziX6oqp)NGp8Hf{je?=Q{A4$y|Uy1|MA@N&Y+;D`Nr^Ye1>a0>jb zU114e^;NQgLI6)SVFB1Vo4Q-OK}-SAza|vmjYv&99|O%*M{=f(u)Xu?$B|%wV=rxm9|z!uU6Kr?0mRS zeF@Q(?ly@$GNIe`XQ%8(!eFO3(hWmi;6b$ChB;b4Ym09uNABL~flbIj+BHj~?fI;@ zaZ3N4MS!ST*THO#seBfLH;dpVCZD|Y<5}%AiHE3=(8e54nm=5gXwu^~HK(QC?KZ0} z`wcvIi(QZuex(}HNII%tT~`3w2~axwHEfed?+SM2LsXXNvfR+)AdtQ!1tkDKd|GcGwzlioo|iFXDiO=-7&OYG6?DK|~71iz+O zQ{VlrFc&naLCI`t&3t={&{V(Z{jWIA|97u3{?cSR>JUo|E_p`_h!;Q~2oT^GFvQ@} zu^De}MW^3QH$g=;o?)V_m( zP8%2Z20_XSQ3?$`{0$W*+R|aUx8~&;ctY#Ed2^g2=QCHg0vTIPv7a{OcS<(%%@~nF zpnz0{nuuisQhedQ+U#=#}9eblv6Z(w1lCAx=BIRKq%OG&ZS82DYM@ultjpz9gEP`mYlB(zsrW_Y@ zf>$f-LyMP`pj(dxUS>52-E~HE?BJ-!c5_BO=n$O`y*+}X?m!R?`FVtt-ofj2fWxyT zY_ccCp%@VFGH-VMflhaqx@b2&ec_u`qq7HVl+Whv5^PGm~NJac?mZu0tnXj!#QN85Wz{b?Ns4=(B}RaD(Gj zNfynmVWMWapMHgBITb+qxlVlMR+)>}KG0tB<+7Jb4B&ApZhB5$u-MdHJn<5v7X_b=;be!m^1o8(~ z5+m94yiQhk4Qhc;q1~j1bmr<=9&FeMF?qgF>0s%(uA@+@Zzm=7o94m zKmiU$)U{zzEW&Hpdf}=BxAQjRb`Lru#dLTJ>h#w!8366rm0t91i*qUQ|(tn99quvwAJA{EvMQ^TzE7S@UldWX#dc-A;66 zAEr)1E565<`KOcg;H+1!PxYbMUPrH%tb^aw#V=7W>IE2j*g_j8Q0nas1QyAi_E|^9EbXo*mrm6A z1js2uqpt)|4Qf;KE`yTL$lXW~RMk&fd4Q)38UPbrn1)TjBjUEB;p+%P%Jx^Fs zmZh#B*W;TPpl0~njYfhe%Azev&J&o-me6nSXWLOKU%t9FFm+~ zE!}&BEj`+WskZjCs