From 8c0d246cb3cdaab2950664315d76d3c4e43ac9b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 00:09:21 +0000 Subject: [PATCH] Update pkgdown documentation bcef4f9b0b243764b433bad92f3b66a5892344c0 --- v0.15.1/404.html | 131 + v0.15.1/CODE_OF_CONDUCT.html | 176 + v0.15.1/CONTRIBUTING.html | 227 + v0.15.1/LICENSE-text.html | 122 + v0.15.1/SECURITY.html | 131 + v0.15.1/analytics.js | 1 + .../adding-support-for-reporting.html | 522 + v0.15.1/articles/blueprint/actors.html | 262 + v0.15.1/articles/blueprint/dataflow.html | 194 + v0.15.1/articles/blueprint/filter_panel.html | 203 + v0.15.1/articles/blueprint/in_app_data.html | 173 + v0.15.1/articles/blueprint/index.html | 153 + v0.15.1/articles/blueprint/input_data.html | 209 + .../figure-html/teal_data_dot_diagram-1.png | Bin 0 -> 17563 bytes v0.15.1/articles/blueprint/intro.html | 215 + .../blueprint/module_encapsulation.html | 180 + v0.15.1/articles/blueprint/product_map.html | 222 + .../articles/bootstrap-themes-in-teal.html | 384 + v0.15.1/articles/creating-custom-modules.html | 340 + v0.15.1/articles/data-as-shiny-module.html | 304 + v0.15.1/articles/filter-panel.html | 282 + .../articles/getting-started-with-teal.html | 348 + v0.15.1/articles/images/bs-corners.png | Bin 0 -> 133220 bytes v0.15.1/articles/images/bs-final.png | Bin 0 -> 109110 bytes v0.15.1/articles/images/bs-font-size.png | Bin 0 -> 138446 bytes v0.15.1/articles/images/bs-launch.png | Bin 0 -> 113504 bytes v0.15.1/articles/images/bs-theme-set.png | Bin 0 -> 102940 bytes v0.15.1/articles/images/custom_app.png | Bin 0 -> 116254 bytes v0.15.1/articles/images/filters-mapping.svg | 1 + .../images/show_code_prepro_missing.png | Bin 0 -> 49689 bytes .../images/show_code_prepro_present.png | Bin 0 -> 48877 bytes .../images/teal-app-components-hover.svg | 1 + .../articles/images/teal-app-components.svg | 1 + .../including-data-in-teal-applications.html | 460 + v0.15.1/articles/index.html | 171 + v0.15.1/articles/teal-options.html | 315 + v0.15.1/authors.html | 202 + v0.15.1/consent.css | 28 + v0.15.1/consent.js | 95 + v0.15.1/cookie_policy.txt | 11 + .../bootstrap-5.3.1/bootstrap.bundle.min.js | 7 + .../bootstrap.bundle.min.js.map | 1 + .../deps/bootstrap-5.3.1/bootstrap.min.css | 5 + v0.15.1/deps/bootstrap-5.3.1/font.css | 124 + ...txg8zYS_SKggPN4iEgvnHyvveLxVs9pbCIPrc.woff | Bin 0 -> 27828 bytes ...txg8zYS_SKggPN4iEgvnHyvveLxVvaorCIPrc.woff | Bin 0 -> 27492 bytes .../1adeadb2fe618c5ed46221f15e12b9c8.woff | Bin 0 -> 46088 bytes .../fonts/4iCs6KVjbNBYlgo6ew.woff | Bin 0 -> 134032 bytes .../fonts/4iCs6KVjbNBYlgoKfw7w.woff | Bin 0 -> 39832 bytes .../fonts/4iCv6KVjbNBYlgoCxCvTtA.woff | Bin 0 -> 117140 bytes .../fonts/4iCv6KVjbNBYlgoCxCvjsGyL.woff | Bin 0 -> 34452 bytes .../6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDQ.woff | Bin 0 -> 17760 bytes .../6xK1dSBYKcSV-LCoeQqfX1RYOo3qPa7j.woff | Bin 0 -> 49156 bytes .../fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3aPA.woff | Bin 0 -> 74684 bytes .../6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7j.woff | Bin 0 -> 18420 bytes .../6xKydSBYKcSV-LCoeQqfX1RYOo3i54rAkw.woff | Bin 0 -> 74348 bytes .../6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vAkw.woff | Bin 0 -> 74332 bytes .../6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdo.woff | Bin 0 -> 18388 bytes .../6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zAkw.woff | Bin 0 -> 74148 bytes .../6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdo.woff | Bin 0 -> 18340 bytes .../fonts/CSR54z1Qlv-GDxkbKVQ_dFsvWNRevw.woff | Bin 0 -> 16724 bytes .../fonts/CSR54z1Qlv-GDxkbKVQ_dFsvaNA.woff | Bin 0 -> 29672 bytes .../fonts/CSR64z1Qlv-GDxkbKVQ_TOQ.woff | Bin 0 -> 75128 bytes .../fonts/CSR64z1Qlv-GDxkbKVQ_fOAKSw.woff | Bin 0 -> 16516 bytes ...xRpg3hIP6sJ7fM7PqPMcMnZFqUwX28DBKXhM0.woff | Bin 0 -> 55992 bytes ...xRpg3hIP6sJ7fM7PqPMcMnZFqUwX28DMyQhM0.woff | Bin 0 -> 56004 bytes ...g3hIP6sJ7fM7PqlOPHYvDP_W9O7GQTTbI1rSg.woff | Bin 0 -> 47720 bytes ...g3hIP6sJ7fM7PqlOPHYvDP_W9O7GQTTsoprSg.woff | Bin 0 -> 47924 bytes ...HjIg1_i6t8kCHKm4532VJOt5-QNFgpCtZ6Ew9.woff | Bin 0 -> 50580 bytes ...HjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew9.woff | Bin 0 -> 50580 bytes ...HjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM70w9.woff | Bin 0 -> 51108 bytes .../fonts/KFOlCnqEu92Fr1MmEU9fBBc-.woff | Bin 0 -> 20544 bytes .../fonts/KFOlCnqEu92Fr1MmEU9vAA.woff | Bin 0 -> 65756 bytes .../fonts/KFOlCnqEu92Fr1MmSU5fBBc-.woff | Bin 0 -> 20416 bytes .../fonts/KFOlCnqEu92Fr1MmSU5vAA.woff | Bin 0 -> 65164 bytes .../fonts/KFOlCnqEu92Fr1MmWUlfBBc-.woff | Bin 0 -> 20408 bytes .../fonts/KFOlCnqEu92Fr1MmWUlvAA.woff | Bin 0 -> 65556 bytes .../fonts/KFOmCnqEu92Fr1Me5g.woff | Bin 0 -> 65456 bytes .../fonts/KFOmCnqEu92Fr1Mu4mxM.woff | Bin 0 -> 20344 bytes .../fonts/QGYpz_kZZAGCONcK2A4bGOj8mNhL.woff | Bin 0 -> 89776 bytes .../fonts/S6u8w4BMUTPHjxsAXC-s.woff | Bin 0 -> 29864 bytes .../fonts/S6u8w4BMUTPHjxswWA.woff | Bin 0 -> 35436 bytes .../fonts/S6u9w4BMUTPHh6UVSwiPHw.woff | Bin 0 -> 28044 bytes .../fonts/S6u9w4BMUTPHh6UVeww.woff | Bin 0 -> 33296 bytes .../fonts/S6u9w4BMUTPHh7USSwiPHw.woff | Bin 0 -> 30016 bytes .../fonts/S6u9w4BMUTPHh7USeww.woff | Bin 0 -> 35168 bytes .../fonts/S6uyw4BMUTPHjx4wWA.woff | Bin 0 -> 28648 bytes .../fonts/S6uyw4BMUTPHvxo.woff | Bin 0 -> 34020 bytes ...HuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZs.woff | Bin 0 -> 138900 bytes ...HuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZs.woff | Bin 0 -> 137508 bytes ...HuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff | Bin 0 -> 128192 bytes .../XRXI3I6Li01BKofiOc5wtlZ2di8HDFwmRTA.woff | Bin 0 -> 53216 bytes .../XRXI3I6Li01BKofiOc5wtlZ2di8HDGUmRTA.woff | Bin 0 -> 54196 bytes .../XRXI3I6Li01BKofiOc5wtlZ2di8HDLshRTA.woff | Bin 0 -> 53856 bytes .../a98f7a7574819ba83bec6279a2cecd95.woff | Bin 0 -> 45884 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk0ZjaVQ.woff | Bin 0 -> 72136 bytes ...SCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkWVAexg.woff | Bin 0 -> 23636 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVQ.woff | Bin 0 -> 74700 bytes ...SCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkWVAexg.woff | Bin 0 -> 23576 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVQ.woff | Bin 0 -> 74564 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk_RkaVQ.woff | Bin 0 -> 74940 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkxhjaVQ.woff | Bin 0 -> 74644 bytes ...SCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjWVAexg.woff | Bin 0 -> 22964 bytes ...cVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVQ.woff | Bin 0 -> 71660 bytes ...X2vVnXBbObj2OVZyOOSr4dVJWUgsg-1x4gaVQ.woff | Bin 0 -> 22332 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4k.woff | Bin 0 -> 68664 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgsgH1y4k.woff | Bin 0 -> 70652 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgshZ1y4k.woff | Bin 0 -> 69392 bytes ...X2vVnXBbObj2OVZyOOSr4dVJWUgsiH0B4gaVQ.woff | Bin 0 -> 22940 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4k.woff | Bin 0 -> 70524 bytes ...X2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVQ.woff | Bin 0 -> 22908 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4k.woff | Bin 0 -> 70792 bytes ...vWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjr0C4k.woff | Bin 0 -> 71144 bytes .../fonts/q5uGsou0JOdh94bfvQlr.woff | Bin 0 -> 31584 bytes v0.15.1/deps/data-deps.txt | 4 + v0.15.1/deps/jquery-3.6.0/jquery-3.6.0.js | 10881 ++++++++++++++++ v0.15.1/deps/jquery-3.6.0/jquery-3.6.0.min.js | 2 + .../deps/jquery-3.6.0/jquery-3.6.0.min.map | 1 + v0.15.1/index.html | 329 + v0.15.1/link.svg | 12 + v0.15.1/news/index.html | 627 + v0.15.1/pkgdown.js | 156 + v0.15.1/pkgdown.yml | 26 + v0.15.1/pull_request_template.html | 113 + v0.15.1/reference/Rplot001.png | Bin 0 -> 1011 bytes v0.15.1/reference/TealReportCard.html | 280 + v0.15.1/reference/TealSlicesBlock.html | 242 + v0.15.1/reference/append_module.html | 135 + v0.15.1/reference/build_app_title.html | 140 + v0.15.1/reference/calculate_hashes.html | 135 + v0.15.1/reference/check_filter_datanames.html | 138 + .../reference/check_modules_datanames.html | 138 + v0.15.1/reference/create_app_id.html | 141 + v0.15.1/reference/deep_copy_filter.html | 142 + v0.15.1/reference/dot-datasets_to_data.html | 141 + v0.15.1/reference/example_module.html | 151 + .../figures/filter_state_reactivity.jpg | Bin 0 -> 62773 bytes v0.15.1/reference/figures/filterpanel.png | Bin 0 -> 116824 bytes .../reference/figures/lifecycle-archived.svg | 1 + .../reference/figures/lifecycle-defunct.svg | 1 + .../figures/lifecycle-deprecated.svg | 1 + .../figures/lifecycle-experimental.svg | 1 + .../reference/figures/lifecycle-maturing.svg | 1 + .../figures/lifecycle-questioning.svg | 1 + .../figures/lifecycle-soft-deprecated.svg | 1 + .../reference/figures/lifecycle-stable.svg | 1 + .../figures/lifecycle-superseded.svg | 1 + .../reference/figures/module_nested_tabs.jpg | Bin 0 -> 33648 bytes v0.15.1/reference/figures/notification.jpg | Bin 0 -> 288712 bytes v0.15.1/reference/figures/readme_app.webp | Bin 0 -> 786974 bytes v0.15.1/reference/figures/reporter.jpg | Bin 0 -> 207761 bytes v0.15.1/reference/figures/showrcode.jpg | Bin 0 -> 278194 bytes v0.15.1/reference/figures/teal.png | Bin 0 -> 79859 bytes .../reference/filter_manager_module_srv.html | 153 + v0.15.1/reference/get_client_timezone.html | 136 + v0.15.1/reference/get_code_tdata.html | 131 + v0.15.1/reference/get_datasets_code.html | 141 + v0.15.1/reference/get_metadata.html | 141 + v0.15.1/reference/get_rcode_libraries.html | 125 + v0.15.1/reference/include_css_files.html | 137 + v0.15.1/reference/include_js_files.html | 141 + v0.15.1/reference/include_teal_css_js.html | 141 + v0.15.1/reference/index.html | 320 + v0.15.1/reference/init.html | 241 + v0.15.1/reference/is_arg_used.html | 135 + v0.15.1/reference/join_keys.tdata.html | 130 + v0.15.1/reference/landing_popup_module.html | 202 + v0.15.1/reference/matrix_to_mapping.html | 141 + v0.15.1/reference/module_filter_manager.html | 154 + .../module_filter_manager_modal.html | 141 + v0.15.1/reference/module_labels.html | 132 + v0.15.1/reference/module_management.html | 141 + v0.15.1/reference/module_nested_tabs.html | 225 + .../reference/module_tabs_with_filters.html | 176 + v0.15.1/reference/module_teal.html | 199 + .../reference/module_teal_with_splash.html | 212 + v0.15.1/reference/modules_depth.html | 142 + v0.15.1/reference/reexports.html | 145 + v0.15.1/reference/report_card_template.html | 157 + .../reference/reporter_previewer_module.html | 155 + .../reference/resolve_modules_datanames.html | 142 + v0.15.1/reference/run_js_files.html | 146 + v0.15.1/reference/show_rcode_modal.html | 143 + v0.15.1/reference/slices_store.html | 158 + .../reference/snapshot_manager_module.html | 219 + v0.15.1/reference/tdata.html | 353 + v0.15.1/reference/tdata2env.html | 144 + v0.15.1/reference/tdata_deprecation.html | 191 + v0.15.1/reference/teal-package.html | 151 + v0.15.1/reference/teal_data_datanames.html | 136 + v0.15.1/reference/teal_data_module.html | 325 + .../reference/teal_data_to_filtered_data.html | 135 + v0.15.1/reference/teal_modules.html | 297 + v0.15.1/reference/teal_slices.html | 244 + v0.15.1/reference/unfold_mapping.html | 135 + v0.15.1/reference/validate_app_title_tag.html | 125 + v0.15.1/reference/validate_has_data.html | 180 + v0.15.1/reference/validate_has_elements.html | 168 + v0.15.1/reference/validate_has_variable.html | 164 + v0.15.1/reference/validate_in.html | 162 + v0.15.1/reference/validate_inputs.html | 233 + v0.15.1/reference/validate_n_levels.html | 180 + .../reference/validate_no_intersection.html | 177 + .../reference/validate_one_row_per_id.html | 160 + v0.15.1/search.json | 1 + v0.15.1/sitemap.xml | 270 + 206 files changed, 29277 insertions(+) create mode 100644 v0.15.1/404.html create mode 100644 v0.15.1/CODE_OF_CONDUCT.html create mode 100644 v0.15.1/CONTRIBUTING.html create mode 100644 v0.15.1/LICENSE-text.html create mode 100644 v0.15.1/SECURITY.html create mode 100644 v0.15.1/analytics.js create mode 100644 v0.15.1/articles/adding-support-for-reporting.html create mode 100644 v0.15.1/articles/blueprint/actors.html create mode 100644 v0.15.1/articles/blueprint/dataflow.html create mode 100644 v0.15.1/articles/blueprint/filter_panel.html create mode 100644 v0.15.1/articles/blueprint/in_app_data.html create mode 100644 v0.15.1/articles/blueprint/index.html create mode 100644 v0.15.1/articles/blueprint/input_data.html create mode 100644 v0.15.1/articles/blueprint/input_data_files/figure-html/teal_data_dot_diagram-1.png create mode 100644 v0.15.1/articles/blueprint/intro.html create mode 100644 v0.15.1/articles/blueprint/module_encapsulation.html create mode 100644 v0.15.1/articles/blueprint/product_map.html create mode 100644 v0.15.1/articles/bootstrap-themes-in-teal.html create mode 100644 v0.15.1/articles/creating-custom-modules.html create mode 100644 v0.15.1/articles/data-as-shiny-module.html create mode 100644 v0.15.1/articles/filter-panel.html create mode 100644 v0.15.1/articles/getting-started-with-teal.html create mode 100644 v0.15.1/articles/images/bs-corners.png create mode 100644 v0.15.1/articles/images/bs-final.png create mode 100644 v0.15.1/articles/images/bs-font-size.png create mode 100644 v0.15.1/articles/images/bs-launch.png create mode 100644 v0.15.1/articles/images/bs-theme-set.png create mode 100644 v0.15.1/articles/images/custom_app.png create mode 100644 v0.15.1/articles/images/filters-mapping.svg create mode 100644 v0.15.1/articles/images/show_code_prepro_missing.png create mode 100644 v0.15.1/articles/images/show_code_prepro_present.png create mode 100644 v0.15.1/articles/images/teal-app-components-hover.svg create mode 100644 v0.15.1/articles/images/teal-app-components.svg create mode 100644 v0.15.1/articles/including-data-in-teal-applications.html create mode 100644 v0.15.1/articles/index.html create mode 100644 v0.15.1/articles/teal-options.html create mode 100644 v0.15.1/authors.html create mode 100644 v0.15.1/consent.css create mode 100644 v0.15.1/consent.js create mode 100644 v0.15.1/cookie_policy.txt create mode 100644 v0.15.1/deps/bootstrap-5.3.1/bootstrap.bundle.min.js create mode 100644 v0.15.1/deps/bootstrap-5.3.1/bootstrap.bundle.min.js.map create mode 100644 v0.15.1/deps/bootstrap-5.3.1/bootstrap.min.css create mode 100644 v0.15.1/deps/bootstrap-5.3.1/font.css create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVs9pbCIPrc.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVvaorCIPrc.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/1adeadb2fe618c5ed46221f15e12b9c8.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/4iCs6KVjbNBYlgo6ew.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/4iCs6KVjbNBYlgoKfw7w.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/4iCv6KVjbNBYlgoCxCvTtA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/4iCv6KVjbNBYlgoCxCvjsGyL.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPa7j.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3aPA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7j.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rAkw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vAkw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdo.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zAkw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdo.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvWNRevw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvaNA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/CSR64z1Qlv-GDxkbKVQ_TOQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/CSR64z1Qlv-GDxkbKVQ_fOAKSw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/HI_diYsKILxRpg3hIP6sJ7fM7PqPMcMnZFqUwX28DBKXhM0.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/HI_diYsKILxRpg3hIP6sJ7fM7PqPMcMnZFqUwX28DMyQhM0.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/HI_jiYsKILxRpg3hIP6sJ7fM7PqlOPHYvDP_W9O7GQTTbI1rSg.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/HI_jiYsKILxRpg3hIP6sJ7fM7PqlOPHYvDP_W9O7GQTTsoprSg.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtZ6Ew9.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew9.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM70w9.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmEU9vAA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmSU5vAA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOlCnqEu92Fr1MmWUlvAA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOmCnqEu92Fr1Me5g.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/KFOmCnqEu92Fr1Mu4mxM.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/QGYpz_kZZAGCONcK2A4bGOj8mNhL.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u8w4BMUTPHjxsAXC-s.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u8w4BMUTPHjxswWA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u9w4BMUTPHh6UVSwiPHw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u9w4BMUTPHh6UVeww.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u9w4BMUTPHh7USSwiPHw.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6u9w4BMUTPHh7USeww.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6uyw4BMUTPHjx4wWA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/S6uyw4BMUTPHvxo.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZs.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZs.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/XRXI3I6Li01BKofiOc5wtlZ2di8HDFwmRTA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/XRXI3I6Li01BKofiOc5wtlZ2di8HDGUmRTA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/XRXI3I6Li01BKofiOc5wtlZ2di8HDLshRTA.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/a98f7a7574819ba83bec6279a2cecd95.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk0ZjaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkWVAexg.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkWVAexg.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk_RkaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkxhjaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjWVAexg.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1x4gaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsgH1y4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgshZ1y4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0B4gaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVQ.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjr0C4k.woff create mode 100644 v0.15.1/deps/bootstrap-5.3.1/fonts/q5uGsou0JOdh94bfvQlr.woff create mode 100644 v0.15.1/deps/data-deps.txt create mode 100644 v0.15.1/deps/jquery-3.6.0/jquery-3.6.0.js create mode 100644 v0.15.1/deps/jquery-3.6.0/jquery-3.6.0.min.js create mode 100644 v0.15.1/deps/jquery-3.6.0/jquery-3.6.0.min.map create mode 100644 v0.15.1/index.html create mode 100644 v0.15.1/link.svg create mode 100644 v0.15.1/news/index.html create mode 100644 v0.15.1/pkgdown.js create mode 100644 v0.15.1/pkgdown.yml create mode 100644 v0.15.1/pull_request_template.html create mode 100644 v0.15.1/reference/Rplot001.png create mode 100644 v0.15.1/reference/TealReportCard.html create mode 100644 v0.15.1/reference/TealSlicesBlock.html create mode 100644 v0.15.1/reference/append_module.html create mode 100644 v0.15.1/reference/build_app_title.html create mode 100644 v0.15.1/reference/calculate_hashes.html create mode 100644 v0.15.1/reference/check_filter_datanames.html create mode 100644 v0.15.1/reference/check_modules_datanames.html create mode 100644 v0.15.1/reference/create_app_id.html create mode 100644 v0.15.1/reference/deep_copy_filter.html create mode 100644 v0.15.1/reference/dot-datasets_to_data.html create mode 100644 v0.15.1/reference/example_module.html create mode 100644 v0.15.1/reference/figures/filter_state_reactivity.jpg create mode 100644 v0.15.1/reference/figures/filterpanel.png create mode 100644 v0.15.1/reference/figures/lifecycle-archived.svg create mode 100644 v0.15.1/reference/figures/lifecycle-defunct.svg create mode 100644 v0.15.1/reference/figures/lifecycle-deprecated.svg create mode 100644 v0.15.1/reference/figures/lifecycle-experimental.svg create mode 100644 v0.15.1/reference/figures/lifecycle-maturing.svg create mode 100644 v0.15.1/reference/figures/lifecycle-questioning.svg create mode 100644 v0.15.1/reference/figures/lifecycle-soft-deprecated.svg create mode 100644 v0.15.1/reference/figures/lifecycle-stable.svg create mode 100644 v0.15.1/reference/figures/lifecycle-superseded.svg create mode 100644 v0.15.1/reference/figures/module_nested_tabs.jpg create mode 100644 v0.15.1/reference/figures/notification.jpg create mode 100644 v0.15.1/reference/figures/readme_app.webp create mode 100644 v0.15.1/reference/figures/reporter.jpg create mode 100644 v0.15.1/reference/figures/showrcode.jpg create mode 100644 v0.15.1/reference/figures/teal.png create mode 100644 v0.15.1/reference/filter_manager_module_srv.html create mode 100644 v0.15.1/reference/get_client_timezone.html create mode 100644 v0.15.1/reference/get_code_tdata.html create mode 100644 v0.15.1/reference/get_datasets_code.html create mode 100644 v0.15.1/reference/get_metadata.html create mode 100644 v0.15.1/reference/get_rcode_libraries.html create mode 100644 v0.15.1/reference/include_css_files.html create mode 100644 v0.15.1/reference/include_js_files.html create mode 100644 v0.15.1/reference/include_teal_css_js.html create mode 100644 v0.15.1/reference/index.html create mode 100644 v0.15.1/reference/init.html create mode 100644 v0.15.1/reference/is_arg_used.html create mode 100644 v0.15.1/reference/join_keys.tdata.html create mode 100644 v0.15.1/reference/landing_popup_module.html create mode 100644 v0.15.1/reference/matrix_to_mapping.html create mode 100644 v0.15.1/reference/module_filter_manager.html create mode 100644 v0.15.1/reference/module_filter_manager_modal.html create mode 100644 v0.15.1/reference/module_labels.html create mode 100644 v0.15.1/reference/module_management.html create mode 100644 v0.15.1/reference/module_nested_tabs.html create mode 100644 v0.15.1/reference/module_tabs_with_filters.html create mode 100644 v0.15.1/reference/module_teal.html create mode 100644 v0.15.1/reference/module_teal_with_splash.html create mode 100644 v0.15.1/reference/modules_depth.html create mode 100644 v0.15.1/reference/reexports.html create mode 100644 v0.15.1/reference/report_card_template.html create mode 100644 v0.15.1/reference/reporter_previewer_module.html create mode 100644 v0.15.1/reference/resolve_modules_datanames.html create mode 100644 v0.15.1/reference/run_js_files.html create mode 100644 v0.15.1/reference/show_rcode_modal.html create mode 100644 v0.15.1/reference/slices_store.html create mode 100644 v0.15.1/reference/snapshot_manager_module.html create mode 100644 v0.15.1/reference/tdata.html create mode 100644 v0.15.1/reference/tdata2env.html create mode 100644 v0.15.1/reference/tdata_deprecation.html create mode 100644 v0.15.1/reference/teal-package.html create mode 100644 v0.15.1/reference/teal_data_datanames.html create mode 100644 v0.15.1/reference/teal_data_module.html create mode 100644 v0.15.1/reference/teal_data_to_filtered_data.html create mode 100644 v0.15.1/reference/teal_modules.html create mode 100644 v0.15.1/reference/teal_slices.html create mode 100644 v0.15.1/reference/unfold_mapping.html create mode 100644 v0.15.1/reference/validate_app_title_tag.html create mode 100644 v0.15.1/reference/validate_has_data.html create mode 100644 v0.15.1/reference/validate_has_elements.html create mode 100644 v0.15.1/reference/validate_has_variable.html create mode 100644 v0.15.1/reference/validate_in.html create mode 100644 v0.15.1/reference/validate_inputs.html create mode 100644 v0.15.1/reference/validate_n_levels.html create mode 100644 v0.15.1/reference/validate_no_intersection.html create mode 100644 v0.15.1/reference/validate_one_row_per_id.html create mode 100644 v0.15.1/search.json create mode 100644 v0.15.1/sitemap.xml diff --git a/v0.15.1/404.html b/v0.15.1/404.html new file mode 100644 index 0000000000..fddd97ccd4 --- /dev/null +++ b/v0.15.1/404.html @@ -0,0 +1,131 @@ + + +
+ + + + +.github/CODE_OF_CONDUCT.md
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
+Examples of behavior that contributes to a positive environment for our community include:
+Examples of unacceptable behavior include:
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly.
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+Community Impact: A violation through a single incident or series of actions.
+Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+Community Impact: A serious violation of community standards, including sustained inappropriate behavior.
+Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+Consequence: A permanent ban from any sort of public interaction within the community.
+This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
+Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder.
+For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
+.github/CONTRIBUTING.md
+ 🙏 Thank you for taking the time to contribute!
+Your input is deeply valued, whether an issue, a pull request, or even feedback, regardless of size, content or scope.
+ +Please refer the project documentation for a brief introduction. Please also see other articles within the project documentation for additional information.
+A Code of Conduct governs this project. Participants and contributors are expected to follow the rules outlined therein.
+All your contributions will be covered by this project’s license.
+We use GitHub to track issues, feature requests, and bugs. Before submitting a new issue, please check if the issue has already been reported. If the issue already exists, please upvote the existing issue 👍.
+For new feature requests, please elaborate on the context and the benefit the feature will have for users, developers, or other relevant personas.
+This repository uses the GitHub Flow model for collaboration. To submit a pull request:
+Create a branch
+Please see the branch naming convention below. If you don’t have write access to this repository, please fork it.
+Make changes
+Make sure your code
+Create a pull request (PR)
+In the pull request description, please link the relevant issue (if any), provide a detailed description of the change, and include any assumptions.
+Address review comments, if any
Post approval
+Merge your PR if you have write access. Otherwise, the reviewer will merge the PR on your behalf.
+Pat yourself on the back
+Congratulations! 🎉 You are now an official contributor to this project! We are grateful for your contribution.
+Suppose your changes are related to a current issue in the current project; please name your branch as follows: <issue_id>_<short_description>
. Please use underscore (_
) as a delimiter for word separation. For example, 420_fix_ui_bug
would be a suitable branch name if your change is resolving and UI-related bug reported in issue number 420
in the current project.
If your change affects multiple repositories, please name your branches as follows: <issue_id>_<issue_repo>_<short description>
. For example, 69_awesomeproject_fix_spelling_error
would reference issue 69
reported in project awesomeproject
and aims to resolve one or more spelling errors in multiple (likely related) repositories.
monorepo
and staged.dependencies
+Sometimes you might need to change upstream dependent package(s) to be able to submit a meaningful change. We are using staged.dependencies
functionality to simulate a monorepo
behavior. The dependency configuration is already specified in this project’s staged_dependencies.yaml
file. You need to name the feature branches appropriately. This is the only exception from the branch naming convention described above.
Please refer to the staged.dependencies package documentation for more details.
+This repository follows some unified processes and standards adopted by its maintainers to ensure software development is carried out consistently within teams and cohesively across other repositories.
+This repository follows the standard tidyverse
style guide and uses lintr
for lint checks. Customized lint configurations are available in this repository’s .lintr
file.
Lightweight is the right weight. This repository follows tinyverse recommedations of limiting dependencies to minimum.
+If the code is not compatible with all (!) historical versions of a given dependenct package, it is required to specify minimal version in the DESCRIPTION
file. In particular: if the development version requires (imports) the development version of another package - it is required to put abc (>= 1.2.3.9000)
.
We continuously test our packages against the newest R version along with the most recent dependencies from CRAN and BioConductor. We recommend that your working environment is also set up in the same way. You can find the details about the R version and packages used in the R CMD check
GitHub Action execution log - there is a step that prints out the R sessionInfo()
.
If you discover bugs on older R versions or with an older set of dependencies, please create the relevant bug reports.
+pre-commit
We highly recommend that you use the pre-commit
tool combined with R hooks for pre-commit
to execute some of the checks before committing and pushing your changes.
Pre-commit hooks are already available in this repository’s .pre-commit-config.yaml
file.
As mentioned previously, all contributions are deeply valued and appreciated. While all contribution data is available as part of the repository insights, to recognize a significant contribution and hence add the contributor to the package authors list, the following rules are enforced:
+git blame
query) OR*Excluding auto-generated code, including but not limited to roxygen
comments or renv.lock
files.
The package maintainer also reserves the right to adjust the criteria to recognize contributions.
+Copyright 2022 F. Hoffmann-La Roche AG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. ++ +
SECURITY.md
+ If you believe you have found a security vulnerability in any of the repositories in this organization, please report it to us through coordinated disclosure.
+Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.
+Instead, please send an email to vulnerability.management[@]roche.com.
+Please include as much of the information listed below as you can to help us better understand and resolve the issue:
+This information will help us triage your report more quickly.
+vignettes/adding-support-for-reporting.Rmd
+ adding-support-for-reporting.Rmd
The teal
package offers an integrated reporting feature
+utilizing the teal.reporter
package. For a comprehensive
+explanation of the reporting functionality itself, please refer to the
+documentation therein.
This article is intended for module developers and aims to provide
+guidance on enhancing a custom teal
module with an
+automatic reporting feature. This enhancement enables users to
+incorporate snapshots of the module outputs into a report which can then
+be reviewed in another module automatically provided by
+teal
. Thus the app user can interact with the report.
The responsibilities of a module developer include:
+The entire life cycle of objects involved in creating the report and
+configuring the module to preview the report is handled by
+teal
.
Let us consider an example module, based on the example module from
+teal
:
+library(teal)
+example_module <- function(label = "example teal module") {
+ module(
+ label = label,
+ server = function(id, data) {
+ checkmate::assert_class(data, "reactive")
+ checkmate::assert_class(isolate(data()), "teal_data")
+
+ moduleServer(id, function(input, output, session) {
+ updateSelectInput(session, "dataname", choices = isolate(datanames(data())))
+ output$dataset <- renderPrint({
+ req(input$dataname)
+ data()[[input$dataname]]
+ })
+ })
+ },
+ ui = function(id) {
+ ns <- NS(id)
+ sidebarLayout(
+ sidebarPanel(selectInput(ns("dataname"), "Choose a dataset", choices = NULL)),
+ mainPanel(verbatimTextOutput(ns("dataset")))
+ )
+ }
+ )
+}
Using teal
, you can launch this example module with the
+following:
+app <- init(
+ data = teal_data(IRIS = iris, MTCARS = mtcars),
+ modules = example_module()
+)
+
+if (interactive()) shinyApp(app$ui, app$server)
The first step is to add an additional argument to the server
+function declaration - reporter
. This informs
+teal
that the module requires reporter
, and it
+will be included when the module is called. See below:
+example_module_with_reporting <- function(label = "example teal module") {
+ module(
+ label = label,
+ server = function(id, data, reporter) {
+ moduleServer(id, function(input, output, session) {
+ updateSelectInput(session, "dataname", choices = isolate(datanames(data())))
+ output$dataset <- renderPrint({
+ req(input$dataname)
+ data()[[input$dataname]]
+ })
+ })
+ },
+ ui = function(id) {
+ ns <- NS(id)
+ sidebarLayout(
+ sidebarPanel(selectInput(ns("dataname"), "Choose a dataset", choices = NULL)),
+ mainPanel(verbatimTextOutput(ns("dataset")))
+ )
+ }
+ )
+}
With these modifications, the module is now ready to be launched with
+teal
:
+app <- init(
+ data = teal_data(IRIS = iris, MTCARS = mtcars),
+ modules = example_module_with_reporting()
+)
+
+if (interactive()) shinyApp(app$ui, app$server)
teal
adds another tab to the application, titled
+Report previewer
. However, there is no visible change in
+how the module operates and appears and the user cannot add content to
+the report from this module. That requires inserting UI and server
+elements of the teal.reporter
module into the module
+body.
teal.reporter
module
+The UI and the server logic necessary for adding cards from
+example_module_with_reporting
to the report are provided by
+teal.reporter::simple_reporter_ui
and
+teal.reporter::simple_reporter_srv
.
+example_module_with_reporting <- function(label = "example teal module") {
+ module(
+ label = label,
+ server = function(id, data, reporter) {
+ moduleServer(id, function(input, output, session) {
+ teal.reporter::simple_reporter_srv(
+ id = "reporter",
+ reporter = reporter,
+ card_fun = function(card) card
+ )
+ updateSelectInput(session, "dataname", choices = isolate(datanames(data())))
+ output$dataset <- renderPrint({
+ req(input$dataname)
+ data()[[input$dataname]]
+ })
+ })
+ },
+ ui = function(id) {
+ ns <- NS(id)
+ sidebarLayout(
+ sidebarPanel(
+ teal.reporter::simple_reporter_ui(ns("reporter")),
+ selectInput(ns("dataname"), "Choose a dataset", choices = NULL)
+ ),
+ mainPanel(verbatimTextOutput(ns("dataset")))
+ )
+ }
+ )
+}
This updated module is now ready to be launched:
+
+app <- init(
+ data = teal_data(IRIS = iris, MTCARS = mtcars),
+ modules = example_module_with_reporting()
+)
+
+if (interactive()) shinyApp(app$ui, app$server)
A new piece of UI
has been added, and the buttons are
+clickable. The user can now add a card to the report and view it in the
+Report previewer
module but the preview is still empty
+since we have not instructed our module what to put on the card.
To add content to a card, we will utilize the public API exposed by
+the TealReportCard
class. The
+teal.reporter::simple_reporter_srv
module accepts the
+card_fun
argument that determines the appearance of the
+output from our custom module. ReportCard
and its
+derivatives allow the sequential addition of content according to the
+order of method calls. To explore the content, we can use the
+$get_content
method. For further details, refer to the
+documentation of TealReportCard
and
+teal.reporter::ReportCard
.
We will add simple text to the card by modifying the
+card_fun
argument passed to
+teal.reporter::simple_reporter_srv
. The function must
+return the card
object, otherwise errors may occur in
+teal
.
+custom_function <- function(card = teal.reporter::ReportCard$new()) {
+ card$append_text("This is content from a custom teal module!")
+ card
+}
+
+example_module_with_reporting <- function(label = "example teal module") {
+ module(
+ label = label,
+ server = function(id, data, reporter) {
+ moduleServer(id, function(input, output, session) {
+ teal.reporter::simple_reporter_srv(
+ id = "reporter",
+ reporter = reporter,
+ card_fun = custom_function
+ )
+ updateSelectInput(session, "dataname", choices = isolate(datanames(data())))
+ output$dataset <- renderPrint({
+ req(input$dataname)
+ data()[[input$dataname]]
+ })
+ })
+ },
+ ui = function(id) {
+ ns <- NS(id)
+ sidebarLayout(
+ sidebarPanel(
+ teal.reporter::simple_reporter_ui(ns("reporter")),
+ selectInput(ns("dataname"), "Choose a dataset", choices = NULL)
+ ),
+ mainPanel(verbatimTextOutput(ns("dataset")))
+ )
+ }
+ )
+}
+app <- init(
+ data = teal_data(IRIS = iris, MTCARS = mtcars),
+ modules = example_module_with_reporting()
+)
+
+if (interactive()) shinyApp(app$ui, app$server)
Now, an application user can see the text added by
+custom_function
in the Report previewer
+module.
teal.reporter
supports the addition of tables, charts,
+and more. For more information, explore the API of
+teal.reporter::ReportCard
to learn about the supported
+content types.
TealReportCard
+teal
exports the TealReportCard
class,
+which extends the teal.reporter::ReportCard
class and
+provides several convenient methods to facilitate working with
+teal
features like the filter panel or source code. For
+more details, refer to the documentation of
+TealReportCard
.
To support TealReportCard
, the function that is passed
+to teal.reporter::simple_reporter_srv
must define a default
+value for the card, as shown below:
+custom_function <- function(card = TealReportCard$new()) {
+ # ... some code ... #
+ card
+}
Without this definition, the API of TealReportCard
will
+not be available within the function.
In conclusion, we have demonstrated how to build a standard
+teal
app with code reproducibility and reporter
+functionalities. Note that the server function requires the
+filter_panel_api
argument so that the filter panel state
+can be added to the report.
In the final example, we have incorporated teal.code
+snippets. teal.code
is an R
library that
+offers utilities for storing code and associating it with an execution
+environment. This allows ReporterCard
to store the code
+necessary to generate the table along with the table itself. To learn
+more about teal.code
see the vignette
+qenv
in teal.code
.
##
+
+example_reporter_module <- function(label = "Example") {
+ module(
+ label = label,
+ server = function(id, data, reporter, filter_panel_api) {
+ with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelApi")
+ moduleServer(id, function(input, output, session) {
+ updateSelectInput(session, "dataname", choices = isolate(datanames(data())))
+ dat <- reactive(data()[[input$dataname]])
+ observe({
+ req(dat())
+ updateSliderInput(session, "nrow", max = nrow(dat()), value = floor(nrow(dat()) / 5))
+ })
+
+ table_q <- reactive({
+ req(input$dataname)
+ req(input$nrow)
+ within(
+ data(),
+ result <- head(dataset, nrows),
+ dataset = as.name(input$dataname),
+ nrows = input$nrow
+ )
+ })
+
+ output$table <- renderTable(table_q()[["result"]])
+
+ ### REPORTER
+ card_fun <- function(card = teal.reporter::ReportCard$new(), comment) {
+ card$set_name("Table Module")
+ card$append_text(paste("Selected dataset", input$dataname), "header2")
+ card$append_text("Selected Filters", "header3")
+ if (with_filter) {
+ card$append_text(filter_panel_api$get_filter_state(), "verbatim")
+ }
+ card$append_text("Encoding", "header3")
+ card$append_text(
+ yaml::as.yaml(
+ stats::setNames(
+ lapply(c("dataname", "nrow"), function(x) input[[x]]), c("dataname", "nrow")
+ )
+ ),
+ "verbatim"
+ )
+ card$append_text("Module Table", "header3")
+ card$append_table(table_q()[["result"]])
+ card$append_text("Show R Code", "header3")
+ card$append_text(teal.code::get_code(table_q()), "verbatim")
+ if (!comment == "") {
+ card$append_text("Comment", "header3")
+ card$append_text(comment)
+ }
+ card
+ }
+ teal.reporter::add_card_button_srv(
+ "addReportCard",
+ reporter = reporter,
+ card_fun = card_fun
+ )
+ teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
+ teal.reporter::reset_report_button_srv("resetButton", reporter)
+ ###
+ })
+ },
+ ui = function(id) {
+ ns <- NS(id)
+
+ sidebarLayout(
+ sidebarPanel(selectInput(ns("dataname"), "Choose a dataset", choices = NULL)),
+ mainPanel(
+ teal.reporter::simple_reporter_ui(ns("reporter")),
+ verbatimTextOutput(ns("dataset"))
+ )
+ )
+
+ sidebarLayout(
+ sidebarPanel(
+ div(
+ teal.reporter::add_card_button_ui(ns("addReportCard")),
+ teal.reporter::download_report_button_ui(ns("downloadButton")),
+ teal.reporter::reset_report_button_ui(ns("resetButton"))
+ ),
+ selectInput(ns("dataname"), "Choose a dataset", choices = NULL),
+ sliderInput(ns("nrow"), "Number of rows", min = 1, max = 1, value = 1, step = 1)
+ ),
+ mainPanel(tableOutput(ns("table")))
+ )
+ }
+ )
+}
+
+app <- init(
+ data = teal_data(AIR = airquality, IRIS = iris),
+ modules = list(
+ example_reporter_module(label = "with Reporter"),
+ example_module(label = "without Reporter")
+ ),
+ filter = teal_slices(teal_slice(dataname = "AIR", varname = "Temp", selected = c(72, 85))),
+ header = "Example teal app with reporter"
+)
+
+if (interactive()) shinyApp(app$ui, app$server)
There are two main actors in the teal
development:
teal
App Developerteal
Module Developerteal
app developer
++%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +graph LR + A[teal App Developer]--utilizes--> B[teal modules] + B--to create--> C[teal app] + D[app user]--uses--> C +style A fill:lightblue +style C fill:gold +style D fill:pink ++
The primary responsibility of a teal
app developer is to
+leverage the available building blocks of the teal
+framework to create a functional teal
app that analyses the
+data.
To expedite the app creation process, developers can take advantage
+of pre-existing teal
modules found in R
+packages like teal.modules.general
and
+teal.modules.clinical
.
These modules are designed with a focus on standardization and +versatility, making them suitable for a wide range of use cases.
+When developing a teal
app, the developer will select
+the most appropriate teal
modules and integrate them into
+the app’s interface to ensure seamless usability for end-users.
To learn more about the existing modules, visit teal.gallery
,
+which contains several demo applications and their source code.
teal
module developer
++%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +graph LR + A[Teal App Developer]--utilizes--> B[teal modules] + E[Teal Module Developer]--develops--> B + B--to create--> C[teal app] + D[app user]--uses--> C +style A fill:lightblue +style E fill:lightgreen +style D fill:pink +style C fill:gold ++
The main duty of a teal
module developer is to construct
+a compatible teal
module that can be utilized within the
+teal
framework.
Several factors influence the scope and requirements for building a
+teal
module.
When creating a reusable teal
module, it’s advisable to
+focus on making it as general and adaptable as feasible to maximize the
+possibilities of being re-used in the future. However, developers have
+the freedom to create a teal
module that is customized to
+suit the specific demands of a project.
Ultimately, one or more teal
modules are employed to
+construct a teal
app.
To learn more about creating custom modules follow the Tutorial on Creating a Custom +Module.
++%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +%%| fig-width: 7.5 +graph LR + subgraph Study B + A2[Study Teal App Developer]--utilizes--> B2[teal modules] + E2[Study Teal Module Developer]-.develops.-> B2 + B2--to create--> C2[study teal app] + D2[study app user]--uses--> C2 + end + E3[Teal Module Developer]--develops--> B + E3--develops-->B2 + subgraph Study A + A[Study Teal App Developer]--utilizes--> B[teal modules] + E[Study Teal Module Developer]-.develops.-> B + B--to create--> C[study teal app] + D[study app user]--uses--> C + end +style A fill:lightblue +style A2 fill:lightblue +style E fill:limegreen +style E2 fill:limegreen +style E3 fill:lightgreen +style D fill:pink +style D2 fill:pink +style C fill:gold +style C2 fill:gold ++
In a clinical trial study setting, a unique study
+teal
app developer is assigned to each study team
+and is accountable for developing a tailored teal
app for
+their respective study.
The study teal
app developer will
+initially leverage existing teal
modules from
+R
packages created by teal
module
+developers.
In cases where there is a need to create new modules tailored to the
+study, a study teal
module developer will
+need to be involved.
Upon completion, each study team will have their own designated
+teal
app tailored to their specific study.
+%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +sequenceDiagram; + autonumber + participant data + participant filters + participant filtered data + participant teal module + data->filters: gets + filters->>filtered data: becomes + filtered data->>teal module: sent to ++
The sequence diagram above illustrates the different stages that data
+goes through within the teal
framework, supported by the
+teal.slice
package:
teal
app;
+teal_data
before being
+passed to the app;teal_data
class
+facilitates reproducibility;teal
modules for analysis;
+teal_data
object so analysis
+code applied to the data is tracked (and can be used to reproduce
+the whole analysis);Whenever filters are added or removed, the data coming into modules
+is re-computed, providing the teal
module with new filtered
+data to conduct the required analysis.
vignettes/blueprint/filter_panel.Rmd
+ filter_panel.Rmd
The teal.slice
package provides teal
+applications with the filter panel, a powerful tool for
+exploring and analyzing data, and a key component of the
+teal
framework.
One of the great things about the filter panel is that it comes
+built-in with teal
, requiring no programming knowledge to
+use.
The filter panel provides a convenient way for users to subset their +data, simplifying the process of exploration and comprehension. +Moreover, users can activate or deactivate filter states interactively, +either individually or globally, using the filter panel.
++%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +sequenceDiagram + autonumber + data->teal.slice: processed by + teal.slice->>shiny inputs: creates + Note over teal.slice,shiny inputs: based on data type + shiny inputs->>reactive dataset: updates + reactive dataset->>teal modules: processed by ++
The filter panel creates subsets of data. Subsetting is achieved by
+creating filter states, each of which holds a logical predicate (filter
+condition) that is applied to single variables. These filter conditions
+are composed into a single expression, a call to a particular function
+(e.g. dplyr::filter
), and that expression is evaluated to
+create a filtered data subset.
The process is entirely interactive. Filter states can be created, +removed, and changed at will, however, the app developer may choose to +constrain or even restrict them.
+When a filter state is created, the filter panel generates a
+filter card with shiny
inputs appropriate to the
+type of the variable, e.g. range selectors for numeric columns and sets
+of checkboxes or drop-down menus for categorical ones.
As users interact with the filter cards, the subsetting complete +expression is updated and filtered data is recomputed.
+The filtered data is passed to teal
modules for
+downstream analysis. The subsetting expression is returned along with
+the data, ensuring an unbroken track record of the entire analysis.
+Signature of the data are also stored to ensure reproducible
+results.
Typically the data that is passed into a teal
+application is available before the app is run. However, this is not
+always true and in some cases the data will be built only after the app
+has started. A good example is pulling the data from an external
+repository, like a database, or uploading a file. Additional
+authentication may be required.
teal_data_module
+Preprocessing actions can be performed in-app using the
+teal_data_module
. Rather than passing a
+teal_data
object to the app, one may pass a
+shiny
module that returns a
+teal_data
object (wrapped in a reactive expression). This
+allows the app developer to include user actions data creation,
+fetching, and even pre-filtering modification.
A complete explanation of using the teal_data_module
can
+be found in this
+teal
vignette
vignettes/blueprint/index.Rmd
+ index.Rmd
Welcome to teal
Technical Blueprint documentation!
The purpose of this material is to aid new developer’s comprehension
+of the fundamental principles of the teal
framework. We
+will explore crucial teal
concepts such as data flow,
+actors, and filter panel, among others.
While this material will be presented at a high-level, we will direct +you to our vignettes for a more in-depth understanding.
+Our hope is that this resource will provide new developers with a
+strong grasp of teal
products, enabling them to contribute
+to code with confidence.
Reproducibility is paramount in the pharmaceutical industry. Accurate +and consistent results are essential to ensure high-quality research and +the safety of patients. By prioritizing reproducibility, researchers can +validate their methods, confirm their findings, and contribute to the +advancement of the field.
+The teal.code
package provides the qenv
+class that facilitates code reproducibility. Code is passed to a
+qenv
object, where is evaluated in a specific environment.
+qenv
also stores the code so that it can be retrieved on
+request.
The teal_data
class, which serves as the primary data
+interface for teal
applications, inherits this code
+tracking behavior from qenv
.
teal
application
+All teal
applications run on data provided in a
+teal_data
object. Data objects are stored and modified
+within the environment of the teal_data
object and all
+R
code used is tracked, which allows for the code to be
+evaluated and executed in the teal
application, and
+reproduced outside the teal
application. This includes data
+loading, preprocessing, filtering, transformations, and plotting,
+etc.
The teal_data
object makes it easy for users to
+reproduce and validate the results of their analyses.
Learn more about the use of teal_data
in the teal.data
+package vignettes.
Show R Code
and Reporter
+In both the teal.modules.clinical
and
+teal.modules.general
packages, you’ll find that most
+modules include a convenient Show R Code
button. When this
+button is clicked, a modal window appears, revealing the R
+code responsible for generating the module’s output. This functionality
+is achieved by inspecting the teal_data
object and
+retrieving code from it. With the Show R Code
button, users
+can easily copy and independently run the code to reproduce the analysis
+presented in the teal module.
The Reporter feature also leverages the teal_data
object
+in its operation. Much like the Show R Code
mechanism, the
+code displayed in a Reporter Card is extracted from the
+teal_data
object.
To learn more about the Reporter
feature, please visit
+the teal.reporter
+documentation.
Overall, qenv
from teal.code
and its child
+class, teal_data
, are powerful tools for ensuring code
+reproducibility and promoting high-quality research in the
+R
programming language.
WTM#|h>5C}FO)V{IVgecKh$e$3 z;xW@EH~%$4dAfFs)T49pVt7MSm6!s$*qEC)S3_VTU%!Y4BYNGrIFZNB+R2Y%Vz#67 z?}B{jw}oT)CT#$JfWoHmSU}|6*d@4S{j)ccK~J9SO_5IIkB*A+ZA+3PZRVG}|52N6 zvP0{Q+fSLE2Jtwpug^OCD)#2Feh&sCBctcn=Ca$3RG35@zi#L*whM)PVT7Ce2L|2% zE5?e^IgIhXbO}TNoA6s-`A$5+?aE3ifP^$mD$f?F(Ol4GY{WVrs@0LSLH{b5y6lac zH?dkbNJ&YF1M2w)2g^7(w@7k2ax1JIPNl8hJg1QMr+l*7n z;y>0DS%17C8^rt>LqUY6@VL0AxYsHG(i^xn6fIxS5@W2E-26d02*y20{uwcfDK!Na z@9e*Q5CZ3{#rDn1%fn@(lBZ7kQBhHmJ8%hE>{j*9$vHsFAsI}TA}-TF=5}S-6UB-P zV47p}eL90?wtfIc)d;)S{_0gtF@Z#uAPo2oRyH CU^u$(z_rWUa32Lwyw z&Zj#5p`jyAss0%oBA62`6M@S i>CM9s)aPB|;;g8iSV8Vh4<)V*OihI{@SfYX ze?M(_czAA65qUV>n+ls$j;Nw`VER5+U0=On!-lHmrG+Tk%+7tDZ;b%i+8}G};o(UH z3?c(DL5BLa`|P+cP{sV;zlmTXWR4UR0@{r_6z^e&qVA@-y){x&q5;Pu^Qws@q<+@T z-Q5@qgzWL*HwmGr!vn*wA1L~1WIoj`q(<$KHZt0M_wL>KN79_W819S)#i_A;NUq=r zo0pfDKNQ*M#SR4p2D-l4wpzc$aV )U8QNb)nsJ}FX)b7hEy8)qlAU*A2M$Lu* zc@B&r^CM|LTGES7ojOH0sM3R@n+by)S_Tm16c>-XclKTq=sjSc3`U!pn%cQf3fmAp zHt*V;t@Wp(%_=G?xzC=d?Na4*XM|U<>GSw_U`M8wNqr#G{O|+2w-}%}DQ|;c%NXT@ z-pd}0OiZ8aw;8^F@SZOBavLYBnDYiaD&Yl(TOgC?U94W^Jk`f0s9SJCRdws%xv89s z$ucv0qx}8bPtt`u5O$0LFaYkMUFyt7Xg{{%0KU9;|Nh${A)CqkZjqcnF?K#P3Rsu) zTUl9I%Cgu}5y~?uf2iuDlt?a4ODn~TG4V$!e!d(qN-u;uBcOirBo*1l+-IU6f%87U z`kjSc-1U*0VT$VKE<^8nGJ6*zJLK?fDDMPkWF^;kbl@V?P;=`*GuyH+9QWnoP87yc z$alt?s>A0( vaH%8J^OmgAdA;xXntOSd}M mEF hI8CrN^G~3|V-KB1W2aDl|Nd op`<1Z zuh;H>7Kp8V6IJHro{84x=2Pd+(SnQ;D+e7uD~S=a-PGFJ`8PN-b03uJ!`={SYg=1s zv$L}yBVC6R16N0BtD&Q#Fc|=d(($5Fc*wnb_Y!%AY+mTqG^`?Yz_-U #z1o&Il=^Ir0LZw89X$U*4KX}pzLEcd>$TN2NLOe?OGBHs_B^-8L-oV@835= zR6cCe%?L$IEMXfxDf#5yfk8o!Rnsrp*n~hh0VUmljzi3dhu0=W`@TmvIg&Dz4yK&z zG;+@RWBytomySIwHlK?AVKyuXR0!E$rQRzQ!_OusCm{f}D{d8+kU%Z{JUF<@#lZ=D4zY1)1ipiV#;;W#v~wN9EZ_gSS5R;>v_vppuz40$HMPRK zJaTe!hpjqk&fY(K5~I~tV4+4-H$(5GBa|v=RDe4TkZ}kFE3oWn7WjTv=2By_?-L$H z1%+xbRx;`D(v-ivky@#XJ!F2^={QQ|TNF49h5E?)O88Jit>NjkC`VyvVG*tuQ13=s z zIGQL$UuHqws;;hWZ^VDmJail0QDEE4lBHXC>h$T`eQGjCPAV!=LuIjFUUZ9-^wf =F-mj5H8+S{Wa^0>sDM|}W29)lGA>u=7S{2Zu>XCm(1^8;fsSy^71|1*-1 zXV)(YZL_MeaXl7CS6Qj^*bUx?uBXQAGo!E^_i%H6{*Y&KzY82= JdXxPQK!wb3GU69^xw3Qwma(o{j-^QIst*fF1_3Q`h zHp1jG0oo-<6rjV+Ejt!OoC^&SD;fLrcvyHi6<`RtkoUr;{(+H^G-rRALMC#luh1Sq z*jHD~4{l u*Z(Z&__v6P8?Gi_BV`F0iIS84{sazKO zJ2RH#>?%`8l^`LL9EqJuS}A(vXjcvgcpp)alarGNS`Jjo01CwBs&nx_{9SqHzp?;P z)G!UJ2#tpp?E%rI>Gf+_^!(4j3g~e67M@c$-96AXGPG4x=rL-y(XmZxZf(5WmCXiV zLONs_xV^ozv$~i}hEGxw*XcW~0gw*|=6`&do}H~HEg7Hr0^0Iq`g5?1x+u9CR{E#6 z=pv*ULp*=(`hye5`Sr_qW&wa?tIns@Fp7noN6!-+4s*K}lMzW9@}$8CKw>Q-0CynR z5%aR5qC&*;?_tTM88xC?jlFG>VL4_SjNUc?S?>haiqOTXf66I%`+2d$i7Ws-;jyxE za<%Y b1~y%Vr|6{a7Qj_}72s02+)Ak{y9 zwjB6^{$6+HK=~~oxyL9yKt>wLpl2dizimgD08xkQpnFb<``b(id|p>lQnFp#^`O_{ z4>=UrLCkdyJ%jZ&LESY`iff}3&GOB+d9EzY-4|nHWmQr&zXIFfmiNj+|A&0DO_*{z z5Gg2~0Gj#QWy+hv1I*w_7*={chbnXR+lT8_RVPxUg+;x+y#Zh!I9Hqo^rh$E2!);= z(V-L1D&fw!dL2#GJ7uX5w&Pc;;Li|(vU%#=DN{wx8(Ic#YrC>9)M6-JJ 4G13dh7SL$I|N;e}A$gQ`7(j&RIl;nJ|cr=s`vp-gzjWKfn_AvC(QALM5qz`5cP9 zKweQxjFmG8E4)dDG;UF+;eqnGK4}<5k+gmp=^!+V6NW1_2rxLH@1)f3&fiOT&{s%A zCqS(Z!g_s{lj(fQ8cqK9RDVuvlckAClE!{iW3{w%vM9So@Watl{)5b@Wa?v$qUE-w zDRZFB)V8(JqaDbCb)u0eu`Hm@9yD#DgL^7+{CE;33*fm+uk-D58jH}3#XC%~64#EB z#q;Oah}M{UfWSk#Hj|duubH6Y!9%l%%I^BVZ782^yoRFS;No&`-DZ}i> =KoBWSH bxwdte`*-1K9#;iAy^0w`ab6R7<;~l5{#CD=Q1`m8D>gb-S?jhl7xY zk6ORgeHa%f0FdAg^Kvj_FHF1rPA}YNGbmxu^)$(Vd~kor&MABy1iHGnx7T!TzmP9X zYGTO%bidb~L^Fq*%6j~&lGDqdfLiq1wxy~0B_wbFU;0Qb&)4n|`VP)Uq1(DOv9OFp zEqM1o5YEo{d*`-g&vPMQ7JHyC{tE}fxu2y!-$1YN6->n5(NR^5CgeYSxK)(*mRDkj zS`(x~p Z35DRk7f#~ t#olfOp0geaM~W z?=(1Gy?WZ#);22VUXv=+gYb<6l%e;?A_EbXt(BrWcEJ{A6!5`^4 OQ^K|}MJItFqd zKYtC(com?ffA0tR)N~c7CDIdJCH##&Xu9XMwV(WX0eGuj;UP-dg)|Aa7!0Dy){+0C zY2>vy)n94X?z%8HwPm0(4bg(Mv@h_DbX)itv~<3!MD@3wNA3sM?@73e5|8jUkRqOe ziHRUm%8^dcDD6Y}An1jZL%gs96vx*R#)PAxDh@ uuP(F5*!0Q!f3{&Tvqv9aggE0TkQgSpU?BN~p|^@)=Kwk!Lw4(?0{d^`XP7MKU^ zqGsx`&zmjD*1P?8^2O9Nl#Rhy^M@*?OESy~u^X#oj=TW{s>h~NRaMQfj{l!Lijlh$ z$6Y3yf_EHB28}Vcvf2kxs=e6G@MHP4V$G6*g2TiFAYH-Q#-<+857=(JSi4M=RVScV z9N4sN|NF%Ye~DEQ68HxLCXC|X;N-*rXgBsDFNruYSUD-_PK)zDPS=~sU)!#CPm~*` zKfGxVSm_%1l8G$F5*#t|rkrzA{c_M4$U7JVIY3;vuGFrfs(J%`iYSEO_Zbe#MLfb> zk_W?^)S(9a_!25*j8;1jN&H_u^j?}UB*+&PEH;;JN5DOChS)G{9?Zcl@GCZ=)xf$V zic>i3DVnLu70Kma2`i6KEEN5uO&wfOY3ovzVsBtLJ{NWw)b^A>)Js#0l$=N_(=s(p zZa3n$gq}{cVKTYUbf?G%!^sC}KnYi4(U<)l&qR)=+C0H?9r9i&wZc2kh3wMVHV-I`1m~cSxe`M&a-1-PpFsBHHgnT* bpu~tMgSkko `Fr><|QMp;con zVktnFhafSt6Lkl-+A6g;z51d1I3HPZ$gwH hcaIInvTWn1|7as_QzK@M%$8J&49cQ8i zs<#<>TnB+5GAXRA;j4Rux8TG7a&E=_UO~9|Ztx}uS;V*|Mhq5QN-dWJffne{M1THJ zV8Jl{KK-Wm;uj8*GQ;l)%saA!AkRmS9#II0g_V$J{)XMv)pdZN5h4r&KmH1*Py^;x zV 8yh>?`{Ec87Au#&+Yv28OeV402hz_KC!{Z*8kDnu&DDWze;yk0g@I)> zJy1 Ml2JWdxp5|Y?QF>2?4P;0SbFA_jfJ7n^6Uae~ zYg*dV_Vx!+AvOY>u=@&yV`QKv4Pr&hLQh1Yz#0!lec?QOm=S3Cc1}(X(0a!uB2~x& z+k?;(l=-dq#WoPj>FMbzBI`qGNdyQ0_ZbM^zIq7aD%4Eqi$tS@zUT)4^B6P}#=t2! z;6(QUBG|{qPru|#XvJ3gII$~=PBObBCD~E3NF9T;2X6Dot 3WTn980 zFvRLZZ^Tz41BS+M`3@&Ci+kCM6jG9tcY%%IBfb$43}DI*!>@J_rHgYF_8nw=A`%iM zSM2IHf2>A6wxjerz=>4OlCpw#H$t$5P%Q@#8N|0Zz-6Hit)rmrJ%SK;xjlI!!ij;< zBM5iHKDbp}d<=0af|%-a?(l(1VYd-Q6tz1!C50?s5 +hs`9z8ld^{KO)9u zHDa*Fk>|UCzCs2II!Ccx|7lbWXb_|~0&twY3t^RNAm_nQ6nj0D50VR!v_e<{kRR^P zkt`4-5Q@Eviys6UqKH6-DAe6d2BWkzk%%IQyriY24fkUhn7sTzLcgFNo&-17JpSR+ zrzGrqm>Hwph5OcRVGqvDJ&5M^q(&@2UWIIyHYBuiZ9W|(ilx-j3 Y}8lgcIi%_KmT=X zvXuLxPCSH|WxW&ntF5E68++{nvS^7-8TYWf;7SmMbBJd@Dk*WK;00yO*O_p(@4NkO zG(g}z5(90ZiH^Jxx=`*AH%>3yxM{j8xwp`&OH&)N7&SnzIc%K}qQ{-bRp4j0y=r+o z=S4a(x{sEFX@~NO6BM)qt>Lp@AoCz^6s(!0tKncOV@iWJWX?biCsQ-)hHh5pf(dX! z2n4ZT`F$(DpzD$qFZSKY%IY6dg4iqKyoKuIr%pc zRhfZ-VKr(bNdi}{EFUNK;(?0!Rj|i%^Yd?HWeI{K+ybfG$7WfmR_WzQ9KiegvSrqQ zE}tZB*1}Y!2@(_}=}eEn(aemqZxVN+92p%t>=)8)KuwAF3W!dF_PUxP{-ch8WPoIl zZexLXRan!eX$Yl_SkV*;+}e{6U8okX9C$!1oKMADkhH%1E_E~JCDrta%*+OZpGu}w z#7hLN*o}fmOgjVD&uhzvNCO3IhTHilkgGs|5a1)0jGfsRHlf|c&mB5+=m&|N1Avl5 z7zu)5kk)c?C;ClG!uikvm+SLh@hn?eULc)F^QktKo!yjhOOSl5R#Vsykm7?D?R!v6 zFX9qNn8O@T><*rTDwwUv`)R*+E`?A7kYg1nxIP<$0w7+~00;jo-z84w0@}HcYL3$} zg#Y m@ z5F#e7iWMG0m1r!STwHC?uEhU*jgVJV9PE(lh=HgA4LsMRk(QWfgwi7AP3}gGyD_TA zzARFgAbJqyh9D}m+u_#uAcXJ!sTK`Tn0CimTm3=l_k+$XaG{hj!SnYH_nFb_SiAqe zryj~=phLdR>qOP`>AA`kHfV+?Va5;-#N&@6WCvp7(`oEJSCmyk6lI9pY{;Zn0mRX> zv)=&@|971lT!-2|-{$*8Y#Op+x(hdvwG5B-CUl2?-%|~+`AXzt(eJU2%x&i$iU(kk zlug%c`j=RsriNYAG>9cD%!PZELzc}$cIl~h-l~4D1wmpn!fwEI!et4AS{G-1CIum- zoA_c?ZS88nVu1uhnVIeLk>;EX$8oxWls!~tB5lRJI7L~$-!%g%j#QJAZyrjJSUL;~ zL(H$h#sn;7eq3+}<{$BDkTD7cDk5$^^5ZbeID_zhO>0CxM$>e_jU$@~GhL6U()=PP zCl_YWT?wCWaJ+H_c+BHEkft2?0jJ?Gdq&*@52_2Tk?d^|8sI_A}}hSqDG}kvV-j z@%eLYJV%Bg5OT(vb4A>0Tj>RK^4B2Mbn@cGUBp=a4~ m5bbS>Vc z5-Al{@w+|yWs*Zsd9ULUU%iIP3t6}ZQzT^DBZ6Zx|7iv$S`rD23g43vh|WnoBI2Y1 z=J^qGcCr_ayG#cT#Uwh~=L_ ui4cHZ0tP+iKl>46K9U_)zt7XF4g8Vp+o$>^ zTTy7#aa*;)aOR8)xUFSI`^Yvn;9=lbQas`9B;nC{uo-0EB9($UkMNqA@gV`lm zYW=prySj}n9=k?)i%Li%9!+lvBAY9sj?ldP0MUqkg(Sg@h^xE5<$iLN{d@MTL2)6< zESV?-^2A-IPhd&$XPsuX5Otm21>H2;dAs^+8CluSi2ss?0R6bOWZz1fRaf?<2aibV z8^@?Z px*#q1breCYa9RI5cRG)4k6FVY z%_+ =;=E=P%PzSWN!7%iKPAia`5UuV_c`Q zly#REe<>rIMGoK~Sqcn@UqD`6kvavJ!!NlZz{M0C-3<1T`0;dT1;Rx{jYery?@wxF zn#EjL)hk#tWPB9Slz6BcUqIYuV3%qVi9%bUM>}o8u_X{cBeU85)L0-LnKfwW)Thr3 z;oQZ^Q>Ru@c7f1vuA)a;lr+dSfO%!VyR8sjxKk5uxl_n^jm#Q2V5(w~mN#uqrAGeu zb6V Bo#~D|>!1&?5)+C^=bX?0j>5Uh~01F$+=eWpT o^s30T~VC_?ck-)PYb%(bn%`&1}}njEF{Kp-`Z9G2OY9acWG|xHV!|;&`x$ z#z#xD_I!(XJYYoDePuf+1EZr)TvXq~>S)eNbG`x1?VpPKCk}bXfAS1*rqMfnQ5fLM z5y%2FJ3dCy5V)%zktm2|7hdPj%*+Uz@a^6EuO9=uRlj_>5s6N6QYzQ1g&D^3PFB1B zjqn@U`B_8F%SHN&H!JjQX|PFXjF7&p-kL*byorp&Be3z@;$k^0h_)9lcBIij%IVTW z@|_mQYqY;o3X8;fT-<4x29<^2b!3TWM%z}yk1=bwczHob*rdBIa_QaM(&nF|YnBir zc!V;6qg`aSuo20bv9oR_za6BDUWj(tDJ2|rmJ*uPz9?TJSLx*CRna#D(sfcsW(|5B zd1K KUC83u|l>PXfQmSg*)ldI$1q06M;3hrGbr)|-m9N_Ba_7Vv0pV%BP#*Gy^ zI54nlJuU0oooeULht<{BE8vI+Vhi#hEjSF7^=eAksAi2yW=B5C!poMH2rx#hc^t`s z>vr=CCX|UH45hCGksy$xmk86<;WWvm);NozDO;sQGaQYgqikhi$ +n%L& zEbrN~2y~1c>RO75fiP2*kc8*PVI2^vJx7jckcbb}uAprPI{8P2hPcs{@5aXRVQoZ# z`KY9;|3vKDa$Fpk95x;~NMnjQz8fDe$a^j>48Tnh20?vaUq$ nEm+mivd%K5N!}SeG0=A#{{_AQ3l9!0SjwnddMz3&->K-e&SfF^3KwP z7!v`2=e<@>4_si!t604F@29I&GM`pdxZ_OOSnrEsS9kaEnU0_KPx%d Q4Xz?;0Ou`Yi-=E^{2a`r?86Qp1de^c;gz@LB*aCT>B@hi*%4ZS7j0PH)DR@l3E` zW?tSjMQ%aX%o&q*)!P~Jy2$r~_>HkqRjG~oXh~8<3sA{g9~^O1p=B4} z3$l;+#DTti$ay$#Wcn)gFL_gD&y{N>4qtAgj&GpAoGGfllHOtY@3>La{$n^aNwo|3 zjFFyROG}Gt7db0w2Kt`)KfYM9K-5@5L#IY`I~Utug7hd&M2TqO?`{m~ogCJ#eC*jB zvsCxq (;H4{2k7GM`K09pj~y}NP&9Pe>f5Uc_PTX z^%W=?)#4m~s-GzMPhob-nR~_ve-UR6>M@Zz2sVd3aX8~4O8LJ7m^cp#CFF2k>-{5} zC}H>RnV*+v@N!YBUwHzKcM(kUa$DkBB2=Qwv#`DZN<-P-ccB%qg%WoEejs@SbMxBj zYO4MF_lucLbY!L#Pd3l6oiVb0KuMiQNX?%3{6J-Vffkd}>89K-Y4Gv8?fC4@?zE7P z%1RQ PMi0H?Mb zK1T08!^FyJeRuomQ1%cauHYY{Q_8FXmL;)7n!s%o!clR^XA21h;n>D`Rn=AW)#yW1 zCr0*%{F_!g0i4Ww_2AeR&Kvj!P3=D12ILc`DG+JNb}m7sqN1P@7{P?W#C{za;o{|$ zOZ%2IXY!=EB8k!D)0%@9R-P(d7$V0)`hKRoyiu`6DWTccMJ>BOMiNJJjPK-C#hKi$ zm^yD@*l~|hb6sObppb ^z`%qe&h~GdtqU%tJi~}kF%b&02R>Rd?D3bdh6}Fu5|Ymss>LNlffKf z+>?~&wcp>WAx-TQkb;Fxd3(*y&&P+NlpuK_vnNT2nUV1#Ha9GD8F~2)lt )KP5aizk1t}Q~k(~MXh^mAGRZZj=$j5v$a-hj+x$ f72>kki>C zDQTeA8spg$^WFB&?9O*-n|n!h*{+)XG|#|LFY?Y<=zj0dzS|B@cs$P$6BSiJgEj+> zX-9m=!O^k(Q*`K{wnpC1yUbDYN3KPhaufPRK^h~;eveGY1I3h6&d!H#Z{e^FpVg8> zs0I1#MnnrNhyHFPf*~=MAj0vpDTd^NxS&mpK1gG#6(v7ef(ao)S!DALhkEl}8ER%i z#*ZFZtFlw!9s8l0;2f|0RG);>{lgn!dde9Xu#;FXIrd&s^6w`bh?VI=!=zW?j+9*B zg-nm82?jCmy)w1Zaeub!D5}=|mdpf%(O|z^gj?b|o}OlpV?T%O`t-->tkymV45FiN zO9BK6fQ{7IJ==8}X#Z4>L3t!?lI9m=5C3oe$cg{y0LzhKzBkCbRDqvFfr51&cbT z0lM(D`|N1ag%rqvF(gzTJ8zdM?E4?itvp$$8sNW|Z4G`jfy!Fr|20YbK=D@*+kl5p eq-OoQ;vcv^+HoYJ2S06uq9A)tCi~RI8~+c2xjDc9 literal 0 HcmV?d00001 diff --git a/v0.15.1/articles/blueprint/intro.html b/v0.15.1/articles/blueprint/intro.html new file mode 100644 index 0000000000..4e2fa3b877 --- /dev/null +++ b/v0.15.1/articles/blueprint/intro.html @@ -0,0 +1,215 @@ + + + + + + + + + Introduction • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/blueprint/module_encapsulation.html b/v0.15.1/articles/blueprint/module_encapsulation.html new file mode 100644 index 0000000000..34fb6d5efb --- /dev/null +++ b/v0.15.1/articles/blueprint/module_encapsulation.html @@ -0,0 +1,180 @@ + + + + + + + + +++ + + + ++ + + + ++
teal
is an interactive data exploration framework based +on Shiny, designed primarily to analyze CDISC clinical trial data.A Shiny Application created with
+teal
offers users the +ability to:+
+- Import data from external sources;
+- Dynamically filter data for analysis;
+- Generate reproducible code for future analysis;
+- Create and download reports of analysis results (for analysis +modules that support reporting).
+Moreover, the
+teal
framework provides application +developers with a wide range of customizable standard analysis modules +to integrate into their applications, along with a logging framework +that facilitates debugging. Additionally, advanced users of the +framework can develop new analysis modules and easily integrate them +into anyteal
application.The
+teal
framework’s functionality draws heavily from +the following packages:+
++ ++ + + + +R package +Description ++ ++ teal
+ +shiny
-based interactive exploration +framework for analyzing data+ ++ teal.widgets
+ +shiny
UI components used within +teal
++ ++ teal.data
provides the data structure used in all + +teal
applications+ ++ teal.slice
provides the filter panel to allow dynamic filtering of +data ++ ++ teal.code
provides a mechanism for tracking code to reproduce an +analysis ++ ++ teal.logger
standardizes logging within +teal
+framework+ + ++ teal.reporter
allows +teal
applications to generate +reportsAlthough these packages are mentioned in the material, we strongly +recommend visiting their vignettes to learn more about them.
+Learn on how to make your first
+teal
application here!Module Encapsulation • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/blueprint/product_map.html b/v0.15.1/articles/blueprint/product_map.html new file mode 100644 index 0000000000..13e59c2f97 --- /dev/null +++ b/v0.15.1/articles/blueprint/product_map.html @@ -0,0 +1,222 @@ + + + + + + + + +++ + + + ++ ++ + + +Module Encapsulation
+NEST +CoreDev
+ + + Source:vignettes/blueprint/module_encapsulation.Rmd
++module_encapsulation.Rmd
++Introduction +
+The
+teal
framework leverages theshiny
+module concept to enable encapsulation of analytical actions in +teal
modules, while maintaining seamless communication +between the modules and the application.++Benefits +
+By implementing the modular app technique from the shiny module into +the creation of the
+teal
module, several benefits are +realized:+
+- +
Streamlined maintenance
+The development of theteal
module becomes more manageable, +as it can function independently from theteal
framework. +This separation allows developers to maintain the module with ease. This +approach has been successfully applied inR
packages +dedicated toteal
module development, such as +teal.modules.general
and +teal.modules.clinical
.- +
Enhanced focus on output
teal
module developers can concentrate solely on refining +parameters or encoding, and output aspects (such as data summarization +and visualization) without the need to concern themselves with the +intricacies of theteal
framework. When developed +correctly, the module seamlessly integrates with +teal
.- +
Facilitated collaboration
teal
module development becomes an accessible entry point +for developers interested in collaborating. This approach encourages +user collaboration for the improvement ofteal
modules, as +developers gain a deeper understanding of the mechanics of the +teal
framework.Product Map • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/bootstrap-themes-in-teal.html b/v0.15.1/articles/bootstrap-themes-in-teal.html new file mode 100644 index 0000000000..3c09b9450b --- /dev/null +++ b/v0.15.1/articles/bootstrap-themes-in-teal.html @@ -0,0 +1,384 @@ + + + + + + + + +++ + + + ++ + + + + ++%% This is a mermaid diagram, if you see this the plot failed to render. Sorry. +flowchart RL +teal +subgraph features + direction LR + teal.data + teal.slice + teal.code + teal.logger + teal.widgets +end +subgraph modules + direction RL + teal.modules.general + teal.modules.clinical + teal.osprey + teal.goshawk + teal.modules.hermes +end +teal--has-->features +features--builds-->modules +modules--creates-->teal +subgraph modules + teal.modules.general + teal.modules.clinical + teal.osprey + teal.goshawk + teal.modules.hermes +end +subgraph calculations + direction RL + tern + osprey + goshawk + hermes +end +tern--supports-->teal.modules.clinical +osprey--supports-->teal.osprey +goshawk--supports-->teal.goshawk +hermes--supports-->teal.modules.hermes +style teal fill:lightblue +style features fill:lightgreen +style modules fill:pink +++
teal
is a modular framework that relies on a suite of +related packages, as illustrated in the above diagram, to provide a wide +range of functionalities.+
teal
’s primary function is to create web app for +analyzing clinical trial data but it has a multitude of +features distributed across various packages.Developers can selectively leverage these packages, such as +
+teal.widgets
,teal.code
, and +teal.logger
, to buildteal
+modules for ateal
app. This approach gives the developers +the tools that speed up their work and avoid re-implementing existing +logic and UI elements.The
+teal
modules utilize various packages such as +tern
,osprey
, andgoshawk
to +perform calculations and analyses. These packages provide +support to theteal
modules by performing +all computations while the modules only have to focus on how to wrap the +input options and the output.Once developed, new and existing modules can be integrated into +
+ +teal
to create a functional +teal
app.Bootstrap Themes in teal • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/creating-custom-modules.html b/v0.15.1/articles/creating-custom-modules.html new file mode 100644 index 0000000000..5baa3a6f69 --- /dev/null +++ b/v0.15.1/articles/creating-custom-modules.html @@ -0,0 +1,340 @@ + + + + + + + + +++ + + + ++ ++ + + +Bootstrap Themes in teal
+NEST +CoreDev
+ + + Source:vignettes/bootstrap-themes-in-teal.Rmd
++bootstrap-themes-in-teal.Rmd
++Introduction +
+We offer an easy application of a custom Bootstrap theme in a +
+teal
app.teal
uses thebslib
+R
package which provides tools for customizing Bootstrap +themes, including those ofshiny
apps.++ +Usage +
++
teal
app developers can specify custom Bootstrap themes +by setting theteal.bs_theme
R
option, which +has to be set tobslib::bs_theme
object. The +bslib::bs_theme(...)
function creates a Bootstrap theme +object, where one specifies the (major) Bootstrap version (default or +one of 3, 4, or 5). Optionally one can choose a +bootswatch
theme and customize the +app CSS with functions likebslib::bs_add_rules
. +Please read more about custom themes in the +bslib
getting started vignette. The +teal.bs_theme
R
option has to be specified at +the top of the code script.Please install
+bslib
package before you run the code +below.+++
+teal.bs_theme
R
option ++options("teal.bs_theme" = bslib::bs_theme("Custom Options")) + +####################### +# teal::init() app code +#######################
++Bootstrap version and themes +
+The best and recommended ways to explore the +Bootstrap themes are to use +
+bslib::run_with_themer(shinyApp(app$ui, app$server))
or +bslib::bs_theme_preview()
, both of which offer an +interactive explore mode (not supported for Bootstrap 3). The +bslib::bs_theme_preview()
is recommended when the end user +does not have anyshiny
app yet. When you already have a +shiny
app and you want to test different Bootstrap themes +(andCSS
styling) then +bslib::run_with_themer(shinyApp(app$ui, app$server))
is +recommended.Available Bootstrap versions could be checked with +
+bslib::versions()
and Bootstrap themes +(bootswatch
) with +bslib::bootswatch_themes(version = "5")
.+# bslib::versions() +# bslib::bootswatch_themes(version = "5") +options("teal.bs_theme" = bslib::bs_theme(version = "5", bootswatch = "lux") +# or +options("teal.bs_theme" = bslib::bs_theme_update(bslib::bs_theme(version = "5"), bootswatch = "lux"))
++Default Bootstrap theme +
+When using the default
+bslib
theme for any version (3, 4 +or 5), its styling might not be as expected. Please run the interactive +themer (recommended) or apply a custom theme to explore all the theme +options. In many scenarios updating only the theme might not be +enough and e.g. font color and other specifications should be updated +too.+# instead of +options("teal.bs_theme" = bslib::bs_theme(version = "5")) +# try non-default themes +options("teal.bs_theme" = bslib::bs_theme(version = "5", bootswatch = "THEME NAME". ...)) +# or run the app inside bslib::run_with_themer
++Reset the Bootstrap theme +
+Please use the
+options("teal.bs_theme" = NULL)
call to +return to the defaultshiny
Bootstrap forteal
+apps.++Theme not updated +
+One reason the theme is not updated could be that the web browser +caches the previous one, especially when different themes are run one +after another. Please, use the
+Cmd+Shift+R
(Mac) or +Ctrl+F5
(Windows) to hard refresh the webpage.++Custom
+teal
CSS
+The most important HTML tags in
+teal
have a specific id +or class, so they can be directly styled. The +bslib::bs_add_rules
function could be used around the +bslib::bs_theme
object to apply customCSS
+rules.+library(magrittr) +options("teal.bs_theme" = bslib::bs_theme(version = "5") %>% bslib::bs_add_rules("Anything understood by sass::as_sass()"))
Other
+bslib::bs_add_*
family functions could be used to +specify low-level Bootstrap elements.++Bootstrap NULL vs Bootstrap 3 +
+It is important to note that the statements +
+options("teal.bs_theme" = NULL)
and +options("teal.bs_theme" = bslib::bs_theme(version = "3")
+are not equivalent as thebslib
approximation of the +defaultshiny
theme for Bootstrap version 3 can introduce +some discrepancies. One important difference is that when using +bslib::bs_theme(version = "3", bootswatch = "THEME NAME")
+one can apply the custom Bootstrap theme. Another one is that the usage +ofbslib::bs_theme(version = "3")
requires the installation +of the latestshinyWidgets
package from the main branch, +see below.+# Downloading the newest shinyWidgets +# needed only when bslib::bs_theme(version = "3", ...) is used +remotes::install_github("https://github.com/dreamRs/shinyWidgets@main")
++Regular
+shiny::fluidPage
+If you want to update the theme in a regular +
+shiny::fluidPage
-like app, you do not need the +teal.bs_theme
option. Simply provide the +bslib::bs_theme
directly: +shiny::fluidPage(theme = bslib::bs_theme(...), ...)
.++Interactive theming guide +
+In this section we provide a step-by-step guide to customizing a +
+teal
application theme interactively with +bslib::run_with_themer()
. We recommend starting with a +simple case and once you are satisfied, verifying with your full +application. To that end we will use theteal
application +below. For this example we assume that we want to use Bootstrap 5. To +start, we launch the app with +bslib::run_with_themer(app$ui, app$server)
instead of +shiny::shinyApp
.++options("teal.bs_theme" = bslib::bs_theme(version = "5")) + +library(teal) + +app <- init( + data = teal_data(IRIS = iris), # nolint + filter = teal_slices(teal_slice("IRIS", "Sepal.Length", selected = c(5, 7))), + modules = modules(example_module(), example_module()), + header = "My first teal application" +) + +bslib::run_with_themer(shinyApp(app$ui, app$server))
This gives us the following.
+ +Note the
+Theme Customizer
section on the right hand +side. This was added bybslib
and is how we customize our +theme.++Set overall app theme +
+Instead of starting from scratch, we want to start with a
+ +Bootswatch
theme. Let us +select the Minty theme in the “Overall theme” drop-down.+
bslib
has updated ourCSS
styles to use our +new theme, including thecustomizer
theme. Additionally, if +we look at ourR
console, we will see++#### Update your bs_theme() R code with: ##### +bs_theme_update(theme, bootswatch = "minty")
This is a helpful guide that provides code to update our theme. For +
+teal
applications we don’t actually use +bs_theme_update
and opt forbs_theme
instead. +However, the printed code will still be helpful.++Customize a
+bootswatch
theme +Our base theme (Minty) is close to what we want but let’s make a few +modifications. To start, we will increase the base font size. To do +this, we choose the “Fonts” section of the
+ +customizer
theme +and then set a value in the “Base font size” input. We use 1.25 here, +which means all our fonts will be increased by a factor of 1.25. If we +check theR
console, we will seebslib
has +printed +bs_theme_update(theme, font_scale = 1.25, bootswatch = "minty")
, +which now includes our font size adjustment.Finally, suppose we do not want borders to be rounded. In our +
+ +customizer
theme, we can go to “Options” and then uncheck +the “Rounded corners” box.As expected, our corners are no longer rounded. If we look at our +
+R
console, we will now see +bs_theme_update(theme, font_scale = 1.25,
enable-rounded= FALSE, bootswatch = "minty")
.++Apply the customized theme +
+Once our customization is complete, we will apply the changes to our +application. To do this, we use the option
+teal.bs_theme
+like before but this time we will expand on our +bslib::bs_theme
call to include our changes. Luckily, the +arguments that were printed to theR
console when running +our app in the themer can be plugged right in.++options( + "teal.bs_theme" = bslib::bs_theme( + version = "5", + font_scale = 1.25, + `enable-rounded` = FALSE, + bootswatch = "minty" + ) +) + +library(teal) + +app <- init( + data = teal_data(IRIS = iris), + filter = teal_slices(teal_slice("IRIS", "Sepal.Length", selected = c(5, 7))), + modules = modules(example_module(), example_module()) +) + +shinyApp(app$ui, app$server)
Now the application has our custom theme applied.
+ +Please note the interactive themer only contains the most commonly +applied options. For more customization options, review the +
+bslib
documentation.Creating Custom Modules • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/data-as-shiny-module.html b/v0.15.1/articles/data-as-shiny-module.html new file mode 100644 index 0000000000..56e743d325 --- /dev/null +++ b/v0.15.1/articles/data-as-shiny-module.html @@ -0,0 +1,304 @@ + + + + + + + + +++ + + + ++ ++ + + +Creating Custom Modules
+NEST +CoreDev
+ + + Source:vignettes/creating-custom-modules.Rmd
++creating-custom-modules.Rmd
++Introduction +
+The
+teal
framework provides a large catalog of +plug-in-ready analysis modules to be incorporated intoteal
+applications. However, it is also possible to create your own modules +using themodule
function.++Components of a module +
+++UI function +
+This function contains the UI required for the module. It should be a +function with at least the argument
+id
. See the server +section below for more details.++Server function +
+This function contains the
+shiny
server logic for the +module and should be of the form:++function( + id, + data, # optional; use if module needs access to application data + filter_panel_api, # optional; use if module needs access to filter panel; see teal.slice + reporter, # optional; use if module supports reporting; see reporting vignette + ...) { + moduleServer(id, function(input, output, session) { + # module code here + }) +}
The data that arrives in the module is a
+teal_data
+object, the data container used throughout theteal
+application.teal_data
is passed to theinit
+function when building the application and, after filtering by the +filter panel, it is passed to modules, wrapped in a reactive expression. +Theteal_data
class allows modules to track the +R
code that they execute so that module outputs can be +reproduced. See theteal.data
package for a detailed +explanation.++Example modules +
+++Viewing data +
+Here is a minimal module that allows the user to select and view one +dataset at a time. By default, filtering is enabled for all datasets. +Note that dataset choices are specified by the
+datanames
+property of theteal_data
container.++library(teal) + +example_module <- function(label = "example teal module") { + checkmate::assert_string(label) + + module( + label = label, + server = function(id, data) { + checkmate::assert_class(data, "reactive") + checkmate::assert_class(isolate(data()), "teal_data") + + moduleServer(id, function(input, output, session) { + updateSelectInput(session, "dataname", choices = isolate(datanames(data()))) + output$dataset <- renderPrint({ + req(input$dataname) + data()[[input$dataname]] + }) + }) + }, + ui = function(id) { + ns <- NS(id) + sidebarLayout( + sidebarPanel(selectInput(ns("dataname"), "Choose a dataset", choices = NULL)), + mainPanel(verbatimTextOutput(ns("dataset"))) + ) + } + ) +}
++Interacting with data and viewing code +
+The example below allows the user to interact with the data to create +a simple visualization. In addition, it prints the code that can be used +to reproduce that visualization.
+++library(teal) + +# ui function for the module +# allows for selecting dataset and one of its numeric variables +ui_histogram_example <- function(id) { + ns <- NS(id) + sidebarLayout( + sidebarPanel( + selectInput(ns("datasets"), "select dataset", choices = NULL), + selectInput(ns("numerics"), "select numeric variable", choices = NULL) + ), + mainPanel( + plotOutput(ns("plot")), + verbatimTextOutput(ns("code")) + ), + ) +} + +# server function for the module +# presents datasets and numeric variables for selection +# displays a histogram of the selected variable +# displays code to reproduce the histogram +srv_histogram_example <- function(id, data) { + checkmate::assert_class(data, "reactive") + checkmate::assert_class(isolate(data()), "teal_data") + + moduleServer(id, function(input, output, session) { + # update dataset and variable choices + # each selection stored in separate reactive expression + updateSelectInput(inputId = "datasets", choices = isolate(datanames(data()))) + observe({ + req(dataset()) + nums <- vapply(data()[[dataset()]], is.numeric, logical(1L)) + updateSelectInput(inputId = "numerics", choices = names(nums[nums])) + }) + dataset <- reactive(input$datasets) + selected <- reactive(input$numerics) + + # add plot code + plot_code_q <- reactive({ + validate(need(length(dataset()) == 1L, "Please select a dataset")) + validate(need(length(selected()) == 1L, "Please select a variable")) + req(selected() %in% names(data()[[dataset()]])) + + # evaluate plotting expression within data + # inject input values into plotting expression + within( + data(), + p <- hist(dataset[, selected], las = 1), + dataset = as.name(dataset()), selected = selected() + ) + }) + + # view plot + output$plot <- renderPlot({ + plot_code_q()[["p"]] + }) + + # view code + output$code <- renderPrint({ + plot_code_q() %>% + get_code() %>% + cat() + }) + }) +} + +# function that creates module instance to use in `teal` app +tm_histogram_example <- function(label) { + module( + label = label, + server = srv_histogram_example, + ui = ui_histogram_example, + datanames = "all" + ) +}
This module is ready to be used in a
+teal
app.+ ++app <- init( + data = teal_data(IRIS = iris, NPK = npk), + modules = tm_histogram_example(label = "Histogram Module"), + header = "Simple app with custom histogram module" +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
++Adding reporting to a module +
+Refer to this +vignette to read about adding support for reporting in your +
+teal
module.++Using standard widgets in your custom module +
+The
+teal.widgets
+package provides various widgets which can be leveraged to quickly +create standard elements in your custom module.Data as shiny Module • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/filter-panel.html b/v0.15.1/articles/filter-panel.html new file mode 100644 index 0000000000..d61c85281f --- /dev/null +++ b/v0.15.1/articles/filter-panel.html @@ -0,0 +1,282 @@ + + + + + + + + +++ + + + ++ ++ + + +Data as shiny Module
+NEST +CoreDev
+ + + Source:vignettes/data-as-shiny-module.Rmd
++data-as-shiny-module.Rmd
++Introduction +
+Proper functioning of any
+teal
application requires the +presence of ateal_data
object. Typically, a +teal_data
object created in the global environment will be +passed to thedata
argument ininit
. This +teal_data
object should contain all elements necessary for +successful execution of the application’s modules.In some scenarios, however, application developers may opt to +postpone some data operations until the application runtime. This can be +done by passing a special
+shiny
module to the +data
argument. Theteal_data_module
function +is used to build such a module from the following components:+
+- a UI function; accepts only one argument,
+id
; defines +user interface elements for the data module- a server function: accepts only one argument,
+id
; +defines server logic for the data module, including data creation; must +return a reactive expression containing ateal_data
+object+
teal
will run this module when the application starts +and the resultingteal_data
object that will be used +throughout allteal
(analytic) modules.++Creating data in-app +
+One case for postponing data operations is datasets that are dynamic, +frequently updated. Such data cannot be created once and kept in the +global environment. Using
+ +teal_data_module
enables creating +a dataset from scratch every time the user starts the application.++data_module <- teal_data_module( + ui = function(id) div(), + server = function(id) { + moduleServer(id, function(input, output, session) { + reactive({ + data <- within( + teal_data(), + { + dataset1 <- iris + dataset2 <- mtcars + } + ) + datanames(data) <- c("dataset1", "dataset2") # optional + data + }) + }) + } +) + + +app <- init( + data = data_module, + modules = example_module() +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
See
+?qenv
for a detailed explanation of how to use +thewithin
method.++Modification of data in-app +
+Another reason to postpone data operations is to involve the +application user in the preprocessing stage. An initial, constant form +of the data can be created in the global environment and then modified +once the app starts.
+The following example illustrates how
+teal_data_module
+can be utilized to subset data based on the user inputs:++data <- within(teal_data(), { + dataset1 <- iris + dataset2 <- mtcars +}) +datanames(data) <- c("dataset1", "dataset2") + +data_module <- teal_data_module( + ui = function(id) { + ns <- NS(id) + div( + selectInput(ns("species"), "Select species to keep", + choices = unique(iris$Species), multiple = TRUE + ), + actionButton(ns("submit"), "Submit") + ) + }, + server = function(id) { + moduleServer(id, function(input, output, session) { + eventReactive(input$submit, { + data_modified <- within( + data, + dataset1 <- subset(dataset1, Species %in% selected), + selected = input$species + ) + data_modified + }) + }) + } +) + +app <- init( + data = data_module, + modules = example_module() +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
Note that running preprocessing code in a module as opposed to the +global environment will increase app loading times. It is recommended to +keep the constant code in the global environment and to move only the +dynamic parts to a data module.
+++WARNING +
+When using
+teal_data_module
to modify a pre-existing +teal_data
object, it is crucial that the server function +and the data object are defined in the same environment, otherwise the +server function will not be able to access the data object. This means +server functions defined in packages cannot be used.++Extending existing
+teal_data_modules
+The server logic of a
+teal_data_module
can be modified +before it is used in an app, using thewithin
function. +This allows theteal_data
object that is created in the +teal_data_module
to be processed further.In the previous example,
+data_module
takes a predefined +teal_data
object and allows the app user to select a +subset. The following example modifiesdata_module
so that +new columns are added once the data is retrieved.++data_module_2 <- within( + data_module, + { + # Create new column with Ratio of Sepal.Width and Petal.Width + dataset1$Ratio.Sepal.Petal.Width <- round(dataset1$Sepal.Width / dataset1$Petal.Width, digits = 2L) + # Create new column that converts Miles per Galon to Liter per 100 Km + dataset2$lp100km <- round(dataset2$mpg * 0.42514371, digits = 2L) + } +) + +app <- init( + data = data_module_2, + modules = example_module() +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
Filter Panel • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/getting-started-with-teal.html b/v0.15.1/articles/getting-started-with-teal.html new file mode 100644 index 0000000000..1da4178f2f --- /dev/null +++ b/v0.15.1/articles/getting-started-with-teal.html @@ -0,0 +1,348 @@ + + + + + + + + +++ + + + ++ + + + ++++
+teal
apps with the filter panel +The filter panel is an integral part of all
+teal
+applications and is included on the right side. Based on the selections +made in the filter panel, filter expressions are executed before passing +data toteal
modules. The technical details of the filter +panel are extensively described inteal.slice
+documentation.By default,
+init
initializes the filter panel without +any active filters but allows the user to add filters on any column. To +start ateal
application with predefined filters, one must +specify thefilter
argument. In the following example four +filters are specified using theteal_slice
function and +wrapped together withteal_slices
.++library(teal) + +app <- init( + data = teal_data(IRIS = iris, CARS = mtcars), + modules = example_module(), + filter = teal_slices( + teal_slice(dataname = "IRIS", varname = "Sepal.Length"), + teal_slice(dataname = "IRIS", varname = "Species", selected = "setosa"), + teal_slice(dataname = "CARS", varname = "mpg", selected = c(20, Inf)), + teal_slice(dataname = "CARS", expr = "qsec < 20", title = "1/4 mile under 20 sec", id = "qsec_20") + ) +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
++Extending
+teal.slice
+++Filter panel respective to
+teal_module
+Each
+teal_module
(see?module
) object +contains thedatanames
attribute that determines which data +sets are to be sent to that module. The filter panel will display only +those data sets and hide the rest when this module is active.++library(teal) + +app <- init( + data = teal_data(IRIS = iris, CARS = mtcars), + modules = modules( + example_module(label = "all datasets"), + example_module(label = "IRIS only", datanames = "IRIS"), + example_module(label = "CARS only", datanames = "CARS"), + example_module(label = "no filter panel", datanames = NULL) + ) +) +if (interactive()) { + shinyApp(app$ui, app$server) +}
++Global and module specific filter panel +
++
teal
contains theteal_slices
function that +extends the originalteal_slices
found in +teal.slice
by adding two arguments: +module_specific
andmapping
. By default +init
initializes the app with a “global” filter panel, +where all modules use the same filters. Setting +module_specific = TRUE
switches to a “module-specific” +filter panel, where each module can have a different set of filters +active at any time. It is still possible to set global filters that will +be shared among modules.One possible scenario is depicted in the figure below:
++
+ +- +
+filter 1
is shared by all modules- +
+filter 2
is shared bymodule 1
and +module 3
+- +
+filter 3
is used only bymodule 2
+- +
+filter 4
is used only bymodule 1
+- +
+filter 5
andfilter 6
are not active in +any of the modulesTo achieve the described setup, one must set the +
+module_specific
argument toTRUE
and use the +mapping
argument to match filters to modules. +mapping
takes a named list where element names correspond +to module labels, and elements are vectors ofteal_slice
+id
s applied to that module at startup. +teal_slice
s listed the element called +"global_filters"
will be applied to all modules.For a detailed explanation about the filter states, see this +
+teal.slice
vignette.++library(teal) + +app <- init( + data = teal_data(mtcars = mtcars), + modules = modules( + example_module(label = "module 1"), + example_module(label = "module 2"), + example_module(label = "module 3"), + example_module(label = "module 4") + ), + filter = teal_slices( + # filters created with id + teal_slice(dataname = "mtcars", varname = "mpg", id = "filter 1"), + teal_slice(dataname = "mtcars", varname = "cyl", id = "filter 2"), + teal_slice(dataname = "mtcars", varname = "disp", id = "filter 3"), + teal_slice(dataname = "mtcars", varname = "hp", id = "filter 4"), + teal_slice(dataname = "mtcars", varname = "drat", id = "filter 5"), + teal_slice(dataname = "mtcars", varname = "wt", id = "filter 6"), + # module-specific filtering enabled + module_specific = TRUE, + # filters mapped to modules + mapping = list( + "module 1" = c("filter 2", "filter 4"), + "module 2" = "filter 3", + "module 3" = "filter 2", + global_filters = "filter 1" + ) + ) +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
Getting Started with teal • teal + + + + + + + + + + + Skip to contents + + ++ + + + ++ + + + + + + diff --git a/v0.15.1/articles/images/bs-corners.png b/v0.15.1/articles/images/bs-corners.png new file mode 100644 index 0000000000000000000000000000000000000000..8d3527d063c1a90e66f176564fe74ee2667df017 GIT binary patch literal 133220 zcmb@ubySp1_&*Gi(ui~kC@Ce++ + + + ++ ++ + + +Getting Started with teal
+NEST +CoreDev
+ + + Source:vignettes/getting-started-with-teal.Rmd
++getting-started-with-teal.Rmd
++Introduction +
++
teal
is a shiny-based interactive exploration framework +for analyzing data, with particular emphasis on CDISC clinical trial +data.teal
applications allow their users to:+
+- “Pull” in data from external data sources
+- Dynamically filter of data to be used in the analyses
+- Generate reproducible code to regenerate the on-screen analyses
+- Create and download reports containing results of analyses (for +analysis modules which support reporting)
+In addition, the
+teal
framework provides application +developers with:+
+- A large suite of custom-made standard analysis modules to be +included in applications
+- A logging framework to facilitate debugging of applications
+More advanced users of the framework can also create new analysis +modules which can be added into any
+teal
applications.++Your first
+teal
application: +This simple
+teal
application takes theiris
+andmtcars
datasets and displays their contents:+ ++library(teal) + +app <- init( + data = teal_data(IRIS = iris, MTCARS = mtcars), + modules = modules( + example_module("Module 1"), + example_module("Module 2") + ), + filter = teal_slices( + teal_slice(dataname = "IRIS", varname = "Species", selected = "setosa") + ), + title = build_app_title(title = "My first teal app"), + header = h3("My first teal application"), + footer = div(a("Powered by teal", href = "https://insightsengineering.github.io/teal/latest-tag/")) +) + +if (interactive()) { + shinyApp(app$ui, app$server) +}
Hovering the image shows the
+ +teal
application +generated by this code.+
+Every
+teal
application is composed of the following +elements, all of which can be controlled by the app developer by passing +arguments to theinit
function:+
+- +Application Title +(browser’s tab title): is the title of the application.
+- +Application Header and Footer +(the top and the bottom of the app): any content to be placed +at the top and bottom of the application.
+- +Teal Modules (tabs under +the header): tab for each module included in the application. +
++
+- In the example code: there are two modules named “Module 1” and +“Module 2”.
+- +Module Content (panel on +the middle): the outputs of the currently active module.
+- +Filter Panel (panel on the +right hand side): for filtering the data to be passed into all +
+teal
modules. ++
+- In the example code: the filter panel is being initialized with a +filter for the
+Species
variable in theiris
+dataset.++Creating your own applications +
+The key function to use to create your
+teal
application +isinit
, which requires two mandatory arguments: +data
andmodules
. There are other optional +arguments forinit
, which can be used to customize the +application. Please refer to the documentation forinit
for +further details.++Application data +
+The
+data
argument in theinit
function +specifies the data used in your application. All datasets which are +about to be used inteal
application must be passed through +teal_data
object. It is also possible to specify +relationships between the datasets using thejoin_keys
+argument but in this case the datasets are not related. See this vignette for +details. If data is not available and has to be pulled from a remote +source,init
must receive ateal_data_module
+that specifies how to obtain the desired datasets and put them into a +teal_data
object. See this vignette for details.In order to use CDISC clinical trial data in a
+teal
+application thecdisc_data
function is used instead. Custom +SDTM
standards can be handled withteal_data
+andjoin_keys
.For further details, we recommend exploring the
+teal.data
+package documentation.++Modules +
+The
+modules
argument toinit
consists of a +list ofteal
modules (which can be wrapped together using +the functionmodules
). Coreteal
developers +have created several universalteal
modules that can be +useful in anyteal
application. To learn how to create your +own modules, please explore Creating Custom Modules +vignette. To use our predefined modules, see the references below +for links to these modules.++Defining filters +
+The optional
+filter
argument ininit
allows +you to initialize the application with predefined filters. For further +details see Filter Panel vignette .++Reporting +
+If any of the
+modules
in yourteal
+application support reporting (seeteal.reporter
+for more details), users of your application can add the outputs of the +modules to a report. This report can then be downloaded and a special +Report Previewer module will be added to your application as an +additional tab, where users can view and configure their reports before +downloading them. See more details in this vignette.++Reproducible code +
++
teal
hands over data with reproducible code to every +module included in the application. Note thatteal
does not +display the code, that is the modules’ responsibility. For example, the +example_module
function used above shows the code in the +main panel together with other outputs. For more details see this vignette.++Where to go next +
+To learn more about the
+teal
framework we recommend +first exploring some of the available analysis modules.For example see:
++
+- general +analysis modules
+- clinical +trial reporting modules
+- modules +for analyzing
+MultiAssayExperiment
objectsFor a demo of
+teal
apps see:+
+- The +gallery of sample apps based on teal
+- A +catalog of Tables, Listings and Graphs
+- A +catalog of Biomarker Analysis Templates of Tables And Graphs
+The
+teal
framework relies on a set of supporting +packages whose documentation provides more in-depth information. The +packages which are of most interest when defining +teal
applications are:+
+- +
+teal.data
: +defining data forteal
application.- +
+teal.slice
: +defining data filtering before passing intoteal
+modules.UwP2q4nz5xsf YS(n%nMO4PW%JFNX N!@ue<684#-{8gpD zi+ASHUv-Wh@!TT*sw0+JqR6oQ=Xd=Cy=-zD_RI+{hJ`_$T*UvCc+y@LxrrGYT(684 zj;-&LugvFai>pNpA>f`^onp34;~s)W1BcD4>g!@Yo|EZ=t`c^*$7JE hcDMJANmAC5GlF%MT6o~cvRYz+!dvK+VjLmB?{K~0!+Ran} zB>#00@A93ekSh>!RF^5_v}WPpoK!G9#XZBh9L()T%Jk$3O`~W7qcX(a#+0epY^q#$ z>swx+G<0sC!tS*oV5)V80|#p%(DT-V{MHLW+#PPo#(hEWvHGRmwAg_8zn7Jt+?O`m zLs9ekm7H8%wfn(n@f^j#1jh{LQgX=6CfZTQt94@SLwt#44Xzw(JydarzL{$Cq47gj zV@o@Q?}Fvjq5=elwQFvMFD1jib36jS8<6|2OgK-FmF|p)>W7iAsASrt(>N6>i3cs3 z!54h*Q3%~*@{Z}rT2yp$)WH#Bn)`DFYc_2I%sy0p%%-W tyxg8l!w6Z5gH0Nkm(+0xnCxBH+uPt$lj-xyZnB^}&*6-#Wk8 z!E;Z6dR?031P{{-0SiIbuX_`IWpUMqqc$z)Cuugi>kOoHmnfBDXF_jE`$S3NB+qap zgfv-m{+Nf&Y&jaK@9bDpIy0k9D}0dzuH2M9rCa7wmGNU!u>Y7gB>qTZ*ZDlFYph~T zsNVjIMha(QPVX+pEy#Z#D!USnHOXu5@8eH@-{<(=kMCOXk1bR`p;b!WTKTxP;I;ON zmnQo^%o8VQLx?SjvJE^ 3Sn{4E_S_@s6TJ0o`B+9o?EXq^;1%WMUC-vF z&Xe{V3gMd6`NpQ@YvuD3f5>{^a(nP(na=ujLG5Iys8LTPnSaQ5QJ#mC_!1URE?h`L z@0#P gx`CPx?uF5})Kf@4HOgG0^+1q2ta%*tRc{C`gD!TFOViwb zN&EhquJdaOy$sku`43U2nT?W-hDD!j4`(H~$jQZ&d7te&6Y!)dIjdw;>Q^=2I;0{l zQSrQXImP(%MN|i`JW#W}+Of_38}L4wZ7OCWyS|T_XSc$U>35cLZunjYXrkMO&wX=F zn@MGg7X#d!IsF=UG)(*o$1QGUPndhP?C_fhU{xGj75ByQYcAz$rXTsm)u;U?4Oct5 z6w~^UkItSWSm) Z$`hr$eWWgLEu~&4L z`6%8E^zncY+l>u0>DH^+kfxx91})N>8mAYY;jy$Pq`Np0ht-C&-CXODJIa^c?ALO% zIa55y*@g4PdoMK_pSr>&$;|uaa>5iYpz2K`aKRSQ{LOMM!Q05=Tlw?dM`d=b;|K2( zaf=Pw2VLt}|HDbOC=>1p(zsrPoSbrxhvbu`6azxHs0IdWe>T-7>Pmf#z;VAC9F{~z z`R29`y0Sdo`Sbb&mtpI50Ih{reZY@1fceo}h7DCtL$<+OWn5fVl|i`F=eWHVqpTt` zi`2)@{#fL}*PyyyOW2B>m|hACqm5GU)jLGNK&SmtY?hD_aY!KHEG}x&x2v&3uEn?y zc0I?WKMqeYjz_XX+Iqp~UL~0cchFXf#WF>cia7OIpE*TjA}HpLNK-&7ZlaualWdTv z$1s)sSqGB r@5qG-(;jdA(qkfsm18H0 zir!=XmFZMQ%JOpgpdij2LuG%7EqFni!Y4}5am}S%)NVGqLF`t;r%Luai!G4|1zML} z*)n2An|1nyB}jXfWbEOmF@x@l$HK7D2MYrI)B8vKkI&$O-%s;)!WiLt?fBZo8Gnpp zwuXFk>VE1@+@%>)q3G1_0eXEvDx~r&LO }8@i~)i! |HlSa=7QZoZN&a&0<`4 z%Zm%irMy3?faR-WCBIu9y%l#bfRvYa7rsm(x|}5g(h{qge`$875pmzg P7ZCAQK9 zu^@MSVbK-wUnJ3n6dqdN3p~w6?or#={g;1{LGUCILxj`UZzsJ#Buo!2wLTw=iujBF z)!Cc|-Dk`%THDF){(C~4$N{f%5%U+O@4xuFQ+a3pa$tSt6(a1cfNyN8)6_XlFL4L` zT E(amMNHh7#Ctlr9TV4EQd9GFOHC;>G!*;BHtI6H z>A1-or={R#<2};_*x=|c`-I7viU%ou?-1f@!)3zk`vslPesmxkH|b{1hk#BR;rB?8 zM#sYH8W?z)rNo@j!=w-YgOL(9>S}G>)ua>F7T-)^161ZgKkfHZhWX$Z-ew)9UGlVC z^=}rr9s?3@PnJJ@QBB$XKi-K*ekdd!;q0rGB@__3xSU>G3Lu5fscTYBX~89e6f1-p z^-ZvqQ0+GE#9w*fQ
-*k%*GD6Ya*ot{=t#Hvr-GG zyND!9u!uW0sWC-E9&b-f*jWH;>K&iNM{1QEV6hr3(h~BzJ9RwrOE{IQ)ljDkv?b AA=3)!Bx;d>V(aAPM*eZe zh-&5=8?o%6M+x;r=u&^R0m5W}+6UpqiE=K~i%=!4n0}50pnJbKMsO&R06% zNV>ZR_MM8BNr-7~c9>i4noq8?9RdLjQ^ZyEbWEA_tQHBAFdu#6n&>kei+kndqERY9 zPlR@GfFG)}EoFB_S_p1(rAjhBkS@I7H1)X6ysHke65RCi%40_uvo145skVO0gQ&?v z-N9mqSq7z&yuJ3Ss_#6b4KtkFEQS9w5E%2dr3pR7RWcxlbktbmb$FU|;$cvi>3{$p zk4FzXIHZz^KZ820KJ$2BaP&EA$4-0C;uaY}FRw6XL(;VZZ&t*gvt|0-NwU@jmwpen z9%c1d6u?~S5<$~76I&qxHx=13d9k)s$S915W3BMzvnXkKI@_+eYI=rt0J??F@dUI7 zB{a%wa_$}-;vC6nO}((AW*IJk_ALtpRA`~J>{DYMWJ^m8TifXubF >6{zl-eAX^nAn;U5V>Q?CQG=IqjM_8hzP{;`9OTpY%pM&^2zy4)-1L zlltN~rVF3X>Ik*8xr??O{Ge-TUYMAQa)B+P8g(6nxYzoWh%-u&T|HIlOFUt?cMD4c zpX(6 NUUhI6ITxtOtH-49bIu&f)??d+i$s z{=$@g5_BxIzILgLt*kkUmW%{dr?&ftdv_`&YVc%Mef1?%l~UBwzDq#c->)P5j@j6s zybL&8I^1QBQY?yH0$;8%CHfa6UOk)r0daxqNqXQ%qr}=K%+Ev|D}&UuOoQ0OnnWD& zsWA_JWCdIouo_=A(olPdLZ=U&Sw;{l`K|*9tk5t!uTEK0*^kvOX7v*N8RGUbDp+s* zb7rku4KiMP0FO|)ax{nI7N&G^3a$%=z=LEXR{84X13JSQHHgy3YQ~mx{_41HR|}X2 zbf{8Gritxm5$c2&*F}V?*_jdS2P%hD0yDd*bDbLrp~r-6qfq-F&qb&G7FS7igP`1k zP;>R{SFIm14^MgI6`<2|@nsW+iGr`7o`g7|Utl8a8g2Xy-3TgSbfX`Fs%h6R5S|*R zhJG7QMkO$fraaAZ?`kzCoj5L)0tF|d3RHEbQ&+kERtEfH^>q+cXVfI`Xv1@|f@6cW z;~o6k$*BkBgi3i(=V3NYie@}AOTH7;P~;H$wVDQIlNWJw2Bo#qj$gZdarW K>IWKbU&h-)yYXh)_%D{a=|D(9QTvk P=fotx_NTvvOOHS9u6Lzz-Cb%mZHPo_kVW`(=PO)8CWYJ~cv|v!*5c&$pe1mc zOW&?R33l2bGw)VswrRmixFj*z3CXEEzO^%LTC_2SZqQDucn;I^G%(j&;;3hXoDH@Y zCL_NKvBz$q7-g*hM=WYRH|RVFCt~L*nV0LKtK`DiQc-GJKC*20QNAaZX+8os*=qTF z8me-szX>)ImZ^G0y;m);+O@J+N%GDeo%Bnus >=t5&?ymkQ`O4Gufd^M5mo{X z{eclnE6Tk62c-)ai~EO7z}PuBCN0-33|O|hy1IywtnLEm?C>8xQCZ;J!(wA(RU+6z z-%4WC19Eb?k!V!e<-@dlrhrPhys|}JoJgv6nEeFP$S+0h;v!71x8i>^>63PCmNSr& zW=n%sZ886epCfaN%t;xHQk+V{9Vv~stWe2%DywPARi;%wUb3Qlmd4bHzQQ~4v#@N1 zRoW7R;6-XxKRNFEx#c+@%Fp;|{CSi*L&5A5ir_oXIuu-AWxAjU3ertX#dx6Dt%>CC zuC%M!ixu7+Jj;k*3~1?M)fuik@=&TaU&$iE81F%2)u}I#D7NpTPnw_3U;Ch^WbR_< zdYs8IU)h#iKizp>luW|iO;)RyOVh{c^RTB@?9C6*>S7^Y(z1^Yh4*we)so~y`NpCs zfv~Xf;qh_M7Yp@bzne=fZVo}V6v^N}_^4cVKZW hQ_HsBeSVj?0f1!W9-ngykZE3YHz zexd`v{d}@@H`-wY41J*`tW>G6O)xQOFUVwfH@NinEUi9A!oAZFH%DMM*u2wJT2I9F=X5}ra*8&j6Fb{{ Xp~n^n!LhnonpvOdRmM(|9V86`9QNebTNvfFX6w@HMR0*rX%5uwuoeuul$ zBu3JtV3DkSud+ER(t_ithnh4)(n&g49zE<=_pV^11ezOpyKoHM;p$RxeYLg&yi%x- z=`Ncw{o-BL!3qfMOQmYHAc>aX{O5_6o^AfzsnC(!wUfuXQaS;p9D=613$pXEtlJs^ zPzy`?t>m`Igk>AUrwzC|(8W8I9qf(VPGZz*M~2BYGzPw6rp%g_bfwi=)y*FG2bB}L zY1Sn9d-GnAySb!;v!F <3Z+sSu=8S8> 8HgO6cn_wxml>f zobbi@@AX119bwO3ydymP|H^Gn^B4U6?8d58z5hawbLJ>7lPN#!@E8o*q^Z*^QqI^g zxY1P3Wc?41`hV}5%JTB3+)*zc!(iVp^79!({OaX7U&&3pKHjGV<>o%{@boN6_+n9$ zYE|`eLz)6!kGGHG0E^7y{%t4Kz3H8i%^^p68jzzo) BN}LL$5SIpN7q5{ ig- z#eH+>Wsrf?ad_h ZY~WtQsYQ(EwE*E|@{Kr*_{u(tBp2 zk5Y|&s}RfXoHXq!*(pTkzO}$&uQ-JRjf^CP^&=sX_GGvb2kfN6*)b~ySa&5-8u$IX zE26r{Wcnqiw45A41dmRR-ktTM+C=kzce4%Ge#?oZ=v3D`{t%b?SF=u}=Y@)-(B`mX2H$_Ey&BSgbg9Lt{pO<-(uHxDK z35%HiL(A~47wu~%S*@t sO+#IW_@ zUa?^~VvCb{Q{ym&-%vfF8C?yM;HE=d6xmmEgiE OOy#dC0=D z-W@?gA?o&cZEbCXuWnpVXO7urjH^CqG6lgIp ^Z-o1EdMAIJ``dsYWYY2BNx z3?>0;S##=?6&Q@IJtebNseM!DQ(;@O`?U?B4RKb(cFsrC%Ghz*4(8Cds_Zwg&XrnL ztJJFqJTZ0&EdW?9K@40yvS!U1q=m=LQaZWfu}rJxzb_D{3IK)X?!^ZFR^edCuL*d* z!gd3el$6+z4>IoTeJ#XAI%CQ)o6PPlK8fnkL2u`8n6O)-35&5Wz^FGtc|nK7AT_=& zlZI~-EO?0TM759Tsef;tc>Z6=v6K*Gn1$`c$HzCxm5xDt9LbgD>+3tYnLM!cy2ie! z-mEpq1E$>|M;G?1Gp9-ZL)(2*D}cEDZ(*^a{da(PZu&^^OlESZwfs~Hlz!YSo($Vn za>Z{EzwZ)_S`Fu-sB`O5n)r@{K7KwtH);jLprK?cn_~l_Un5g{X&x>9-SY@M!Z%|_ zHMI^a&7=vQ5=P$GM4J!Z^L&DY$RWJo#js7A@Y%ULO4;=Pj^gg`Q6Q^qL}cD|Yn`|^ z@nG%hRrf$aZ|>|fdhuRXL{2z8Fn(Z2K4tzWLyd4<@TOoBM@N2Lp+P)41=Rh;(&nzg zT~2wESt{9=I&sZh6~2GCz`^#&VXH+ke^#(U>z|_9(HkEL=G*?9bn-8DAY~5NXVTCZ zK@sW6)N5|z0+4?>(ND3{goS4Gdz{GYNC&dc5&knPWBT)cdB&O^sp*?c@mF~6e>{u| z6A5cJyqR|VP^kv{OmT-{BdkBVaL)c2x&+jj^nsiq**;88{>y )FRC zRM|p61)z|X`SIno@s@jy81iwv9*z2 ~#J;T;6&XU&MsR%=mvNm~<< NAb2Y1zg{Fe0v+F_jR?7XTrBLaDr;;u3tFJx@DjAlaUuC z7JRD0-iQuSmC2+dOuh5|>M-+nP%NJ1NiW@Hi^s$^2M5Q{fZ4r)OA+5TF!(tqH3><9 z#64pE+Mig=%gTyvWMs5!@g(i>_T;^oFM^noRAP7TcG{_WJVF!w_{!X0n(a=oxA|^G z*QhaPV$2!eN41a#coA(Fox36rglZ(8)t>ckE@)EjvU}n6C5EdUa<+!tx6~JP;mYse zz(z9*TUX0)dh0v-(O(Rcf$)kev)5f-aBQkwbU!MlPxc06=8+*oqd9fZ;)+pdC&HL_ z;23?B#La)W_w-&u7h2+Fv3Wzy$N|p43i%8ziG3q&*Ir@+5e ^ zM-Lv#m4#)tRWaFT!$FAEb3|&Ov*p03-{xkeLcnE>F DSU7x#cBjG?OW(C)IS4c^@jAb^@g8yyt50!k!}Kuj z1beN6s+0TX3;GOG=Nrh)<}_1BhL#4V6G`a8LiG1P$9=}{Ly^Qg@Mocmz?L`Zv81`z z=fptmDG~pvUBPNo*PZ058CQczb_@b%JdL_B9F%v;P%X4CIC{>a8=Wp^hg$HFQ~3-3 zaHdZE!XJTK=eTEtZtLENzJU5dA-CO^*NC?`62iVj^mMa9{#NAqHHHuOqu*n2(|smS zdAUNeKtc#MHGfLCGlj8dpV`%0Yg-pyT1vq(;ukDQHxomcWasPb%(C>QC4`z;^81d( z&C7JDkOi?YL4tj)v*yzk6?ls_YEB0Qo`d(@oTB}S`uI~)iNRI^4^VD{^5`r<>wJpI z`j3$#w{&%FTNZ@NHB5$hRN#(#&qQK$n2Fg)cKB0L#*6S(1XhEY?+^T1{Mg=eBHf8z z3^)<6S-WUZX9Y^SSC?b)f$62#q6ER2yla5Y5!*FjgrJ;sBx@;ZbJ-VUZYi-dW{F}Z zFWgz^vUNw&-(X}Ra&y;-?MlLnYMY~#n368|6a#cPOuXk+dBcSPQcN13Y~u@qrr013 z!UY6B9#yX{_<6W;{7CgupN*x*l*3Q#Y|kHf5DnV^9RrFF4_YVtu1=RK54Ebp4;Pj8 zD}`=Rek7~=E*VKWQ<0b6aRh8|);!=Bu#z#fc|9D`jOXzOMD7;H2QMyB&@2#q@ 5910&EXr2%f}yEjb!izF~lci3FQ(f5qPxr?!Hy0gsPmStu<4h{}$} z%wU0Sve1$l-CWy#!TZ5owOU=GKpAg?zOg~gvi-8kwWz2@XrpUoNEMHzzr2u*6HVmj z1fc?&nmA*u?g6a{AsbxWENf-O{q@0%H=q8~QTV3IorKjZD{PGujs)ep(LDfy{zo<{ zH4TsZ)_MS=3zbGpSj~Qi xsJ=nHVj|KKmHDZOXFtwT3=u7d@hy7ryq3YrgHuKk;T#}0KRV`w(x{zG zo}0tjp^+ni^{%-L=L)^|$teXbP;_pMM~V)S_Te!yyiSLU=bp=c6cjtSIgtRNgp>$h zUE!*QNKvi4nxcuS8X7%nlRg~Wkr_!h%ejn7{C*?BM?y@!*!3S5vu3{uafNN$y?2?C zDrGmliG8a|8Y*Oawh;M^rk0_iB#(Cj;qwQ1u!(QQfN2Dre{ 4j8VCNj+bMUJfK|CxqA;u &Xl{7^)rZ9B1SE+;Pd*mKeeWy9Subl^&mj1LnGvbu8M6u8oBeMT3$DL)>VR^5^ zUxj`ClcVyihU}3%mjBrPl;Tw^HUKv<#Yi^Yz_Os+pd!U#lmDs@qNL9?2f#OIUW>%p zy!BO8GxKlG$&`rn&7ZVQ$ox2G$WB6Rhw@o;PPie`LvqadQpDL(vR| s792V|D2Po9C$G=lADItXdpWhOm7}8PMy!G#lxKg!0FhUo4*qXF>)v41 z7w58Gx<#o@KkM^Qg2A!wTbkz>$RmgYof;GhSS`Ij9>k{TRX!td<8$27!&q4+HUGSa z xu$TdK?=%$C6R&27HJufR|s7xe8G1Mhl`=uV=;| zZkN01lAkzML#Y?LuuMPoG-{#ut;Q1Usd_TeD_HEe-tKB?GGgB}_q~p_hR 86l28+jBfRo5 zxJ$vzJ_jP@hm%aJtRve`*Lu*qZiwc1 qv6Wlx1(y7hAD=I^-4IIj|_Q;xh&EST8qVac!h+|3;k$ z_m?yhVeitbvqg!7DyjaUFY(lIq+QyXV7TXdJ)dhZyWF05^DU#gVPxfS{^(?h7+Z#| zhTB-mtK_XUEM_Gjc4yz4^o4i3e5Ce-gl=U(jTn4{Bg9zLfkyOweoHT5*VS?;NaP}~ zv>c_6d%Hk2+5xr+I?RpTalFC);i@D|Kt7!2*0Sfg(an6lonH@adwac8pGTqk#-rk? zQ-2o)>1z|0r8*b1D7!P&Q$dYJG6~Y@crMsfZv)9C5FXH>Xi2S*XqP&^^H$7DUu V3K*vw;7B;%jp$TifH!rI)EgKWL%WI`=)P-_okT25;&mUU*|jFV+Cm~ zB9Rm-nEio=Op -B1T`y z@EgDQ$^KU_QLQP7xtZC7LW4*ZW|Sb>`t~b%U@b@QjCe@PaKRC5W*1ZOioh=%C}?)L zVRsas2n#u}&RLCl`N;VNcF%@d0k0BQnx%bT5Z<~}wBK_INACRt)~%DnZw>SDw)|Up zI|O=V!P> ~dqU}kwN2^Pq_nwR#+f!Fe 6O=PcXOpnu2c*( zQu1GV9-Y?$tzv*Z*|O^?VmrV}vwZN}ZNwJ^kSG|@MmFZQ%h41iFd;pQS~NllN~a2( zcF55l!QFat+!87TvFbm+s1o0dH7=e)C?a?po%i>$GLBkbnYt*3Pi_wnBkJ8D)Gxf6 z1a_=cRf$?!S|+|&JkcHWW?`RDS2=%jlA2it`ug&Dvvx#BfQelFK}af6bm%CeiE`LC zwsJbN2QXL<_hPJXybA!E^0vb1kqL}fn)eMLQXbRTNP{ELcuY5w724SYHE{)0+H!zN z@)P&YQ*!#Y%tNuGc0zJ%2F{;szrUP=nELW`w9}-eS#dg0F^D_5tBM+MiiC+{IA;;f z;1`J0VJUK%fR=76^`@wchv7YA0*gFC<+xs$K&fyYO0KQK)pk%^nyg{xlElkOONPB? z`mSobRCzT1wO-eOZyng>pY7|yxjsdz>rO$|d=?I2L3DeviPK@Z=31zy#{JR~(D*EG z;*@!G2F6^pCM=Ha0$&BW^Sa=XAs-+2RXi1AZY*e~q}ANfCF}I&LxM>mM@OuMInFy- z9C(#Um#%xDoq9pr;bu2`lj^;oppX5ZzJZ4KM0533!Cv-F^(UX}@?B (2P1+^U8c6pSuQGSvyy3UrVz8>aW zh~D(#(vd;m7Y+=t>ac@{3AS0{$-H4Brr~^@`~||+C&LAG8_?o7+$h?VlgUJj)|t#u z{fhpvh_%xhKMAbo _E=HQr1L)NO$mHgnY&+Z=%?rNVQJDp~uc*# r9{~C@cn3j@?WgB#GXK_cbMa z`!v=@cnPgxglig0n%wjAi_(TH$7sAx$&OUgki@%ts<3Piy*z#N{0nD~s; P=M8$ej)sm*D>o~@@kI1FMRgr8V1uet6# z6mu`rCI`0bT0d`Ns3*~rHN0;IU-Y#W;tpCNzPmMDY)IHkRH$^?V=koaN^DH#*0Js$ z-AQQSD>)>=9H%uOtqNoy1=Y;wZ66v{(e71?d*Qc}xSu|j-pw<^Oa1Zm&4M>e*x6Ub zEgF^HZ_(q=RSqI=J-smZTQ%6I--T8z+bU>xWQ}r{U^7UH(8V5|_=nL)K7pQ|K6+$o z{NmNTUD9&ch2#~(e#=J|MfEerN1UW3`X5J?_w_3VP8}W_mBCS>Bt>Emk4}z0(z9E3 z1I`{XSQ|$KuYaAe%9+)dc=l{z+}VH1l5s^RH* ?*Gm)tmnu4~~fQUT%fi8gJ zZ-K!d`W+0|C2QVF29Z_V*{gk{HB&28_ZAiKP`{- }x}L;;jo9^X@SdJ)NR#oH1*tci~QXg{WW5LBKd+_AA| AlZYG2F;}M7$A+DK+<$>IS#oyfb!hh9zg&{n0B=rx3f80qmZ41b$L# z^?Ij1`|<|X^BA)5keV(TnZTMTAxB+ERk8WInx1 @{ab6j(~-5MAX#(uO?m%70R) z&)9SS7V
TUROZf3CUCc{-f+kK24^I9!diab)8Y}OASmy*l%pMwin zwc>rziz9=G9GcPIPV($`#5TdlmC%c$sy(U&N?L^n*28KhXWnjddhCW9Xwy8G#mskV zUQ}%$un|7HZ2TtP;pT5BLRsmBziyy_C*@H1HVj12{WG~uj6ilVIp#lt8P6x -{$GPxh>NyJX4)F(Bcp *R{SN38w)$_mp1OaE_#LR #vmSX>RKA0LnJMjSS5l1`PSdlrYpDU6F5IxClK|Bbu gd_ !SN$u8eQ=-8X3Ras^Z@S1;2aHZf^XfLYZKSCVVvRQXl6k_A;(0*|1^D!B) zx0w0%evZq FUwzqxJ`>Ls1V&!}wZJ2j#eys=q`BYA6*02Xk^S@D|9nT9I@ zdj)4*R%XKY>!Z(NdN&^MKHIlCpCH=Les!e;5T0i-!mP&e?) `xzQlOOEz5cFk_5Bg&`Ai09Sk#M0=! z;uLYY(L=9oo$e8u43*x$FCW*ZIWh>Ogx`y|G6Bzf@&4;~%h$Gi{y0A#)jI}5-h-|8 z<7Cm^b9;9VBRYOPyU?<+CWUMoP4Ux;)Tzbr&IGc}0MlSOa;VgC{I0Wu0Zzw;+S!_4 z)KpU|Z{Eio&t)% 6EuRx#* z V_u%)gaOeHsJkHMnOXNR2&Q0@y{881E>*69(Ht_`I zoohoK=NB5Ce9MmKKOh Mr{~$>a>I|C;&3<-gGqQ zcyRX5rxciA{~HaJlf!?8-$I$MKG2KQT 3ONw|qSU$6O(2?pmFnOY@7AWm!XNarW)Mu^(aUwHf^9+!QjDN{l8eivRJ1y5R& z!E^W+y}yo+PxfVI(jc<{IxU`*Xtev?l%^zQB#t9jNX>8t7M8}zQ^IxrZ%{3N?te0c zcTc7|A+M*VznvhHg>7^(o1fvi86uAcW)@>LOG``Jyek7W_Imz&n=2H(@y$Y1WoZX2 zzeV6H Pi@HgfI$6C+F+zKKD&_5yd)6o{5-O^(!q?O!5BwIz@ pr2R% zq{+l?CPt5b*q7bv4-dL&^0h&w1t*Dn+U-O~ZZb|V^JqF`ga8@+hi4K}3rxRU2H^s$ zT!!k_lX1BW-M8Zu#J9r)^Y;)9ZEv&@j18tgB|27`rjcYBd0y{-iYE1MoBvC&A*B?V zE_%)rv5z<$v<)+pG9$YI%3;|&Ek?<~4B+w460$_BT{7sXt@Py;7>>Z_*1ELf6tzo` z&9 s`kqwGo*nZc*|>ru}+7xf~V&Sre`VK-Z #UsEj`qiQ+l$pepawj5 >`yo1ywbidir-|HVk)~c9rE!7WT%Z#@J}S zOih8W?nd?ndp#(ocmfp5j}Khbw_wnUe+~rP1p=7#a j6 zK1_O2kaUtiQO#=6vg!dcarGg37aykgD#aNR(^+2Miud6gw^$V|oBSAs1A#P#r})Nu zS>!fbVxJ&o?2S;>;li$)ls1q=9&wV3ZZ;Gal<#k6)p=fL=w2MBP;#}8r^Y`3JI!@A zic+r!Z1al}>LltQ=uCuC8SsD^_x?(o$$#dAV$G-&RhJMgkEE0QWv ^A zUPP>CF3r3PBu%*qHF1n(wLA|eZ1f>GyZH0FV9}s@7V=&5){1b|5LQCztfsdETs6Ye z&fYr5wGY1sfM2V!6f$dDG^Sh73m0Y{y`5>!d{#HvsZ^V4*g_FC`2t`H&@HNm?Oz{( zfrOELZ!=0u_=B7D5&ZJcb?b^wQL?BoeukcTVw;8@ISaN;|6UTXuByJ2z@5gN=pnD? z;8$V1HbX(GeS;I8T$9DTmQ1fSA3vO6cXS)>@fowL%_5q#%pWk{^Z}di4EJ4MnBA*L zGu-_7NN&YW_9$4M650ASLFdH9I5B-<;Lz~}zmiAB&r`iNnsCLG-Kc}#ki=+HpZOMJ zm&{o*KgxvjVQo59Gq>TZvbYRz#rwsTj`X3qbLa_xdV9uqqN(hv) 7LKrSS#9l8WM-CTv%X4Bvdd)b z+3urly_A`m*TU00dh<7F2b}){F8RIFqstCNjZwc;ma(p`wGmmuFQn4D?cn9*-7V0M zaMIK%%w_dz$tx_~iFD_C@^~sDf1sNE5jqlhLOm-ky~ZpnwO}fZi|>w3^6b|-sOt0= zbI-q}nzMSC3{jbsE@T(j%_bou6FLl!x>aaj{e;!z_3gQd#fZz9 s6+oaZIzhOd;yrOoq&Chp}Z^R%w21XZC^NNoi3sih5J4+hL=h zVs12&|2E@nI-LoPM{9pvtn$ee^&HG}fpAj6%d6><;{JVf (9aXS=CSkP&W3S mLOu+hBvtL&01&|Am|} z$YbC9EWc9ATCC8UH!f&GYlgI5ie@J(5V~z=-N@lPty+Gilm7(U3q^4-{;Bu>C>GMR z2?E$zP5ql&kV4v5xMVwvWbU9IGoumS*H28I{NVQx`N98I#Asje?~G;QI`#bKRer3E zpodc>>!^}D2IQ03ACNt8)LL{99=+Xg#KVb{drs}|5kb}reYiDC%16wP?UtY)W5_Fr z*VgxImr@Znn-y(!|MEy!=?q$Y@e AaYHIO% z0?f?Md>=B}y#4m=+phUfuW@4gy4gMdftZt@X7?TiT+hb7(?0Z=9%3mtkR*AZ89^Ux zcC5MAcC9|F)y(Twp80!I_;wT4_Gs$rhSuBptn6)Ot58$I)m?r+m=Bqh`f5X|Y5 +ifrT?G*X#7Lp_7Zy^PQn7E`nwJHC~(qWU{ zZ=WXkx4x#zId5n^7i>FkXge2_L^4Bu|9_?mk0}N?EEpa?P9jYjDlO#doBowhQJS{o ztaF`#JXaZ>E{Wu0av#_$!K$~_zlka*=)bNAllbxSI*_~d&(e=JD0+;#B-&1n6*asL z9fH}6axn9b{J&}$l(BY^H(I}Te#5avs|!k7uJ}9{TvoL*6Sj2^{>E(YdN#GyqS&BF z TP!|i zUqab1JZUA6bK+v6{1>K;1EUD}k+ukjP3LiF-+ofmAv_~njk-qb$(!iRvaJSSSte6y zj+?O`+ji+9g{b!MA5W?iQ@#&RUWd=gwOoD?_BiuKkNR -B-a4E;?~6mL+OKdwnoPTssCC{^39C5IX_V~Qfk@PpYbJ-<9Y8vY4r-hlKN#rd zCGJrKb`oBr^C`G%B|lEGwCif-5Lj)74~#}$<(YSzh#e-R3CweeT=OpJek5h#CglJU z$v2xF#%-An?`2usZ5J{+7^SX^8dhctPRhZxjZkcrg12U%d%m% &6=8P$(fKjmMU`Q9fy$9 zImPK7x7>1dFmX|XB-dO-JJ;(-PRh+4Ay+X!o-F~qNc^stkDzxo0P52vitqz`JYGQ^ zuDJ`H$FG|(C^u<&U9SmwwvZk_{N})qAoVK1ywL*1xi}u)m|_b3Iac-+% 3&(Q4Q!L*tT>@>YU$e{(3r{ zTJhi-CU$-Gj?ilfNWZVF8vC)!l16zpE^B$QJGc5KZ?A`VYzQH9eN>RZdhnEn#4i_q zJ7o_RsmC~Qc-c2}?0kOOgu8BG7=Iyg&v-HVdc`B!TXlk;D#@y?%e~os&EVYdQ$>bz z=o~tu&|^$PhwRRX1)hh4=csLxZ;3D$siIP=P`2yy9JdxC01X?0{(XWvbLQvbgk{tD z-jh!7A6^`7(1_3HriQE36wy_wkWZdl=+0gDc-FC&`yLcZH1zgLX@bQ1ZV@|ylG)-M zDWwsJiWjD)3^KB^KNVEpjqU>dT)opiWFhf~$+r0BQ6A(xaIj_i=ys~I&x?1jC6Hkq zbIMuLA#bBmi01Oav)y)Hn~3z|bQbQ;^6m!1IjiIMy3em?5F%3u;84_g;Hp^5kK2v^ zhpDp;XtM3!z90e$h;+A !ec{jb9uo86+ZHyr3)(C!=zo?TR<9|BamC{@T?m* zz~#B&@qPnmX>J;H8n6||G zbG(Ui}bc%fis&LiUiu08SS`zJ3!+PP1pU=Lh&Z! zJJp` ;JHT7JX{M6ow6bWC;A@{K~x<>ef2M1%G zjs2(P^8WoFvJ*1n#wWFha|E}*xbcx3>>?CBpK9*s!+=A-bp8O0&3LWbFUAcx^V-%_ z#{DB?cb%QzG-Az;s7?J*a&>zbY^t4t6}OLTaO!(|hq(|timjJw<(H#!$)WN6!PBNa z>x3_?d+UoOL-g)m(L9_t?b%Gpea+Vv)E}7qgO6=AH~z6@^RnNw1U?i=ATk6O{JE*M zyJYVI&~h5lkNCkYcu~0J>h Z_Wxo%`DDq$R zKH;nYk!e2N!#f1UU1;tpPOXfhk{qR|2a%~@@(t{eUWpLKL3l8OGv-ZoD?phiDN>tR zQT;5~XaYDm(O%=NyV@g6T9+f?v;S1@ygR|{I^@bwQuKmVGRTYL-FbQc*5I#`1ggAp zh9_Wg=tmDtHaCyRNXhpTq}-;B#9S$#JhP0awW4I*rntG^rVfF1Vj4Do>E{~{UD*r5 zfNtxMYh{Z;%Y8$L1A<{?GjO<$(Qyh@SF%i08*7giVj0w=a_FV}vk^+FUE4`YIZ_u< z6;maw7LW3DQe;?HKl7=7z2|-Q__w#GkQ$unO$bN-&g7_NA4!FUZI!Vi*pLLPncA#f z{1tdF{d2?t|GDB`NFa1E`kbTpjJR>v_hp;3@ss7wB!R|=vx+~#F8v#txQfE(djq=D z#_G4!5h?)!-p5um *Y&HaZ#}1UUH(`% zZ!VZi-w@!Uyt452=P#Z3h4bzVT@zlUxw*_(@2>TR@t-MCps)|a@v|?@46WV3yN@w> z7i_YnUkXe71Ol>jrYGcX#*|T)ycfa1qO6q-VLJ)0YqTU|O**z-{FWX{sJk2Zl-*v! zM`2>O)NFV3r791<#YB9f*%aLHREUBHkqiL3zwwkW5A`u*tn+?XV;5%YMmPCM`nzl2 z$29W#x|a2_81kTD7@-O6BiMP!^sa`FX|S=P&@-Mao@M!*)9%nvpSikndhCBfssXJ( z9TBy6sR8cH#Mg=)5?&0qS3!7{O7OT8N&VG&>&vZG4N26(tJCU{)P+Hu)}k9sl8~os zxy}bzH70h!=F>DwOR`Ii?(z*=KY0_kd2NR=QH<11n^{SBpGTYV$21!KasyN43V6#T zx>6!q_S|+Ym#phvU7yz6{fgOzq=s|HOB1Sf52%T_UM`PX9JDBUZ=Dnj2%$bJ%`fTf zU7k4n&T$mGS&bPQbQAjn+SR!7u%gvZ@LKkM$al9q?tQ((ju %x5(_DRJ6um#`xxw?H1!0Ka{-$ccQe-xjfHN#z%JU!Bgk z=@zjQ?Te?2sk(UIJxYNh3cA_H3f0*#KVe5&KR$i~Ln03Rlvli_RV6>bWl#%D*fLo{ zPaL&%0X#JAb-wSP?VT&BkDVN3bc=4=Rm1lIGUbk{a`K2vP*69Q8-uKI1m<4Aosi^R z%<@`DO<%}P^nCGfM=aHO(XR$@Q65LnWyh#=97S4Ce8^SdM+Pb4i`x|<$@2h;zUPkX zF`mGB8<;4v(-{%7W!8N+pZEpTmi_GFhQa)J0!N^y=u-s?uS0jKTX9zFeDSQ9^W3Y( zz9eM@aH5a@;)chY!AEO0qalhc#i2f)hJ*Uhqbf(HqWb3~%lJd&dcFqpd@)jubzi5z zb{>o6M&X}E?ISo1 0jQ6( =YGi `VdP~o7||@(-Y>VwT}E VG0Q0 z^JZPm`qH+L2RBoo2r78|$Xic)DMjNc1^d zm{BcI_$kYa*F=u3K$Bz`f4AQoRpGow+%bodjON!79PTyOFc5Wc`GDq9yl-~0Z#0}O zi6m{8Z)x67i83ecFo+QMy#playr?c9xAbt GKuiX}GSU-dZ$)SOD&n{Fn4yRA) zf ~BaP8%tl!;MdU$()(do`1@jxBsdty(n%x~ z zDtWF#(L;yE#th!;q;2}nWZ%=w`nDJjKiJv0aMCoA$;w)J#UQ+g5(45{^Oph5z(hw{ z@98kd3D1M%q=-(U!L^*YnS;GwL&Kg #ZjbA-fxOB!m0H}a#Db1isNmao{^rxL`bRi|5)`ONU14 q>E3mh}{& zGjC`8Kk-#f&2v`eDuX&p)oujSj2I^hl_^b~XZ-K5g2OMujF#pP%n!vmJ+eV9V-AMZ zWn1k{S)R9X7J4twIp&{a@;CY#odu2_f1i%R-NwHtbDM4C^(@SZs+*(f2CpARf3Cjv zl ^vrg6oA%96i7RQrAYpJ|WitQhnf=<{7Aoubkf-n#!9s9Int35` zUt16gf;9x5({Lllv5j$aBl{1bdyT+;GxC+(WmEZ{3kJ rB zkqp8QkcCHWj=8p4h~E(``2 y$gX8qUaAf4ihJ@Gefhco_9iyQ~L>X?^q9_8=_9t zP5YAE$X8$@OTE_>?S0em d4+Tmw{3<-h9 FQphxIo&;%#JRj1pJbKujmO!*ke?VZ2dIGxTibwE7?rNNL={9ee zR@WuX0pHRTXrlTft>N{md+&$>F5*jWiFH_wB4Jhr;j|VA{=kG?V>s9RluevEwitp1 zjQJ3G2IaAROTe)AMEh2Fz<{DR&ZVE?FL?F4J#v~g2G1zr!8^j8Mc}oE@Ye5uZ)wk& zIYr8wK$9C%gJVXIXoJPctCDyw?ACub^b!0X^N9YtR9pG6!({$y^tYBDs0svG7d-hc z@#}c$hsm^WXi-M 6pM`)X~Y3qFJ%*KWLU zb7 Fhi0g{NIA=i?9DQ~+~((T!@5s6*i-)2puqw3A-bV(O&26%`V zO}UbR*{J
A2*3WnFwKrCw;c_h(k#c-k z8Py)}SbJE4w=X^jMS`Q!opM&8bLcg9;=K>`Vj9S|*9a+phwr=j7=On~^z$0sWxtHJ z2C*;^URrCgSdwCPts{@gwIKfSaAy%z+7sohXPYJV7`3g#{aq&@FsBXlP~(U|m?oS{ z%?v5BkCH^ZFwGD&;F0h=rfoTf<^q0L2NlN`=Jqx|F;j4d$~agZ#JA$!oxP0NZ@=E! z*#^;C{B4&Ogr<7vr|H=iBos9DC@{VD;k~g+HC~k+>Gy{1hj0);CATb*L8wKRNFwV6 z7n2?Ve_&hOB+~KaW=l0b9(#Df>52@ZLTYN&h5QAMR0w;xyWMr3US=uV6HhX^hXOYj zLEZTb0fbWGWGp9tre}^0n!UZcr$xW|lItZ0wJA+_h)({H;6E&U DB8w z9T0Yc(Tx}gPUAm(3Ygc@^rts9Ji^7U GHUJ?tBSpMe))fXT1$;Ouh|p z3)oyqTSs1SR-N>sHLh{XLY4S&sGc{4>viI_g!tL=3$7kbO&hr*o10WI=#pRQ 2O z0LjzGfIUm4v-ZOctS9NfbKl1oz(-;wRE67ynt>SQ>g4jIO|Kolz=|9jWAK5sspWl5 zQ5_0gYtf;<^10puRLo}W$}zg>(rSb4Az_5fl?mNgFh*^HUryd4>J7L~mO{e2(X?ZQ zP99v%s&$;U9+A#D8#5ywd7hx%`>#9)pur)7l9RAFa-m20a%GBmvH|{f>TgaByM^?E zWSIl4FkvS&wqsgzh2$4jX&!oOc6g=~&77X+0Y!nr!{A@={+-drkJ%vl%&Nfm%O;Zd zJ71$RI`!WOT9=BBdi;>cuz{*VMvQ{bv5`aNBf6T7 #{hlmG@>hH$nX*)c$$4cnBTOh->+V9e ;^;hOUozIU#5 zZwSfN0Z8azP=r_JXR4{K;(go&nZaKeFHZOhaOJkQOT3r;_-C(WLk>G{x&t&_*~m)m zJpLxOOv{-hyS<#XFll1Z5;Gwq6N3JHe|OAfrR(1PbE{}J$F1~s8irf%zrI45e6nmm zC{MX<5`80aKH$-$MrnS-#+3HTq!MHo JCFC-t!~ve?=I$2l4<+X5*O5hz>z%pBa1aFrYCKp z%+-H`eVbQqR<*{UU+seJ1fP+YSnfj%e2}BOz8pHH<+Qe4D1&%-(u`zFj47U6ATGP6 z%a%#jZjK^s`K=Z7+#Zxap^ol1OPxpd6A$ca2%=SBAN0r<`R5DkHa{30Z?MV1UG?e% zNf#f0%rK4K3tzMvMt)ZJ-?6Wgs>ArC{cXM4Fd^wvj`4n*=03JomXZ{QngTH! tud+%Oq#{oz;4zRZej2b#tqzVYo z$b0R-w-*vFlh%pI8A&vup?Ua|Z0_<0{aBJcUi;=;-G|7j`pEtPPL^kBnZYI**B(q4 zV}?g%7XXUpo%>tgRJ~i{(b?+Uma&BJnb`h=lu^O%dwx!SYKMqj!_+se+OnG~Ocdf! z1#!tE;%YTXbJ-*M% 7G_vUwr z#}{Gx9xXgdl2;PHx94>sX?6>#g#NVqjQ^s8&G2QY;%3kzEuM-xjWYHL@|v1tGX|`*>0k_ z@bD&47qxlO>)H8+4|i}Nm0mP0!$bcjmg<7bo6pCGW{vMi;t!^riGgoPaPGyvLT;sX zPGDO1b~rc4iNDT?w42|e+HahwRVc$ctqbB(gfzF+N!a;_D6A=v{SZDVMjp^BTu2Ta zPPwjFOe&jXv3tJOy*ou$vk38ri6+!9TuB2-(wdgR;9J8qSY+mgrG_D%Tg*XI1g~d> zwn-`2&G8`@^2 {Fp=?c??*crdHk<6A7nZ87V{~qGBUOt?P>b^X>eL0A zzOe|dOF9(X&uX%j+!Qxs7*h$OJ~*DcZzb2Mc3$3=7=4Zw6!lbvyjb`$y?Kj&cQLJ= z_{}W(T x9CpfWq)MpOf>TfeOiyfUhtKgIO=`?d~&Y`dKKRUumPC>do)Yz zE9#s!=dL{aCRO^x$Cf|NU~P+K&4DYoug80xs3-YG(^#3ND|z-+4A#A)-ep{!?WgKt z6FvcWWkaI6NXIVhcB6emyT$cFG^y~Zngbje!SL_JjI25gF#=Cm*1NwpSv&-;tcmtN zW~n`ptlRt@ZN>doRcj;-IOZ^5e`q-b#b#|LQ!`opt)EmkY35h)+VO^)m9Nwb+G2Rg zH^G8>n;!evB7a^-q;|lKlhW~E+L#kU_c;&lT~O4tDfULw&4lN@8fBjUlO$n|TsysH zEsDHK*o_Wdl73^?xpe1sUBzt+l>3*;UJLsvL)ir7()`kVc3^I4?t2MX@ ^!+ zImA6wuk QoHajB)d96|kny563q#m;O2&%zGQtGpLG zWb44gW_bEs?SVtztOqZxz`OL~EWQ{wO{v+yM4l#jasY $hdLF?m@(K?;DACLVe%iY^toOV|fGJ!B@ qGJry(<6K0mm~yO_Z{xM)!M{_88x+d{M`ufBFR$#1huuz-L2EyI%Qm<9}@qR zgs3U?;F6XY89_4?36qX*b3rY(ldj5ODC}6wo*H88R#-V{JE0FjR5acKzAhNc ^7m zBQOqgwx`vNQh2^ex+`6L1f=Ul^3^k>ooH=eAX?j&I2Mugy15V^eBC%g-}gwmoX899 z+oUT({mN^155`$XTx|CT(VpObVbEsFJytx41lai)qu`)}$Fh8~&fY>B+(mbJsMmND z-$VcfeJN%xCsEi)&-9$BW_4YqnDK3R%{$S{h~L&rBZ?54GSK53;=A4eum#5l)jI z#p>_3$kI=}tKdt?WjmzulJ;oE-B*cZL);J-`&{t}Ru%We{g`xVA?3o5zE}kunAuAj zy#tpS>UkL467WEYP;cqE!CP;yh%?hcSKs}9QRCGFCa;gmst167xMqcgg-qh#v&~2} zZ$$0#;3bOAZfS{$U(hnY#tHrf*C1Zr#xJr#AhT;BCOt#AFqQ|c5~8 4@nZS>VOmCs;!10FWaJySec#8J zsNHE!TY!JN+y?KzQZ#>S>p~v`RZ9c2;!z5+PpgKis >fT-6nULqliobUa9p{KoZ3+y8Oq+ d2@~8$87RJGrOEd_VscAFj)k}zHEwz{n6f`wA|Cz z{N`P)4LmK`x(R$hqS-CBr}T)ISrp3Ah^zeE6{(60{o8rhaD;n`o6P?EECNDhpFpu| z8UDx6==I+-@dResT|#D{^>TTWe@qctw!$)of?{0Hv5$qg&>hZ`s*l=FTVAj8JE2@S zGWF_%a3$2ex=Gsouq lqt7zue$wf&9~xM@*ksSs=>!OC!feM)wYm&>9HsA& zvSjxq(Ho7>PAvW#_?akTRv3)jND!vn)57cblR(cE6g6TsuOSJTz5ba_aLx9p -2wu~Wl2otx zXYLHHgn_8-n{E52goVcr4#;`pa_RKAZ<&KkSpAj@qdBi%@4g0^|LH{^D5sUcna?Of zY74?~_I1nunigLh$`d_JzV{k$UJqlO2UAz-(x0e(A0cFVH|qJ5B6<+Xw3h0}A234b z3Yv6n(oLiF=f5*>z^#3nOvfp|Nx^lLK!9|WHfsz#Qkw7JjcoN|3q<^Ra01V6=k*LW zk!#d#UJAgubKaubh>2lc?q3e_#x9DDI0W_J=HC?U3(2UeN-V zPNHGM(?TBhCST03;Iy?flSatdPrv4k5#O~{HcEOS #gHa$J#W%&Uuq@;D)2** o?DoT&j+53v?=mC25YjyMmUn3=BD08)A#q6c}AXCw4dH=Fd8cQS}MW}Hm zB)0z1GaA3X#P5w`(dq!*D683~|e(r4{`~c-i;Emt)c0zY>TuxK_NX8Quh@M>FR& zlRoi)J!dVah0wad|H$hWVt71D>;5~fgy!HuPOFUEh^_`e-dA}pjcr1I``7}JYbN>) z-qgO0oX(T|t-brB=2v{-UCJ_BW{NAeK|bVO6H7RPLICvis`dRCM41qp5#*WOuko)~ zaNq|0WZ3@?DF-&WM)H}@j;U>nxID|3;NWuFSossbFY0nY?eC}7i`O3XAhrc=v9)}( z(PzKCe5czJ9)onlc-b}^zt4WGK?P*bF_grSr&_BQzgNae(l=YN(aHZ0{yF+=%8e1T zBD-fqT^DWOV(sgU7jI11J8*ZyV`?y<0bOFY9K)k 0FBEN^F3K#J +V}nUOq5tu_43vU|93ahuAh-|+4za3b#6Khe3k}|NTCO< z=6`lVW)PEW#H1#z5J}T%U1CiTd9KBsjDuGGqF+dDalmJp;5j5$LLmPykAn{LX#wRt z$o~m5@1wT=oof+~O85bPWF)njynm{c_zVvxPj?~eb*=q8w%q>1XT%Gp(((%6j8Efi zVzwZ=H3hU_9ztrWI5ugyz|kBvk{!IdHLoj;o{ab02bBD)HJ%Xt|BrxHzvf@tm6=1| z_RWyx9l(M?+Y@ U|6yK*Wt_lbwx; z!Xo`^1EqHUhA$4~t}x)23ctN#nK6HK_g>1$SH?8sq^P 5WxlB!tTjIZlh pL3p)u&5CKX!i{=eJseidmm9Hwm6i>Y9F-XMj341n*nJ%_jt zbk=edrxf^K;nk#KB(a75@(==)%o9gG2x8TRyi)TZB)0kF%xDdoXvpWcu7aWYLel-E zTs9VOtGU-+61^~Ra$^l)8f6a560j#fk4*;~^LT0Al5-1&$4qea)Tycl1Lae5p=e!! zN^i7*%F3>?K7oh!TH?psy%&cG3(udAn1PJ{`$!%usOm)xtfQ}{$~i0FTZMQ2`P2*U zX>hwPjWq7(e2H>h=qz}XK!Jc4-INpB8~SCLJkA_7mCf}d{Lsl!GqdIC+eV9Y{!E!a zA0;#No0)VRT}>9XKA`mFvCd0pRxGDG?u7?8xGWe+y@d5Z?MhJL;?tfj^C|8#oTqae zjJRns!TjpsW-T9O-Vwv~IBbo?-oK3^w+1)cKzRAsaoTf;cy{7od!7gflL~RHtAB5d zm*{6d-{#9IWa~{j^zRM?2faSTh59%Qznw_WFEV${ZdUbrPNkyzli8um_*S++!200z zJKkp^UB`Adki{R5;y9aU{!Y=)dU$wn*;>Dg?Z5{8&>^tY+o1F B+75 ~?H8rN?dOVBPF{w++|;tBk@`lE-Cp8I pf;lqF KtwLnf<9j} z8aQF^O$zv}zeT2MS49Lx{%6B6L=R&tOq5TM9z4PK$~1ld1=67br6LA95P+k~jPQoN z_J^E~Df=KYdOr vN)WeTbl;POjL(^KleFn(Ex9x+^r|qOn<2t3(AN|CKq`IfHO9I5Q(UY zLcAdYSD6ry?|lRRo%vQCHrO*~{dOQObAJip`%7r6$Gd8` HydMB zp^0&w1aK^%x@zn35JRq2*?U{CUy(+U0_+At=K5Ygw7XJj`YUmapKJa{N1iT|Ms+{H zo?$|_(U$K&+sUNmx^_3e!;JQyniUcih7YN|;$pLJqZ|hZb~+2$tseJA6?*?s%djBi z4a-Z`t`*l+Cr2ih4{awYo=H`z)n%)|;qu^nTE1Os)?+WKBjFr|-10`a^_M&+Jd#O* z{Jca2o}FD0`j&=JbMLvTa~aKkD{s=Ft|QH`Ph;W~d0LaPD@@P|+leOaVTaV>PEYbC z+vAehKksvy{Jv}H8AJC_3ghIIp=N*~m$JVkPAhXHdI=9-##cb~z<(%$3i(&}!-YSi zZ}+oSA$G&i<~h+8T@Mvf8OVKiiy2rGr*2^Z#3bK0ibf_Y61|je^1xr3hY})tPM6#j z*!XH`4w!+y9%5qPpt1^oEsCg}Lxa>==q;x{TBeIDOkt^c2B% Bim1^hV4J*6_umi=|owa73DD`{jh=mkB2>#e{6n zwtaG*c7+(`__{e%REM%7)29FQU`Df+xnK^f5W~|7A2!dzNa0{zz>A^OkW#K%Yv?N! z8!}&s+4QH6YZ7 ^Z`;Ysh?f za;R>+3v85NR(Jsa;nIa`J>SS#x$~z>(`(d5Grd|rym`~netPQs`#=2B#`(wG0bEpx z<6C8Ukg^N)qa1;aJtXPvD=Dq3(TU;r)0XZi<~>2SybGRQW*EcEEok5-kjn`AX+wNb zL=S7vxzp5175wo2>YvZ}LO(^4HwDPs6MB?B`fKDRwjHlSW2Rwo7~^;>`Ag+%dU8zV z<0Qw|bUZ)Fvi1yTTfmL@Oy4>Cr;S6^!pTE)d2rTk?1vnF&wov}=jT-WxgGvM3O!O# zA!|2-^}Fus&o2#)#LViU^9W(^^NC?&iRDck9O3m9rT1Sv?XsyPOc`jrLT;)bCkZfd zQ@kCDm2rC4M|^fzB=AFL%HZz73pa|ML-sPGGdreg#e^qo{o4289s0Gf-(x%DD@_bI z06T%^F4~X|hLH1px&l;?xEj^#-Xz Fb7}b6qB1Fe>~aWuf&>X^+C2 z(6cXE3k%}v^?&dvnBqgQlpVp(Lwmc6EWR}g{ivry^ww^BYR%URnw4nZJO@Mt-k!as zD;vMn&(>sFxAw|)ty~tJ_cao;^U8Cgxky^*@E+DH;n|N{_c6pVtut}6v#hQwU3%?1 zRj%;d0+V>(GcW7&?tE4DR15sn F4Z-Zg~}at)BC5sta4Q5L8gC_q0upS4!cajYr3eX_`Jte<>uCj@H?leDq5nC(f5U zHH`b*%nNuY(0A~)ZoM8w=XN&JDLx8Ha@*1>G?kyBB@yDal^KG(xi1o+GdPQv8EBS& zSa~`3* XjJHAl_M)liLLxo82qzAuQN0v02!%Z##T>lN2nEQ_fy;c&C_2$Emc<@hO zdBW3LX=2Wudbb_{GbBfS5`R&@HtFrN2DwOEBw9c4S=MS{?`yAH_y4WFmnzk6mqE*= z2WM*#X2vy1r;XYnKii2Zo;vJq3z!_w4?WR8+vb wUKNUo!p$r+FjyI!-Ui^GPggnlFyrq zeBCWEuNA#nM9x^aZzt_%47i6xKg5rNwg5}HXx~q+{W1F<1xazZMJ$~-=|ceKm%l)R z_(=5Ph7Mc6GJ5}*@%|^^+K3v-S_oG36S3II7y`y2Q*?9(8~Z$|av2tW(&x7B$jlm+ z7J+hWUTAvna7_Jl>g7Vl_8*C*+8QTX8?wL!%tb8SUhc(Dmc<3xb6K=FW~%uCV11&r z4!X6^>5A%|-s@WxpOvH_Q=?^x-vrv19>2pmFe<}FGrXHkl&96;(S`)ymqFmkGF(-~ zufFu4)X8UazUJAqIYVu&DPGuhx;!j1XK`IeRR96qjDyT`H}1>z<*HKz#!+idut)C1 z-! nbkoC?Qog6 jghvXX~9OTlWR>#A{Kdm8<;rjZ*1JKoM_`*Jl!e6`%j B}qYiN~58hI=ZB8eI zu5+0o%qY1(>vzrE6Xp19*`nh=wi_H+_V#FNi}yK_ROnw`X Y> z@9^uH|K9^}?9NItvZ|nid$7Iqm~N2I(o5~e5R#fq%D81C_F|*D|LBRr-GC{jlhE1I z pmu?Y8m d*UrNYC^nj#+(8MdzQ_C6E*=HKctO*Iw;?V zU_skf*wNF5HKX%ckH_BYf@)pPaNWit7*T(b`iSL^{|@60%X2;@Bge!raj}2%YR#X^ zrRWG V?p`6ub?o(d-l3*G_B5;GFErUV=E3A_QMXMs9$esJ%9}e!ulV~& zp@+!ggkkL;b0}@`bYS%Q_UF|CoB@xgJ!*Xua3pb^@DiwNLv`s1AvRD5jX49C>^^ zAlNOhO)xdob*2Fp|N8-hljAc%i+BO@`Kxh^_)nh5&Q7|`=)K5=YQ|@k-(2>4Wg?Wt z`rr&`vFV*@12*YT%hGC;?kz##g0;h+{?AfuezCuoz}(L0^~!RUSX%6dq}Pf>vx$st z*7a*nq)@$S3YSLI!ii=3+soFO&9>()IZX`6=!F@Fsr lSfziE&BET z!*vS<`W|m&WOCP2 Xtb6ftgg1dDuG zvt CQ2@bGsWxR-*%KGWt?x|^ zrC2!ej=eIx#;^0d*kh9c6Y&m*arTAQpUtrPIEK8iYc&V4S9GsXJ(X&6Lp<(%bW9ks zKD=#1Nub}rqs7UW-dD;m=E;ZVE~}kw%wD@1IWmw)c**@4R+;f$qw%+X8bo92o-SJC z63TgUi!lbwT3U)c8P91?ZKWCdJDx~zgHm8Bs(v8x*K6e_rvB4M->JZ#*Mxl);qQC8 z ;a}?{0D{K3X0x zcAb==1~i{{(qTw*wD=O=i6!mNf}0MFq61=xT>>WyD1{x;g&pZDAT{h3V}9FLsoce? z2@uSpc3Ux1r)9r>#$%MOzs)3#+i} 58p`*DJqv0>payUB|{9{SGs zhLg`5H+9=Oe9C<%D(Skd@SDctwv=LtXlroM)^bVb|E!O7x-E5e(nYC5{~&(fsi?@i zyVn|*Wde#vEe1Y|qv9FScIScUG#!y}IrOU4?6Z4$;PoSi!IT)S`L7a)9u@VKct(as zCH5fz^X+BYr^*A9ACh+uqyv#=m#>5fMOq&Utc- y^$U zJaq7LTIytC6CDEkJW)4V0^;t}@wpfHDKN(<@&acV67ctEUO)k&9i>~gRk2<#4RA@I zL{?l -?*XkDgM*|mrm_c2v8yQO&72ZJcI z>9&7>H^sLh@zqWv9HycV_H%S3fa2UWUs0D0tHqb!<|3yG@xCZ}P!sCaG6s+u^|#m( zISA7`-q{9PQi+Q2sFx?bjtxL<>&E(wiXRpBO+Cwnow_@oTA7)dp{;z;lqDuEE|nW3 z*XE>$UDPJ81M_WzuaIuVEqf|z&l8I@AOw1QN(I~)A35H6g(c%3$hl !i+nMjh|IsgYR?qE`KE0X5G1~e!w$O}m5g>^eY8?|4 z{rij?+tNjYQR91D_7yN?_vJacv3#NPD|#@~gvVQ1b$o GNy8qE&ptdMVxAPhQ9SCAZ5s%uCW)WBWNk+1Oe6Z=8RStZZ^!XhCgq5 z)#pAjRp451+#}98QI$Xv*rfp_vqy&{21f4mXLzXPZp{+O6Y10`fn>*dA4;3nQzKPe zknCpoMU@$ZJ%37`&|5oy5g9`Rm#v2+NkozNSq{?pL>SBeCqh-2$lAfMV_%?lx+3$A zID%}4zocz Lp?6ai%m56v#$t0#f|KfUf!{TSr;QHhcYc>YhO13}>)^lEKu9-Sp2qjDF zZRnnM9kWC&dE(aDIl}Rs@7~1jh+vPN#mM{5Kl!<}*E3J0cswh9>{wy!#$t9^rgNes zVdfE*0ey=Kdh|}p`=^qC5@b@N9JsLXM)gkH5wJG3(pIRS%-F;Zu~3~2|9in%Zf2Iy zB!Wd)KHgUx&N(fH5hGdlSU{+roP5u&i{YA+E&O2yjjp9pp7G9$T+@aC4V)jf3Rg)A z=-vUnzoA#vLRMYR|Jhb)rQ~$xfXHNFtf=W1p~h$$Zgn#Abj%2q;a{}ubwPq7*DLMK z=~-DvM%RfQX#5+x6;uD>fqawu)RXNNiS+){y6pT_$Ve%Cl;L6X9H=0@tbc9Nr 9rm cF9dOZ!`9q$g{Ps7oCYKGqLZ&vyoH6{r zjJ=JrZz>dt29wxQU3-td4o)yVGfnZCag(EwC;M1Xzrx*=gBPPzd
lQbus w$9wr$E@>#m9=msCV`{P|Je5$AUK%E(At zP@*&cp_D{8Q|0cHc&qHbPB_~s?#`z%Dd6%-{KuHrd%p%jcW9HU4<9^rMm~wV<111+ zt!) R| hCB7|sd?)Fx2l@Xjb+O3j|JmA@?NW|MS7bR?7-q<%U@vIeqy$7eLI>en zRVu@Lt$%8^%onEWF^flo;@W9d6pydQXZ&ulq-EM3a*gwW_(;T|CwlM9l;7!=U88Vp z1vdnry6;9Ywdsha<%StoXyETyUZu2nUCJ(yY=;C7`5_E<108fOK&m^-tBVtSm25`j z4zD_K9q~SxO2iPpO!3XSdMcqHxOomW*J2M!reNs*d+53DhR7 n-G8by42|es+3ZtVv8ce-rlG>7|HK2` z^*3JqH;oM&*qAq9Z25nnBOzAY8FiRqB*azT?~;wtD42~ahzXzEXETY$4 n!8Gjwxptg$Gmf?8N|b2g0AVIjh*%u_1$m9o#2Al7w%sb3sI*P2qh;0O!@HD z*(FcxTM&oRT;m6aUwpD{GkmHa*Y{)8z9cq4{kZe(P)(aJrDYmumh&Y7UvfM(ff>@A z?{57VA=8UrUEZM*)iZs}S79F8$cph8V=V)?VMW(--6Cn+WPqWm%}^nXdrsJY!HmPm z`zCx!C=0JSd0ky5h}evLW6g5*J*?&RtTRn$Enat|(?bE~8Q|V}biSas%nhkpS}K>2 z7UWCNbNW51sPRFMt9nNn?!D=UhI>q-?=y{#BpTHc |`*&H@P& zPs(MS&l)IB4t-4S``-DRr9zLI6@vfmdGozC4lq#ltptt6^#9dD_i;A#wI4O}G;rCV zX%x7-X&s!1H^yk{!Q?05HDJ L*;UHnX%?VHyh(ir8iVwjDI zSS@c2+d`;KNsG9JO}kUxWIYR?Agif-Zb0suh>K^79*bSNyfx?FFz87Tv>EQoAsR%N z0Lo-wH7&m>d9@0jO}`X)JV;;=xI~ODCzEm6@O%L=SlmkeOOmt;yl=smU^`U7X~De- z|BtrsjB5Icw#9}DDk@Duzy=5kNSCf6AV`%afl#G}&_e_as5B{p(px}4T0)ghfG9|j zD!qh&NC_c8q=XhiUQqw#-uv!dZ@stPe8`7DCX<=@ojK?1J^O5@`-qM{%Q^PgbZNc@ zw<|lEu*uC(;)xVTMEh1KdgA;7IYP$k#5rRJdlS5i^s#-`#^}xRnRg$ro}6|r!<={; zL3Se$aE)vqgf@w_ 0r?Zf3% z`Q=W|HHbcs$9$|)1>}P+_VbA(M;Cq#S$EYp_QTL72Ei2wbOQe=(YKR(u&XXv9SF4! z-srK7U=x^Lup^SSoUVAhi@Wn^xyLZojJT=){31L)TRsSiJj4BkeYo6+uDnv%+VkV+ zAqSgB=2!2N?r3_*w8$J^?PH2~G2Y-!^2=Vq%IdGbZ?tdXvn=i;UPL5%j&;EAoH`dW zl^SNL>y;<(cR$G^wZ}*?o-}Zkn%=q2rqu7ItEYeKK5$OcnuawxHJK^DhrjSCk4I}3 zaDMN9c<3wPZQRWek=r4~9;URL%=V2+9q2IkYqy%lf_#iJ>wY7R+Y!m(3iTtuz1&LK zgP)i0ACu?+JOO}-stY}Al9$=fQpDTH_8h>BH?tsvw<;r^RBeEq7i((7f`IRwxbEH& z5NEs^+paZE*Hz>nFbM53Uvo 2NxvTOj4TXfh+O>st6xZ>hd~cRN z@V+*7{rvpJSG!-HeRw@Q3emI{GOY<~we`Hh!Ib+^z=Sa_tg >ivwuCv^X~2Y#E)XZscSpE{vFYlikmcHtxF-`4Ezwqk zZpJH~jqr`JZJRXTAsX-Cprtg>imwHZld~6`L|qaRoAIA%l^HqS)kuf=#nl*x`LW4d zuKPBWvT5n9(6*6ncLTxsK>6AX`(P!~1zvHue8|Xde(Q}h X?>UgE!Zl^u-mL%=Njg>+Y`S zw{EzXoZq_jQTh4F!Ya0~X6LFJXZRmbu(;7-hZn%oZNW(JRy%p^3;QCCh%mMWq2Ypq zTd@t@dd!d8?y?DeS$b12LA%r*RC;oYR0hTN%iNNb3LTMWMm>JOdGFlouSS8^F+#^x zwlLPoKsV|4`R`t{JDN{i?-YF!f0NgjdOCu~k-1}0NMX71uwi8@8fX3NkmN-7%Ua{7 ziFIb)Uc`a?0Gx-u P*AT(m6t+u&slBWNU=STV>7OJozWrNisA zt*z}+0*xN^s)jwxFXo>`GO@~k^h4n?;9uz9a?sbLvk4I&Y(u_D` olGszj-PO=XZ8N)m)&=2^z`4u0rss? zBYqj9mgvF;v}Z@ ~)?aHfd$^#OUO~u)