From 84943db1440e78edca41496e3f4f8f55e6675d8b Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sun, 7 May 2023 15:19:11 +0200 Subject: [PATCH 01/14] Update .gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b5cc70b..375f4dc 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,7 @@ dmypy.json .pyre/ # Jupyter Book -_build/ \ No newline at end of file +_build/ + +# Jupyterlite +_output/ \ No newline at end of file From 7170d2607e38d0b400878aeb66460b8be269a5f6 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sun, 7 May 2023 15:19:27 +0200 Subject: [PATCH 02/14] Add Jupyterlite REPL example --- book/_config.yml | 3 +++ book/_toc.yml | 3 ++- book/cookbook/jupyterlite.md | 9 +++++++++ jupyterlite-config.json | 8 ++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 book/cookbook/jupyterlite.md create mode 100644 jupyterlite-config.json diff --git a/book/_config.yml b/book/_config.yml index abf141e..4273941 100644 --- a/book/_config.yml +++ b/book/_config.yml @@ -8,3 +8,6 @@ execute: sphinx: extra_extensions: - sphinx_inline_tabs + - jupyterlite_sphinx + config: + jupyterlite_config: jupyterlite-config.json diff --git a/book/_toc.yml b/book/_toc.yml index bf5c061..110d88c 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -9,4 +9,5 @@ parts: - file: installation-and-setup/jupyter-book-setup - caption: Cookbook chapters: - - file: cookbook/recipes.md \ No newline at end of file + - file: cookbook/recipes.md + - file: cookbook/jupyterlite.md \ No newline at end of file diff --git a/book/cookbook/jupyterlite.md b/book/cookbook/jupyterlite.md new file mode 100644 index 0000000..f16beb3 --- /dev/null +++ b/book/cookbook/jupyterlite.md @@ -0,0 +1,9 @@ +# Interactive elements with Jupyterlite-Sphinx + +```{eval-rst} +.. replite:: + :kernel: python + :height: 600px + + print("test") +``` \ No newline at end of file diff --git a/jupyterlite-config.json b/jupyterlite-config.json new file mode 100644 index 0000000..7fbf1bb --- /dev/null +++ b/jupyterlite-config.json @@ -0,0 +1,8 @@ +{ + "LiteBuildConfig": { + "federated_extensions": [ + "https://github.com/jupyterlite/pyodide-kernel/releases/download/v0.0.5/jupyterlite_pyodide_kernel-0.0.5-py3-none-any.whl" + ], + "ignore_sys_prefix": true + } +} \ No newline at end of file From 3a87bb1d1e11f9dc4c0d87e3f26f8b6b134f82f8 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 27 May 2023 16:11:57 +0200 Subject: [PATCH 03/14] Add JupyterLite configuration --- book/cookbook/jupyterlite/configuration.md | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 book/cookbook/jupyterlite/configuration.md diff --git a/book/cookbook/jupyterlite/configuration.md b/book/cookbook/jupyterlite/configuration.md new file mode 100644 index 0000000..ad3ba09 --- /dev/null +++ b/book/cookbook/jupyterlite/configuration.md @@ -0,0 +1,40 @@ +# Configuration + +In order to use Jupyterlite, we need to update the configuration of our book a bit. First, make sure you have the correct packages installed. These are: + + jupyterlite-sphinx + jupyterlite-xeus-python + +You can install these using `pip`. Make sure these are also defined in the `requirement.txt`! + +## Configuring the kernel + +There are multiple Python kernels available that work in the browser. Two popular ones are [Pyodide] and [`Xeus-Python`]. The latter allows you to install packages from `conda-forge` during build time, making them immediately available on your website. In this example, `Xeus-Python` will be used. + +When you have installed `jupyterlite-xeus-python`, the kernel will automatically be included in the build without any configuration. However, the default kernel only comes with `numpy`, and we want to make sophisticated interactive content, for example with `matplotlib` and `ipywidgets`. `Xeus-Python` can install these packages itself with `conda`. All we need to do is give it a list of the packages we want installed. To this end, we need to make a configuration file for `jupyterlite` containing settings that will be passed to `Xeus-Python`. The configuration file needs to be in JSON format, and needs to be placed in the root directory of your repository (where `requirements.txt` and `.gitlab-ci.yml` live). In this file, we can specify which packages need to be installed in the kernel as follows: + + { + "XeusPythonEnv": { + "packages": [ + "numpy", + "matplotlib", + "ipywidgets" + ] + } + } + +## Updating the Jupyter Book `_config.yml` + +Since `jupyterlite-sphinx` is a Sphinx extension, we need to tell Jupyter Book to include it in the build process and specify the name of the `jupyterlite` configuration file. To do so, create a new entry in `_config.yml` like this: + + sphinx: + extra_extensions: + - jupyterlite-sphinx + config: + jupyterlite_config: jupyterlite-config.json + +Of course, change `jupyterlite-config.json` to the name of your configuration file. + +## Building + +When everything is configured correctly, a `Xeus-Python` kernel will be built when you build your book via `jupyter book build`. You can check this by keeping an eye on the output in the terminal: you should see a lot of extra lines mentioning `JupyterLite`. \ No newline at end of file From 70ba1cdfa4af96b2db27da74ff0654cee6e6f4b2 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 27 May 2023 16:13:16 +0200 Subject: [PATCH 04/14] Add "how to include JupyterLite" + demo notebook --- .../jupyterlite/including-jupyterlite.md | 103 +++++++++++++++++ book/cookbook/jupyterlite/wave.ipynb | 108 ++++++++++++++++++ jupyterlite-config.json | 11 +- requirements.txt | 4 +- 4 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 book/cookbook/jupyterlite/including-jupyterlite.md create mode 100644 book/cookbook/jupyterlite/wave.ipynb diff --git a/book/cookbook/jupyterlite/including-jupyterlite.md b/book/cookbook/jupyterlite/including-jupyterlite.md new file mode 100644 index 0000000..efbfbca --- /dev/null +++ b/book/cookbook/jupyterlite/including-jupyterlite.md @@ -0,0 +1,103 @@ +# Adding `JupyterLite` to a page + +There are three different `JupyterLite` directives that you can include in your web page: + +1. `retrolite`: this embeds the old Jupyter Notebook environment in your page. This is a good one if you want students to program things on you page, since it allows students to edit and execute cells. +2. `jupyterlite`: this embeds a JupyterLab environment in your page. +3. `replite`: this variant provides an environment similar to the regular `IPython` kernel. This is probably the best solution if you want to include small, interactive pieces of content, like a plot with sliders. + +Below are examples demonstrating how to include each variant. Note that the `jupyterlite-sphinx extension` is designed for use with `.rst` files (Restructured Text). Luckily, `MyST` provides a convenient directive that allows us to include Restructured Text content in a regular `.md` file. + + +## `retrolite` + +To embed a Jupyter Notebook environment in your book, include the following directive: + + ```{eval-rst} + .. retrolite:: + ``` + +You can also include you own notebook for students to work with. To do so, add it to the directive like this: + + ```{eval-rst} + .. retrolite:: wave.ipynb + ``` + +Finally, there are some formating options available: + + ```{eval-rst} + .. retrolite:: wave.ipynb + :width: 100% # The width of the box + :height: 500px # The height of the box + :prompt: Click me! # Instead of loading the kernel immediately, show a button + that activates the kernel on clicking. + :prompt_color: #00aa42 # Color of the prompt button + ``` + +Here is the final result of the directive above: + +```{eval-rst} +.. retrolite:: wave.ipynb + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 +``` + +## `jupyterlite` + +To embed a JupyterLab environment in your book, simply change out `retrolite` for `jupyterlite`: + + ```{eval-rst} + .. jupyterlite:: + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 + ``` + +Here is the final result: + +```{eval-rst} +.. jupyterlite:: + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 +``` + +## `replite` + +This is probably the cleanest solution when you want to do something simple, like a `matplotlib` plot with some `ipywidgets` sliders. The `replite` directive provides a REPL environment (Read-Evaluate-Print-Loop) that is very similar to `IPython` in the terminal. Here's how you can include it: + + ```{eval-rst} + .. replite:: + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 + ``` + +You can't include a notebook in a `replite` environment, but you can pass it some code that executes once the kernel is loaded: + + ```{eval-rst} + .. replite:: + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 + + print("Hello, world!") + ``` + +Here's what it looks like: + +```{eval-rst} +.. replite:: + :width: 100% + :height: 500px + :prompt: Click me! + :prompt_color: #00aa42 + + print("Hello, world!") +``` \ No newline at end of file diff --git a/book/cookbook/jupyterlite/wave.ipynb b/book/cookbook/jupyterlite/wave.ipynb new file mode 100644 index 0000000..4ec2b57 --- /dev/null +++ b/book/cookbook/jupyterlite/wave.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sine wave" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Packages" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coordinates" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(0, 2*np.pi, 100)\n", + "y = np.sin(x)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotting" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(x, y)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "fast", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/jupyterlite-config.json b/jupyterlite-config.json index 7fbf1bb..1a02a78 100644 --- a/jupyterlite-config.json +++ b/jupyterlite-config.json @@ -1,8 +1,9 @@ { - "LiteBuildConfig": { - "federated_extensions": [ - "https://github.com/jupyterlite/pyodide-kernel/releases/download/v0.0.5/jupyterlite_pyodide_kernel-0.0.5-py3-none-any.whl" - ], - "ignore_sys_prefix": true + "XeusPythonEnv": { + "packages": [ + "numpy", + "matplotlib", + "ipywidgets" + ] } } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 501ce69..2c544df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ jupyter-book -sphinx-inline-tabs \ No newline at end of file +sphinx-inline-tabs +jupyterlite-xeus-python +jupyterlite-sphinx \ No newline at end of file From dd29623881bebee11b826434f99f0b70016e6464 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sun, 28 May 2023 13:33:47 +0200 Subject: [PATCH 05/14] Update `jupyterlite.md`, include new sections --- book/_toc.yml | 6 +++++- book/cookbook/jupyterlite.md | 9 --------- book/cookbook/jupyterlite/jupyterlite.md | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) delete mode 100644 book/cookbook/jupyterlite.md create mode 100644 book/cookbook/jupyterlite/jupyterlite.md diff --git a/book/_toc.yml b/book/_toc.yml index 110d88c..3d8a946 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -10,4 +10,8 @@ parts: - caption: Cookbook chapters: - file: cookbook/recipes.md - - file: cookbook/jupyterlite.md \ No newline at end of file + - file: cookbook/jupyterlite/jupyterlite + sections: + - file: cookbook/jupyterlite/configuration + - file: cookbook/jupyterlite/including-jupyterlite + diff --git a/book/cookbook/jupyterlite.md b/book/cookbook/jupyterlite.md deleted file mode 100644 index f16beb3..0000000 --- a/book/cookbook/jupyterlite.md +++ /dev/null @@ -1,9 +0,0 @@ -# Interactive elements with Jupyterlite-Sphinx - -```{eval-rst} -.. replite:: - :kernel: python - :height: 600px - - print("test") -``` \ No newline at end of file diff --git a/book/cookbook/jupyterlite/jupyterlite.md b/book/cookbook/jupyterlite/jupyterlite.md new file mode 100644 index 0000000..df75c2d --- /dev/null +++ b/book/cookbook/jupyterlite/jupyterlite.md @@ -0,0 +1,19 @@ +# Interactive elements with JupyterLite-Sphinx + +By popular demand: how to include interactive pieces of code in your Jupyter Book. We can do this by using the [JupyterLite](https://github.com/jupyterlite) app, which allows you to run a Jupyter Lab session and execute Python code entirely in-browser. Jupyterlite can be embedded in a Jupyter Book with the [`JupyterLite-Sphinx`](https://github.com/jupyterlite/jupyterlite-sphinx) extension. + +## An example + +You can try JupyterLite below. It has `numpy`, `matplotlib` and `scipy` installed. + +```{eval-rst} +.. replite:: + :width: 100% + :height: 600px +``` + +## What you can and can't do + +JupyterLite is ideal for including small interactive pieces of content on a page. For example, you may want to include a `matplotlib` plot with some sliders to play with. Or you may have a small model that requires a student to provide some input parameters and then gives some output. It is important to note that JupyterLite makes use of the browser cache for memory, meaning that the state of a JupyterLite element is lost when the user leaves a page. Hence, it may not be a good idea to ask student to code a lot by hand, as they loose all of their progress when the page is closed. + +It is possible to install packages in the kernel that will be shipped with your book. However, there are some strict limitations to what packages can be installed. For once, they should be listed on `conda-forge`. In addition, the package needs to be a [`noarch`](https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/packages.html#noarch-packages) package. In theory, you can install your own packages if it meets those two requirements, but we have no experience in doing that (feel free to try it out yourself, so that we can add instructions to the manual!). From 35c3f7965b23ad8370e09fa47cdf1d3d2794f036 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sun, 28 May 2023 13:34:14 +0200 Subject: [PATCH 06/14] Add scipy to xeus --- jupyterlite-config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jupyterlite-config.json b/jupyterlite-config.json index 1a02a78..eac0d3a 100644 --- a/jupyterlite-config.json +++ b/jupyterlite-config.json @@ -3,7 +3,8 @@ "packages": [ "numpy", "matplotlib", - "ipywidgets" + "ipywidgets", + "scipy" ] } } \ No newline at end of file From 1047449d8e9fa5eb9fe4e18d3367801c6c8560db Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 3 Jun 2023 12:18:37 +0200 Subject: [PATCH 07/14] Add interactive wave example --- book/_toc.yml | 1 + .../jupyterlite/interactive-wave.ipynb | 91 +++++++++++++++++++ .../jupyterlite/jupyterlite-gallery.md | 11 +++ 3 files changed, 103 insertions(+) create mode 100644 book/cookbook/jupyterlite/interactive-wave.ipynb create mode 100644 book/cookbook/jupyterlite/jupyterlite-gallery.md diff --git a/book/_toc.yml b/book/_toc.yml index 3d8a946..f6354fb 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -14,4 +14,5 @@ parts: sections: - file: cookbook/jupyterlite/configuration - file: cookbook/jupyterlite/including-jupyterlite + - file: cookbook/jupyterlite/jupyterlite-gallery diff --git a/book/cookbook/jupyterlite/interactive-wave.ipynb b/book/cookbook/jupyterlite/interactive-wave.ipynb new file mode 100644 index 0000000..c3be4a8 --- /dev/null +++ b/book/cookbook/jupyterlite/interactive-wave.ipynb @@ -0,0 +1,91 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "%gui asyncio\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from ipywidgets import interact" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGdCAYAAAAfTAk2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABZOklEQVR4nO3deVzUdeIG8GdmgOEQBrlBTi9EQUVUBNM0DTU17VKzUMssN63U3G3t2Kyt+LW7lV1alkeZqZVZWl5o4pF4gIA34skhiCDMAMo18/39AU4Rh6AMnzme9+s1r9c6fmd4Zraah898DpkkSRKIiIiIzIhcdAAiIiKi1saCQ0RERGaHBYeIiIjMDgsOERERmR0WHCIiIjI7LDhERERkdlhwiIiIyOyw4BAREZHZsRIdQASdTofLly/D0dERMplMdBwiIiJqBkmSUFJSAh8fH8jlTY/RWGTBuXz5Mvz8/ETHICIiotuQlZUFX1/fJq+xyILj6OgIoOYNcnJyEpyGiIiImkOj0cDPz0//Od4Uiyw4N7+WcnJyYsEhIiIyMc2ZXsJJxkRERGR2WHCIiIjI7LDgEBERkdlhwSEiIiKzw4JDREREZocFh4iIiMwOCw4RERGZHRYcIiIiMjssOERERGR2DFpw9uzZg7Fjx8LHxwcymQw//fTTLR+ze/duREREwNbWFh07dsRnn31W75r169eje/fuUCqV6N69OzZs2GCA9ERERGSqDFpwysrK0KtXL3zyySfNuv7ChQu47777MGjQIKSkpODll1/G888/j/Xr1+uvSUxMxMSJExEbG4u0tDTExsZiwoQJOHjwoKFeBhEREZkYmSRJUpv8IJkMGzZswPjx4xu95qWXXsLGjRtx6tQp/X0zZ85EWloaEhMTAQATJ06ERqPBli1b9NeMHDkS7du3x5o1a5qVRaPRQKVSQa1W8ywqIiIiE9GSz2+jOmwzMTERMTExde4bMWIEli1bhqqqKlhbWyMxMRFz586td82iRYsafd6KigpUVFTo/6zRaFo1N5kmSZKQX1KBk7ka5BTdQHmVFjcqtSiv1qK8SgcnW2t4O9vCW2ULb5UdfJxtYW9jVP/KEBFRI4zqv9Z5eXnw9PSsc5+npyeqq6tRUFAAb2/vRq/Jy8tr9Hnj4uLwxhtvGCQzmQ6dTkJKVhHiT+bjxGU1Tl7WoLCsstmPl8uAMF9nRHdyxcBObugb2B621goDJiYiottlVAUHqH8E+s1v0P58f0PXNHV0+oIFCzBv3jz9nzUaDfz8/FojLhm5m6Xml6O52HIsD3ma8jp/L5cBHd3bIcjNAQ42Ctha19yUVnIUX69CrqYcucU3kKcuR0lFNdKyipGWVYwlCedgo5BjUBc3TI70x5BgDyjkjf8zSEREbcuoCo6Xl1e9kZj8/HxYWVnB1dW1yWv+OqrzZ0qlEkqlsvUDk9GqrNbhp5QcLNl9DhcKyvT3t1NaYXiIByI7uqK7txOCvRybPQpzufgGEs8VYv+5Quw/V4BcdTl2ns7HztP56OBsh0f7+2FCXz94ONka6mUREVEzGVXBiYqKwqZNm+rct337dvTt2xfW1tb6a+Lj4+vMw9m+fTuio6PbNCsZp/IqLdYeysTSPedxWV0zWtNOaYV7u3vivjBvDOridttfK/k42+GhCF88FOELSZJwNr8U3yVl4fvkbOQU38D/tp/Boh0ZmBzpjxeGdYFrO5ZqIiJRDLqKqrS0FGfPngUAhIeH4/3338fQoUPh4uICf39/LFiwADk5Ofj6668B1CwTDw0NxTPPPIMZM2YgMTERM2fOxJo1a/DQQw8BAPbv34/Bgwfj7bffxrhx4/Dzzz/j1Vdfxb59+xAZGdmsXFxFZX50OgnfJWXhf9vTUVBaM6/Gw1GJpwd3xKP9/eGgNFyXL6/SYsvxXHxzIBPJl4oA1JSqvw3phCcHBsHOhvN0iIhaQ0s+vw1acBISEjB06NB690+dOhUrV67EtGnTcPHiRSQkJOj/bvfu3Zg7dy5OnDgBHx8fvPTSS5g5c2adx//www949dVXcf78eXTq1Alvv/02HnzwwWbnYsExL2eulOCVDcdw+GJNufBtb4eZd3fCwxG+bT4JeP+5Aryz+RSO59Ss1PNW2eKlkd0wrrdPk/PEiIjo1oym4BgrFhzzUF6lxce/ZeDz3edRrZNgb6PAvHu7Ymp0IKwV4k4h0ekkbEy7jP9uS0dO8Q0AwIgennjngTB+bUVEdAdYcG6BBcf0nbyswaxvj+gnEA8P8cQb43qgg7Od4GR/KK/S4os95/HRbxmo0kpwa6fEfx4Owz3dGp8QT0REjWPBuQUWHNP2XVIWXvvpOCqqdfByssUb43pgRA8v0bEadTxHjbnrUpGRXwoAmBzpj1dHh3DTQCKiFmLBuQUWHNNUXqXFv34+ju+SsgEAQ4Ld8cGE3mjvYCM42a2VV2nx323pWLbvAgCgu7cTvpzaFz5GNOJERGTsWvL5LW6iAlELZBZexwOL9+O7pGzIZcD8mK5YPrWfSZQbALC1VuC1Md2x+qlIuLWzwclcDe7/5HekZBaJjkZEZJZYcMjoHc9R48Elv+NUrgauDjZYNT0Ss+/pArkJ7hw8sLMbfpo1EN28HFFQWoGJSw/g59Qc0bGIiMwOCw4Ztd/PFmDi54koKK1Ed28n/Pr8IAzs7CY61h3xbW+PH/4WjeEhHqis1uGFtal4f3s6LPDbYiIig2HBIaO1Ke0ypq04hLJKLaI6umLdMwPgpTKPYxDaKa3weWxfPHN3RwDAR7+dxcKNJ6DTseQQEbUGFhwySit/v4Dn16agSithdE9vrHyyHxxtrUXHalUKuQwLRoXgnQfCIJMBXyVewis/HWPJISJqBSw4ZHSW7buAhZtOQpKAqVEB+HhSOJRW5nvcweRIf/z34V6Qy4A1h7Lw9x+OQsuSQ0R0R7gRBxmVbw5cwr9/OQkAeH5YF8wd3sUijjh4OMIX1goZ5n2XhvVHslGl1eH9Cb1gJXBHZiIiU8b/epLR+CE5G6/+dBwAMPPuThZTbm4a17sDPnk0HFZyGTamXca879L4dRUR0W1iwSGj8MvRy/jHD2kAgGnRgXhpZLBFlZubRoV547PHI/Ql59+/nuTqKiKi28CCQ8LtPHUFc9amQicBj/b3w+tju1tkublpeHdP/O+RXgCAFb9fxGe7zwtORERkelhwSKhj2WrM/jYF1ToJD4R3wFvjwyy63Nw0PrwDXh0dAgB4d+tpfJ+UJTgREZFpYcEhYS4X38D0rw7jRpUWd3d1x38f7gmFCe5ObChPDeqIZwbX7JPzzx+P4bfTVwQnIiIyHSw4JERpRTWeXHkY+SUV6ObliE8mh3PFUANeGtkND4Z3gFYn4dnVR3AsWy06EhGRSeAnCrW5aq0Os789gtN5JXB3VGLZNPPbxK+1yOUyvPtwTwzu6o7yKh2eWZWEgtIK0bGIiIweCw61uX//chIJ6Vdhay3Hl1P6ooOznehIRs1aIcfHj4ajo5sDLqvL8ew3R1BZrRMdi4jIqLHgUJtaeygTXyVegkwGLJrYG738nEVHMgkqO2ssndIXjkorHLp4DW/+ckJ0JCIio8aCQ23meI4a/9pY88E8PyYYI0O9BScyLZ092mHRpN6QyYBvDmTi24OZoiMRERktFhxqE8XXKzHzm2RUVuswPMQTf7u7k+hIJmlYiCfmxwQDAF7feByHL14TnIiIyDix4JDB6XQS5n2XhuyiG/B3scd7E3pBzuXgt+3ZIZ0wOswbVVoJs1YfQSEnHRMR1cOCQwa3ZPc5/HY6HzZWcix+rA9UdlwxdSdkMhn++0hPdPZoh/ySCrz4Pc+sIiL6KxYcMqjfzxbgve3pAIC3xoUitINKcCLzYG9jhU8mh0NpJUdC+lUs23dBdCQiIqPCgkMGU1hagRdqz5ia0NcXE/r5iY5kVrp5OeFfY7sDqDnOITWrWGwgIiIjwoJDBiFJEl5afwwFpRXo6tkOb44LFR3JLE3u74/7wrxQrZPw3Joj0JRXiY5ERGQUWHDIINYezsKOU1dgo5Bj0cRw2ForREcySzKZDHEP9oRveztkXbuBBT8egyRxPg4REQsOtbrzV0vx5qaTAIC/jwhGdx8nwYnMm8rOGh8/Gg4ruQy/Hs3F98nZoiMREQnHgkOtqkqrw9x1qbhRpUV0J1dMvytIdCSLEO7fHvNiugIA/r3pJC4X3xCciIhILBYcalUf7cxAWrYaKjtr7nfTxp4Z3Anh/s4oqajGP344yq+qiMiiseBQq0m+VIRPd50FALzzQBi8VTxEsy0p5DK890gv2FrLse9sAb7hUQ5EZMHapOAsXrwYQUFBsLW1RUREBPbu3dvotdOmTYNMJqt369Gjh/6alStXNnhNeXl5W7wcakB5lRZ//yENOgl4sE8HjO7Jc6ZE6OjeDv8Y0Q0AELf5FC4VlglOREQkhsELzrp16zBnzhy88sorSElJwaBBgzBq1ChkZjb82+WHH36I3Nxc/S0rKwsuLi545JFH6lzn5ORU57rc3FzY2toa+uVQIz7amYHzV8vg7qjE62N63PoBZDDTogMRGeSC65Va/P37o9zlmIgsksELzvvvv4/p06fjqaeeQkhICBYtWgQ/Pz8sWbKkwetVKhW8vLz0t6SkJBQVFeGJJ56oc51MJqtznZeXl6FfCjXieI4an+85DwB4a3woVPY8ikEkuVyG/z3SCw42Chy6eA3Lf+cux0RkeQxacCorK5GcnIyYmJg698fExGD//v3Neo5ly5Zh+PDhCAgIqHN/aWkpAgIC4OvrizFjxiAlJaXR56ioqIBGo6lzo9ZRpdXhHz8chVYnYXRPb4zowaJpDPxc7PHK6Jpdjv+3PR2ZhdcFJyIialsGLTgFBQXQarXw9PSsc7+npyfy8vJu+fjc3Fxs2bIFTz31VJ37u3XrhpUrV2Ljxo1Ys2YNbG1tMXDgQGRkZDT4PHFxcVCpVPqbnx+PDGgtn+8+h5O5GjjbW2PhWH41ZUwe7e+H6E6uKK/S4ZWfuAEgEVmWNplkLJPVXSosSVK9+xqycuVKODs7Y/z48XXuHzBgAB5//HH06tULgwYNwnfffYeuXbvi448/bvB5FixYALVarb9lZWXd9muhP2RcKcFHO2tWTb0+tjvcHZWCE9GfyWQyvP1AGGys5NibUYCNaZdFRyIiajMGLThubm5QKBT1Rmvy8/Prjer8lSRJWL58OWJjY2FjY9PktXK5HP369Wt0BEepVMLJyanOje6MTifhpfVHUanVYWiwO8b37iA6EjUgyM0Bzw3tDAB4c9NJFF+vFJyIiKhtGLTg2NjYICIiAvHx8XXuj4+PR3R0dJOP3b17N86ePYvp06ff8udIkoTU1FR4e3Npclv5LikLRzKL4WCjwNsPhDVrRI7EeObuTuji0Q6FZZWI23xadBwiojZh8K+o5s2bhy+//BLLly/HqVOnMHfuXGRmZmLmzJkAar4+mjJlSr3HLVu2DJGRkQgNrX8K9RtvvIFt27bh/PnzSE1NxfTp05Gamqp/TjKsa2WV+L+tNR+U82KC4ePMDf2MmY2VHO88GAYAWJeUhQPnCwUnIiIyPCtD/4CJEyeisLAQb775JnJzcxEaGorNmzfrV0Xl5ubW2xNHrVZj/fr1+PDDDxt8zuLiYjz99NPIy8uDSqVCeHg49uzZg/79+xv65RCAd7ecRvH1KnTzcsTUqIBbP4CE6xfogkf7+2PNoUy8vOEYtrwwCEornvBOROZLJlng0gqNRgOVSgW1Ws35OC2UfOkaHlqSCABY/7coRAS4CE5EzaW+XoVh7+9GQWkF5t3bFc8P6yI6EhFRi7Tk85tnUVGzVWt1eGXDcQDAxL5+LDcmRmVvjdfGhAAAFiecRXYR98YhIvPFgkPN9lXiJZzOK4GzvTVeGtVNdBy6Dff38kH/IBeUV+nwzuZTouMQERkMCw41yxVNOT6IPwMAeGlkN7g4NL10n4yTTCbDG/f3gFwGbD6Wh9/PFoiORERkECw41Cz/t+U0Siuq0dvPGRP7cidoUxbi7YTYATWTwxduPIEqrU5wIiKi1seCQ7d0JLMIG1JyIJMB/x4XCrmce96Yunn3BsPFwQYZ+aX4OvGS6DhERK2OBYeapNNJeHPTSQDAw318EearEpyIWoPK3hp/HxEMAFgUfwZXSyoEJyIial0sONSkjWmXkZpVs2PxzQ9EMg8T+vqhp68KJRXV+M9W7nBMROaFBYcadb2yGv+3peaD79mhneHhZCs4EbUmhbxmwjEAfJ+cjeM5asGJiIhaDwsONeqz3eeRpymHn4sdpt8VJDoOGUC4f3s8EF5zUOpbv56EBe77SURmigWHGpRTfAOf7z4HAHh5VAhsrbmtv7maPyIYSis5Dpy/hh2n8kXHISJqFSw41KB3t5xGRbUO/YNcMDLUS3QcMqAOzn+M0MVtPsVl40RkFlhwqJ7UrGJsTLsMmQz415jukMm4LNzc/W1IJ7g62OB8QRnWHMq89QOIiIwcCw7VIUkS4mq38H+ojy9CO3BZuCVwtLXGnHu7AgAW7ciAprxKcCIiojvDgkN17ErPx8EL16C0kmNe7QceWYZH+/mhs0c7XCurxKe7zoqOQ0R0R1hwSE+rk/TLwqcNDISPs53gRNSWrBRyvHxfzSGqK/ZdRNY1njZORKaLBYf01idn48yVUqjsrPHs3Z1FxyEBhgZ7YGBnV1RqdXhve7roOEREt40FhwAANyq1eL/2tPDZQztDZW8tOBGJIJPJsGBUCADg57TLOJWrEZyIiOj2sOAQAGDF/gvI05Sjg7MdYqMCRMchgUI7qDCmpzckCfjfNo7iEJFpYsEhFJVVYklCzaZ+80d05aZ+hBdjgqGQy7DzdD4OX7wmOg4RUYux4BA+3XUWJeXV6O7thHG9OoiOQ0YgyM0BE/r6AajZ9JFHOBCRqWHBsXB56nJ8feASAOAfI4Mhl3NTP6rxwrAuUFrJkXSpCLvSeYQDEZkWFhwL9/FvGais1qF/oAvu7uouOg4ZES+VLaYNDAQA/GdrOnQ6juIQkelgwbFgmYXXse5wFgDgxZiuPJKB6vnb3Z3gaGuF03kl2Jh2WXQcIqJmY8GxYB/uzEC1TsKgLm6I7OgqOg4ZIWd7G8y8uxMA4L34dFRW8yBOIjINLDgW6mx+CTakZAMA5scEC05DxuyJgYFwa6dE1rUb+CE5W3QcIqJmYcGxUB/EZ0AnATHdPdHLz1l0HDJi9jZWeHZIzSjOJ79loKJaKzgREdGtseBYoBOX1fj1WC5kMmBeDA/UpFubHOkPTyclLqvL8V3tvC0iImPGgmOB3t9ecyTD2J4+6OblJDgNmQJbawVmDa05n+yTXWdRXsVRHCIybiw4FiYlswg7T+dDIZdh7r0cvaHmm9jPD94qW1zRVGDNoUzRcYiImsSCY2E+3JkBAHgwvAOC3BwEpyFTorRSYPY9NaM4ixPO4UYlR3GIyHix4FiQ1KxiJKRfhUIu039QEbXEIxF+6OBsh6slFVh98JLoOEREjWqTgrN48WIEBQXB1tYWERER2Lt3b6PXJiQkQCaT1budPn26znXr169H9+7doVQq0b17d2zYsMHQL8PkfbijZu7NA+EdEODK0RtqORsrOZ4fVlOOlyScw/XKasGJiIgaZvCCs27dOsyZMwevvPIKUlJSMGjQIIwaNQqZmU1/h5+eno7c3Fz9rUuXLvq/S0xMxMSJExEbG4u0tDTExsZiwoQJOHjwoKFfjslKyyrGrpujN0M5ekO378E+vvB3sUdhWSW+2s9RHCIyTjLJwMcER0ZGok+fPliyZIn+vpCQEIwfPx5xcXH1rk9ISMDQoUNRVFQEZ2fnBp9z4sSJ0Gg02LJli/6+kSNHon379lizZs0tM2k0GqhUKqjVajg5WcYqoidXHsZvp/PxUB9fvDehl+g4ZOJ+SM7G/O/T4OJgg30vDYW9jZXoSERkAVry+W3QEZzKykokJycjJiamzv0xMTHYv39/k48NDw+Ht7c3hg0bhl27dtX5u8TExHrPOWLEiEafs6KiAhqNps7NkhzNLsZvp/Mhl4Fzb6hVjOvtA38Xe1wrq8S3B7miioiMj0ELTkFBAbRaLTw9Pevc7+npiby8vAYf4+3tjaVLl2L9+vX48ccfERwcjGHDhmHPnj36a/Ly8lr0nHFxcVCpVPqbn5/fHb4y0/LhjpqVU+N7c+UUtQ5rhVy/u/Hne85zXxwiMjptMq7811OqJUlq9OTq4OBgBAf/cTZSVFQUsrKy8L///Q+DBw++redcsGAB5s2bp/+zRqOxmJJzLFuNnRy9IQN4sI8vPv7tLHKKb2Dd4SxMjQ4UHYmISM+gIzhubm5QKBT1Rlby8/PrjcA0ZcCAAcjIyND/2cvLq0XPqVQq4eTkVOdmKW7uezOudwd0dG8nOA2ZExsrOWbe3REA8NnuczyjioiMikELjo2NDSIiIhAfH1/n/vj4eERHRzf7eVJSUuDt7a3/c1RUVL3n3L59e4ue0xKcztNgx6krkMmg32afqDU90tcPnk5K5KrLsT45R3QcIiI9g39FNW/ePMTGxqJv376IiorC0qVLkZmZiZkzZwKo+fooJycHX3/9NQBg0aJFCAwMRI8ePVBZWYlvvvkG69evx/r16/XP+cILL2Dw4MF49913MW7cOPz888/YsWMH9u3bZ+iXY1I+3XUOAHBfqDc6e3D0hlqfrbUCzwzuhDd/OYnFCWfxSF9fWCu4fygRiWfwgjNx4kQUFhbizTffRG5uLkJDQ7F582YEBAQAAHJzc+vsiVNZWYn58+cjJycHdnZ26NGjB3799Vfcd999+muio6Oxdu1avPrqq3jttdfQqVMnrFu3DpGRkYZ+OSbj/NVS/Hr0MgCO3pBhPdrfH4sTziK76AZ+SsnBI30tY34bERk3g++DY4wsYR+cv3+fhu+TszGsmweWTesnOg6Zuc93n0PcltMIcnPAjnl3QyFveMI/EdGdMJp9cEiM7KLr2JBSMx9iFldOURt4fEAA2ttb40JBGX49lis6DhERC445WrrnPKp1EqI7uaKPf3vRccgCOCit8MTAIADA4l1nYYEDw0RkZFhwzEx+STnWHs4CAJ45RW1qalQgHGwUOJ1Xgl3p+aLjEJGFY8ExM8v2XkBltQ7h/s6I6uQqOg5ZEJW9NR4bULN4YHHtCj4iIlFYcMxI8fVKfHOg5nTn2UM7N7qzM5GhTL8rCDYKOZIuFeHQhWui4xCRBWPBMSNfJ15CWaUWId5OuKebh+g4ZIE8nWzxUIQvAGBxwlnBaYjIkrHgmIkblVqs3H8RAPC3IZ04ekPCzLy7I+QyICH9Kk5cVouOQ0QWigXHTHyXlIVrZZXwc7HDfaFeouOQBQtwdcDonj4AgMUJnItDRGKw4JiBKq0OS/ecBwA8PagjrLhVPgn2t7s7AQC2HMvFhYIywWmIyBLxk9AM/Ho0FznFN+DqYMNt8skodPdxwtBgd+ikml2OiYjaGguOiZMkCZ/VfoA8MTAQttYKwYmIajxbuw/Tj0dykK8pF5yGiCwNC46JS0i/itN5JXCwUSB2QKDoOER6/QJdEBHQHpVaHVbUToAnImorLDgmbknt6M2j/f2hsrcWnIaormcGdwQAfHPgEkrKqwSnISJLwoJjwpJrN1OzVsgwfVCQ6DhE9QwP8URHdweUlFdj7aEs0XGIyIKw4Jiwm5M3x/fuAG+VneA0RPXJ5TI8PahmFGf57zXHiBARtQUWHBN17mop4k9dAQA8c3dHwWmIGjc+vAPcHZXIVZdjU9pl0XGIyEKw4JioL/degCQBw0M80NnDUXQcokbZWivwxMBAAMDne85BkiSxgYjIIrDgmKCC0gqsP5INAJgxiKM3ZPweiwyAg40CZ66UIiH9qug4RGQBWHBM0NeJl1BZrUMvXxX6B7mIjkN0Syo7a0yO9AcA/b5NRESGxIJjYm5UarEq8SIA4OnBPFSTTMcTA4NgJZfh4IVrSM0qFh2HiMwcC46J+SE5C0XXq+DnYocRPTxFxyFqNh9nO9zfu+YQzi/2nhechojMHQuOCdHqJHy57wIA4Km7eKgmmZ6n7qqZM7blWC6yrl0XnIaIzBk/IU3I9hN5uFR4HSo7azzS11d0HKIW6+7jhLs6u0EnASt+vyg6DhGZMRYcEyFJEj7fUzOsHzsgAPY2VoITEd2ep2p33V53OBPqGzy+gYgMgwXHRCRfKkJqVjFsFHJMjQ4UHYfott3d1R1dPduhrFKLtYcyRcchIjPFgmMibk7KfKB2V1giUyWTyfRzcVb8fpHHNxCRQbDgmIBLhWXYfrLmWAYeqknmYFy4D9zaKZGnKcevx3h8AxG1PhYcE7Di94uQpJtD+zyWgUyf0kqBqVEBAIAv9lzg8Q1E1OpYcIyc+kYVvkvKAvDH5Ewic/D4gADYWstxMleDxHOFouMQkZlhwTFyaw9l4nqlFsGejrirs5voOEStpr2DDR6OqNnugBv/EVFrY8ExYlVaHVbuvwigZu4Nj2UgczP9ro6QyYBd6VdxNr9UdBwiMiNtUnAWL16MoKAg2NraIiIiAnv37m302h9//BH33nsv3N3d4eTkhKioKGzbtq3ONStXroRMJqt3Ky8vN/RLaVObj+UiV10Ot3ZKjKvd4p7InAS5OWBYt5ojR1b8fkFwGiIyJwYvOOvWrcOcOXPwyiuvICUlBYMGDcKoUaOQmdnw/hd79uzBvffei82bNyM5ORlDhw7F2LFjkZKSUuc6Jycn5Obm1rnZ2toa+uW0GUmSsKz2WIapUQFQWikEJyIyjOl31cwtW38kG0VllYLTEJG5MHjBef/99zF9+nQ89dRTCAkJwaJFi+Dn54clS5Y0eP2iRYvwj3/8A/369UOXLl3wzjvvoEuXLti0aVOd62QyGby8vOrczMnhi0U4mq2G0kqOxwYEiI5DZDADOrqgu7cTyqt0+JYb/xFRKzFowamsrERycjJiYmLq3B8TE4P9+/c36zl0Oh1KSkrg4uJS5/7S0lIEBATA19cXY8aMqTfC82cVFRXQaDR1bsbuy9pJlw9F+MLFwUZwGiLDkclk+lGcrxO58R8RtQ6DFpyCggJotVp4enrWud/T0xN5eXnNeo733nsPZWVlmDBhgv6+bt26YeXKldi4cSPWrFkDW1tbDBw4EBkZGQ0+R1xcHFQqlf7m5+d3+y+qDWQWXkf8qZqN/Z4cyKXhZP7G9vKBu6MSVzQV2HwsV3QcIjIDbTLJ+K+rfyRJataKoDVr1mDhwoVYt24dPDw89PcPGDAAjz/+OHr16oVBgwbhu+++Q9euXfHxxx83+DwLFiyAWq3W37Kysu7sBRnYiv0XIEnAkGB3dPZoJzoOkcHZWMkxpfar2GX7uPEfEd05gxYcNzc3KBSKeqM1+fn59UZ1/mrdunWYPn06vvvuOwwfPrzJa+VyOfr169foCI5SqYSTk1Odm7EqKa/C90nZADh6Q5blsQEBUFrJcSxHjcMXi0THISITZ9CCY2Njg4iICMTHx9e5Pz4+HtHR0Y0+bs2aNZg2bRq+/fZbjB49+pY/R5IkpKamwtvb+44zi/ZdUjZKK6rR2aMdBnXhxn5kOVwcbPBgnw4AgGX7uPEfEd0Zg39FNW/ePHz55ZdYvnw5Tp06hblz5yIzMxMzZ84EUPP10ZQpU/TXr1mzBlOmTMF7772HAQMGIC8vD3l5eVCr1fpr3njjDWzbtg3nz59Hamoqpk+fjtTUVP1zmiqtTsLK/TVLw58cyI39yPLcHLXcfvIKMguvC05DRKbM4AVn4sSJWLRoEd5880307t0be/bswebNmxEQUPN9e25ubp09cT7//HNUV1dj1qxZ8Pb21t9eeOEF/TXFxcV4+umnERISgpiYGOTk5GDPnj3o37+/oV+OQe04dQVZ126gvb21/jdZIkvSxdMRg7u6Q5Kg38WbiOh2yCQLnM2n0WigUqmgVquNaj7OxM8TcfDCNcwa2gl/H9FNdBwiIRLS8zFtxWG0U1ohccE9cLS1Fh2JiIxESz6/eRaVkTieo8bBC9dgJZchdkCg6DhEwgzu4o5O7g4orajGD8nZouMQkYliwTESy2vP4Rnd0xteKvM5coKopeRyGabVzsX5av9F6HQWN8hMRK2ABccI5JeUY1PaZQDAE1waToSH+nSAk60VLhZex670fNFxiMgEseAYgW8OZKJKKyEioD16+zmLjkMknL2NFR7t7w/gj9FNIqKWYMERrKJai28PXgIAPDEwUGwYIiMSGxUAuQz4/Wwh0vNKRMchIhPDgiPYL2m5KCithLfKFiN6mNeJ6ER3wre9vf7fiRUcxSGiFmLBEUiSJKyo3dgvNioA1gr+30H0Z0/WnjK+ISUH18oqBachIlPCT1SBki4V4XiOBkorOR7t5y86DpHR6RvQHqEdnFBRrcOaQ5m3fgARUS0WHIFW/n4RAPBAeAe0d7ARG4bICMlkMjwRXTOK83XiRVRpdYITEZGpYMER5HLxDWw9UXPK+jROLiZq1Jhe3nBrp8QVTQW2Hs8THYeITAQLjiBfJ16CVichupMrunkZz3ERRMZGaaXAY5E1X+HyfCoiai4WHAFuVGr18wmmRQeKDUNkAh6L9Ie1QobkS0U4ml0sOg4RmQAWHAF+Ss2B+kYV/FzsMCzEU3QcIqPn4WSL0WHeAP6Yu0ZE1BQWnDYmSZL+P9BTowKhkMvEBiIyETePMdl09DLyS8oFpyEiY8eC08YSzxUi/UoJ7G0UmNDPT3QcIpPRy88Z4f7OqNJKWHMwS3QcIjJyLDhtbEXtJMmHI3zhZGstNgyRibk5Z+2bg5dQWc0l40TUOBacNpR17Tp2nLoCAJgSFSg2DJEJGhXqDQ9HJa6WVGDzsVzRcYjIiLHgtKGvEy9CkoDBXd3R2aOd6DhEJsfGSo7YAQEA/hgNJSJqCAtOGymrqMbawzXzBqZFBwhOQ2S6Ho30h41CjrSsYqRkFomOQ0RGigWnjWxIyUFJeTUCXO0xpKuH6DhEJsutnRJje/kAAFZwyTgRNYIFpw1IkqTfgXVqVCDkXBpOdEduTjbefCwX+RouGSei+lhw2sDvZwtxNr8UDjYKPNzXV3QcIpMX5qtC34D2qNZJWH2Qp4wTUX0sOG1gJZeGE7W6qbWjOKsPZnLJOBHVw4JjYJmF17HzdO3ScJ47RdRqRoZ6wdNJiYJSLhknovpYcAzsz0vDO7lzaThRa7FWcMk4ETWOBceAyiqqsS6JS8OJDGVSfy4ZJ6KGseAY0M2l4YFcGk5kEH9eMv4VR3GI6E9YcAxEkiT9f3CncGk4kcHcXDL+67FcnjJORHosOAay/1whMvJLYc+l4UQGFearQkRAe1RpJXzLJeNEVIsFx0BuLg1/qA+XhhMZmv6U8QNcMk5ENVhwDODPp4ZP5eRiIoP785LxLce5ZJyI2qjgLF68GEFBQbC1tUVERAT27t3b5PW7d+9GREQEbG1t0bFjR3z22Wf1rlm/fj26d+8OpVKJ7t27Y8OGDYaK32KrDlyCJAGDurihs4ej6DhEZs9aIcfjkbVLxnk+FRGhDQrOunXrMGfOHLzyyitISUnBoEGDMGrUKGRmNvxd+YULF3Dfffdh0KBBSElJwcsvv4znn38e69ev11+TmJiIiRMnIjY2FmlpaYiNjcWECRNw8OBBQ7+cW7peWY21h2pe2zRu7EfUZm6eMp6aVYy0rGLRcYhIMJkkSZIhf0BkZCT69OmDJUuW6O8LCQnB+PHjERcXV+/6l156CRs3bsSpU6f0982cORNpaWlITEwEAEycOBEajQZbtmzRXzNy5Ei0b98ea9asuWUmjUYDlUoFtVoNJyenO3l59Xx7MBMvbzgGfxd77Jo/BAquniJqM/PWpeLHlBw8GN4B70/sLToOEbWylnx+G3QEp7KyEsnJyYiJialzf0xMDPbv39/gYxITE+tdP2LECCQlJaGqqqrJaxp7zoqKCmg0mjo3Q6i7NDyA5Yaojd08n2rT0cu4WlIhNgyRharS6jB95WFsSMlGlVbcpH+DFpyCggJotVp4enrWud/T0xN5eXkNPiYvL6/B66urq1FQUNDkNY09Z1xcHFQqlf7m5+d3uy+pSQfOX0P6lRLYWSvwSF/D/AwialwvP2eE+zujSithzSEuGScSYcvxPOw8nY93Np+GYb8jalqbTDKWyeqOZEiSVO++W13/1/tb8pwLFiyAWq3W37KyslqUv7m6+zjh1dEheHZIJ6jsuDScSIQ/loxfEvrbI5GluvlNxmOR/rCxErdY28qQT+7m5gaFQlFvZCU/P7/eCMxNXl5eDV5vZWUFV1fXJq9p7DmVSiWUSuXtvoxmU9lZ46lBHQ3+c4iocaNCvfGW4ynkl1Rgy/E83F97lAMRGd6xbDWSLxXBWiHD5Eh/oVkMWq1sbGwQERGB+Pj4OvfHx8cjOjq6wcdERUXVu3779u3o27cvrK2tm7ymseckIsthYyXHY7X/YeX5VERt6+Ymt6PDvOHhaCs0i8HHjubNm4cvv/wSy5cvx6lTpzB37lxkZmZi5syZAGq+PpoyZYr++pkzZ+LSpUuYN28eTp06heXLl2PZsmWYP3++/poXXngB27dvx7vvvovTp0/j3XffxY4dOzBnzhxDvxwiMgGTI/1hrZAh+VIRjmWrRcchsggFpRXYlHYZwB8T/kUyeMGZOHEiFi1ahDfffBO9e/fGnj17sHnzZgQE1GzKlZubW2dPnKCgIGzevBkJCQno3bs3/v3vf+Ojjz7CQw89pL8mOjoaa9euxYoVK9CzZ0+sXLkS69atQ2RkpKFfDhGZAA9HW4wO8wbwx2+URGRYaw9lolKrq53s3150HMPvg2OMDLkPDhEZh5TMIjyweD9sFHLsX3AP3NoZfh4ekaWq0upw17u/4YqmAh9M7IUHwg1zyLTR7INDRCRKuH979PJzRqVWp99dnIgMY9uJPFzRVMCtnRL31Y6eisaCQ0Rma1rtYberuGScyKBW1p4BNznSH0orhdgwtVhwiMhs3RfmDbd2SlzRVGDbiYY3AiWiO3M8R42kS0WwksvwuOCl4X/GgkNEZktppdDvxbGSp4wTGcTN7RjuC/OGh5PYpeF/xoJDRGbt8Uh/WMllSLpUhOM5XDJO1JoKSyvwsxEtDf8zFhwiMmseTrYY3ZNLxokMYe3hLFRW69DLV4U+/s6i49TBgkNEZu/mb5Yb0y6jsJSnjBO1hiqtDqsSLwGo+XesqTMmRWDBISKzF+7njF6+KlRW67D2sGEO2yWyNNtO5CFPUw63djb6UVJjwoJDRGZPJpPpR3FWJXLJOFFruDm5eHJkgNEsDf8zFhwisgije3rDrZ0N8jTlXDJOdIeO56hx+KLxLQ3/MxYcIrIINUvGazb+45JxojujPzW8p3EtDf8zFhwishh/XjLOU8aJbk9BaQU2phrn0vA/Y8EhIovBJeNEd05/arivCuF+zqLjNIoFh4gsyhMDgwAAm9Iu42oJl4wTtUSVVodVB2qWhk8baHxLw/+MBYeILEpvP2f0rj1lfA1PGSdqka3Hje/U8Maw4BCRxXliYCAA4JsDl1BZzSXjRM214vcLAIzr1PDGsOAQkcUZFeoND0cl8ksqsOV4rug4RCYhLasYRzKLYa2Q4fEBxrk0/M9YcIjI4thYyfH4gJol4yu4ZJyoWW5OzB/T0wcejsa5NPzPWHCIyCI92t8fNgo5UrOKkZJZJDoOkVHL15Tjl6M1S8NvfsVr7FhwiMgiuTsqMaYXl4wTNcc3BzNRpZUQEdAePX2dRcdpFhYcIrJYT0TXLBn/9WgurmjKBachMk4V1Vp8e7B2abgRb+z3Vyw4RGSxwnxV6BfYHtU6Cd/U7u1BRHX9kpaLgtJKeDnZYmSol+g4zcaCQ0QW7ebGf6sPZqK8Sis4DZFxkSQJK/bXLA2PjQqAtcJ0aoPpJCUiMoCY7p7o4GyHa2WV+vN1iKhG8qUiHM/RQGklx6P9jX9p+J+x4BCRRbNSyDElqmbJ+PLfL0CSJMGJiIzHzW0UxvfuABcHG7FhWogFh4gs3qR+/rCzVuB0XgkOnL8mOg6RUcgpvoGtJ/IA1Jw7ZWpYcIjI4qnsrfFQRAcANaM4RAR8vf8itDoJ0Z1cEeLtJDpOi7HgEBEBmFa7ZHzHqSvILLwuOA2RWGUV1frDaJ+snYhvalhwiIgAdPZoh8Fd3SFJwFeJF0XHIRLqxyPZ0JRXI9DVHvd08xAd57aw4BAR1Xqydp7Bd4ezUFpRLTYMkSA6naSfXPzEwCDI5TKxgW4TCw4RUa3BXdzRyd0BJRXV+D4pS3QcIiF2n7mK8wVlcLS1wsMRvqLj3DaDFpyioiLExsZCpVJBpVIhNjYWxcXFjV5fVVWFl156CWFhYXBwcICPjw+mTJmCy5fr7k0xZMgQyGSyOrdJkyYZ8qUQkQWQy2WYVjvfYMXvNRMsiSzNzYn2k/r5wUFpJTjN7TNowZk8eTJSU1OxdetWbN26FampqYiNjW30+uvXr+PIkSN47bXXcOTIEfz44484c+YM7r///nrXzpgxA7m5ufrb559/bsiXQkQW4qE+HaCys0bmtevYceqK6DhEbSo9rwR7MwoglwFTogJFx7kjBqtmp06dwtatW3HgwAFERkYCAL744gtERUUhPT0dwcHB9R6jUqkQHx9f576PP/4Y/fv3R2ZmJvz9/9hF0d7eHl5epnMmBhGZBnsbK0yO9MeShHNYtu8CRvTgf2fIcqyoHb0Z0cMLfi72gtPcGYON4CQmJkKlUunLDQAMGDAAKpUK+/fvb/bzqNVqyGQyODs717l/9erVcHNzQ48ePTB//nyUlJQ0+hwVFRXQaDR1bkREjZkaFQgruQyHLlzD8Ry16DhEbaKwtAI/puQAAJ68yzSXhv+ZwQpOXl4ePDzqLy3z8PBAXl5es56jvLwc//znPzF58mQ4Of2xydBjjz2GNWvWICEhAa+99hrWr1+PBx98sNHniYuL088DUqlU8PPza/kLIiKL4aWyxeie3gCA5fu48R9Zhm8PZqKyWoewDir0DWgvOs4da3HBWbhwYb0Jvn+9JSUlAQBksvpLyyRJavD+v6qqqsKkSZOg0+mwePHiOn83Y8YMDB8+HKGhoZg0aRJ++OEH7NixA0eOHGnwuRYsWAC1Wq2/ZWVxdQQRNW167W+wm45eRr6mXHAaIsOqqNbi6wOXAABP3hXYrM9pY9fiOTizZ8++5YqlwMBAHD16FFeu1J+gd/XqVXh6ejb5+KqqKkyYMAEXLlzAb7/9Vmf0piF9+vSBtbU1MjIy0KdPn3p/r1QqoVQqm3wOIqI/6+nrjH6B7XH4YhG+TryE+SPqzxskMheb0nJxtaQCXk62GB3mIzpOq2hxwXFzc4Obm9str4uKioJarcahQ4fQv39/AMDBgwehVqsRHR3d6ONulpuMjAzs2rULrq6ut/xZJ06cQFVVFby9vZv/QoiIbmH6XUE4fLEIqw9ewux7OsPWWiE6ElGrkyQJX+49DwCYGh0IGyvz2CLPYK8iJCQEI0eOxIwZM3DgwAEcOHAAM2bMwJgxY+qsoOrWrRs2bNgAAKiursbDDz+MpKQkrF69GlqtFnl5ecjLy0NlZSUA4Ny5c3jzzTeRlJSEixcvYvPmzXjkkUcQHh6OgQMHGurlEJEFure7F/xc7FB0vQo/HskRHYfIIPafK8TpvBLYWSswub//rR9gIgxa01avXo2wsDDExMQgJiYGPXv2xKpVq+pck56eDrW6ZpVCdnY2Nm7ciOzsbPTu3Rve3t76282VVzY2Nti5cydGjBiB4OBgPP/884iJicGOHTugUPC3KyJqPQq5TH8I57J956Hjxn9khm6O3kzo6wuVvbXgNK1HJkmSxf0bq9FooFKpoFarbzm/h4gsW0l5FaLjfkNJRTWWT+uLe7o1PYeQyJSczS/B8Pf3QCYDdr04BIFuDqIjNakln9/m8UUbEZGBONpaY1L/mq0lvtjDJeNkXpbtuwgAuDfE0+jLTUux4BAR3cK0gUFQyGVIPF/Ijf/IbBSWVuDHI9kAgKcGdRScpvWx4BAR3UIHZzuMqd347+Z8BSJTt/pgJiqqdejpq0K/QNPf2O+vWHCIiJphRu1vuJuO5uJy8Q3BaYjuTHmVFl8n1mzsN/2uILPY2O+vWHCIiJohtIMKAzq6QKuTsHL/RdFxiO7Iz6k5KCitgLfKFveFmececiw4RETNdHMUZ83BTJSUVwlOQ3R7dDoJS/fUfNX65MAgWCvMswqY56siIjKAocEe6OjugJKKaqw7zDPtyDTtSs/HuatlcFRa6VcImiMWHCKiZpLLZXjqrppRnBW/X0S1Vic4EVHLfV47ejM50h+Otuazsd9fseAQEbXAg306wNXBBjnFN7D5eJ7oOEQtkppVjEMXrsFKLsO0gYGi4xgUCw4RUQvYWisQGxUAAFi65xwscDN4MmFf1G5zcH9vH3ir7ASnMSwWHCKiFpoSFQhbazmO52iw/1yh6DhEzZJZeB1bjuUC+GPCvDljwSEiaiEXBxtM7FszOfPmfAYiY7f89wvQScDgru4I8Tb/cxhZcIiIbsNTgzpCLgP2nLmKk5c1ouMQNamorFK/8u9pCxi9AVhwiIhui5+LvX6DtKV7zglOQ9S0bw5cwo0qLbp7O2FgZ1fRcdoECw4R0W16ZnAnADXHN2QXXRechqhh5VVa/e7bTw/uaJbHMjSEBYeI6DaF+aowsLMrtDoJy/ddFB2HqEHfJ2WhsKyyzqGxloAFh4joDtwcxVl7OBPq6zy+gYxLtVaHpbVLw58e3BFWZnosQ0Ms55USERnAoC5uCPF2wvVKLb45eEl0HKI6fj2Wi6xrN+DiYIMJfc33WIaGsOAQEd0BmUyGZwbfPL7hAsqrtIITEdWQJAmf7a4ZvZkWHQg7G4XgRG2LBYeI6A6N7umNDs52KCitxPdJPISTjMPuM1dxKlcDexsFptTuvm1JWHCIiO6QtUKOZ+6uGcX5fM95HsJJRuGz3TXbFzza3x/O9jaC07Q9FhwiolYwoa8f3NrZILvoBjYdvSw6Dlm4lMwiHDhfc6jm9LuCRMcRggWHiKgV2For8MTAmg+SJQnnoNPxEE4S5+bozfjwDvBxNu9DNRvDgkNE1EpiowLgqLTCmSul2Hk6X3QcslBn80ux/eQVAMDMuy3jWIaGsOAQEbUSJ1trPF47mfPTXWchSRzFoba3OOEsJAmI6e6Jzh6OouMIw4JDRNSKnhwYBKWVHKlZxUg8Xyg6DlmYrGvX8XNqzRyw2fd0FpxGLBYcIqJW5O6o1G+otiSBh3BS2/ps9zlodRIGdXFDT19n0XGEYsEhImplTw/uCIVchr0ZBTiWrRYdhyzEFU05vk/KBgDMHmrZozcACw4RUavzc7HH/b18AACf7MoQnIYsxRd7zqNSq0O/wPaI7OgqOo5wLDhERAbw7JBOkMmAbSeu4HSeRnQcMnPXyiqx+mAmAGAWR28AsOAQERlEF09H3BfqDQD45LezgtOQuVvx+wXcqNIirIMKd3d1Fx3HKBi04BQVFSE2NhYqlQoqlQqxsbEoLi5u8jHTpk2DTCarcxswYECdayoqKvDcc8/Bzc0NDg4OuP/++5GdnW3AV0JE1HI3V7H8eiwXZ/NLBKchc6Upr8LK/RcBALOGdoJMJhMbyEgYtOBMnjwZqamp2Lp1K7Zu3YrU1FTExsbe8nEjR45Ebm6u/rZ58+Y6fz9nzhxs2LABa9euxb59+1BaWooxY8ZAq+UpvkRkPEK8nXBvd09IEvDpLq6oIsNYlXgJJeXV6OLRDjHdvUTHMRpWhnriU6dOYevWrThw4AAiIyMBAF988QWioqKQnp6O4ODgRh+rVCrh5dXw/0lqtRrLli3DqlWrMHz4cADAN998Az8/P+zYsQMjRoxo/RdDRHSbnr+nC+JPXsHPqTl4YVgXBLo5iI5EZqSsohpf7j0PAHh2aCfI5Ry9uclgIziJiYlQqVT6cgMAAwYMgEqlwv79+5t8bEJCAjw8PNC1a1fMmDED+fl/bHmenJyMqqoqxMTE6O/z8fFBaGhoo89bUVEBjUZT50ZE1BbCfFUYGuwOnVSzwyxRa/o68RKKrlchyM0BY3v6iI5jVAxWcPLy8uDh4VHvfg8PD+Tl5TX6uFGjRmH16tX47bff8N577+Hw4cO45557UFFRoX9eGxsbtG/fvs7jPD09G33euLg4/TwglUoFPz+/O3hlREQt89ywLgCAH4/kIOvadcFpyFyUVVTji9rRm9lDO8NKwXVDf9bid2PhwoX1JgH/9ZaUlAQADU50kiSpyQlQEydOxOjRoxEaGoqxY8diy5YtOHPmDH799dcmczX1vAsWLIBardbfsrKyWvCKiYjuTB//9rirsxuqdZL+lGeiO7XqwCVcK6tEoKs9xvXm6M1ftXgOzuzZszFp0qQmrwkMDMTRo0dx5cqVen939epVeHp6NvvneXt7IyAgABkZNZtleXl5obKyEkVFRXVGcfLz8xEdHd3gcyiVSiiVymb/TCKi1vbcPZ2x72wBvk/KxqyhneHjbCc6Epmw65XVWLqndvTmni4cvWlAi98RNzc3dOvWrcmbra0toqKioFarcejQIf1jDx48CLVa3WgRaUhhYSGysrLg7V2zn0RERASsra0RHx+vvyY3NxfHjx9v0fMSEbWlyI6uGNDRBZVaHT7dxbk4dGdWJdaM3gS42mM8R28aZLDKFxISgpEjR2LGjBk4cOAADhw4gBkzZmDMmDF1VlB169YNGzZsAACUlpZi/vz5SExMxMWLF5GQkICxY8fCzc0NDzzwAABApVJh+vTpePHFF7Fz506kpKTg8ccfR1hYmH5VFRGRMZo7vCsA4LukLM7FodtWZ/SGc28aZdB3ZfXq1QgLC0NMTAxiYmLQs2dPrFq1qs416enpUKtrDqNTKBQ4duwYxo0bh65du2Lq1Kno2rUrEhMT4ejoqH/MBx98gPHjx2PChAkYOHAg7O3tsWnTJigUCkO+HCKiOxLZ0RV3dXZDlVbiKA7dtm8OXEJhWSX8XezxQHgH0XGMlkySJEl0iLam0WigUqmgVqvh5OQkOg4RWZDkS9fw0JJEKOQy/Pbi3Qhw5b441Hw3KrUY9J/fUFBaif883BMT+lrWquCWfH5zXIuIqA1FBLjg7q7u0OokfMwzqqiFvkq8iILSSvi52HH05hZYcIiI2tjce2vm4vx4JBsXCsoEpyFToSmv0m8zMGdYV1hz7k2T+O4QEbWx3n7OGNbNAzoJ+Ghnhug4ZCKW7b2A4utV6OTugPEcvbklFhwiIgFujuL8nJqDs/mlgtOQsSsqq8SyfRcAAPPuDYaCZ07dEgsOEZEAoR1UiOnuCZ0EfLDjjOg4ZOQ+23MOpRXV6O7thFGhPDG8OVhwiIgEmXtvV8hkwK9Hc3E8Ry06DhmpfE05vtp/EQAwf0RXnhjeTCw4RESChHg7YVyvml1o/7MtXXAaMlaf7jqL8iodwv2dMTS4/iHW1DAWHCIigebdGwwruQx7zlxF4rlC0XHIyGQXXce3hzIBAH+PCW7ysGqqiwWHiEggf1d7TI70BwD8Z9tpWODeq9SEj3ZmoEorIbqTK6I7u4mOY1JYcIiIBJt9T2fYWSuQklmM+JNXRMchI5FxpQQ/JGcDAF6MCb7F1fRXLDhERIJ5ONriybsCAQD/3ZYOrY6jOAS8u/U0dBIwoocnIgLai45jclhwiIiMwNODO0FlZ42M/FJsSMkRHYcEO3ThGnacyodCLsM/RnYTHcckseAQERkBlZ01nh3SCQDwQfwZVFRrBSciUSRJQtyWUwCAif380Mm9neBEpokFh4jISEyNDoSnkxI5xTf0+56Q5dl6PA8pmcWwt1FgzvAuouOYLBYcIiIjYWutwIv31kwm/fi3sygqqxSciNpalVan3xPpqUEd4eFoKziR6WLBISIyIg9F+KKblyNKyqvxIQ/itDhrD2fhQkEZ3NrZ4OnBHUXHMWksOERERkQhl+HV0d0BAN8cuITzV3kQp6Uoq6jGhztqSu3zw7qgndJKcCLTxoJDRGRk7urihqHB7qjWSXh362nRcaiNfLb7HApKKxDoao9H+/uLjmPyWHCIiIzQgvtCIJcB205cwcHzPMLB3GUXXcfSPecBAP8cFQJrBT+e7xTfQSIiI9TV0xGTan+Lf3vzKei4+Z9Zi9tyGhXVOkR1dMWIHp6i45gFFhwiIiM1d3hXONgocDRbjY1pl0XHIQM5dOEafj2aC7kM+NfY7jxQs5Ww4BARGSl3RyWeHdoZQM22/dcrqwUnotam00l485cTAICJ/fwR4u0kOJH5YMEhIjJi0+8Kgm97O+Sqy/HprrOi41Ar++FINo7naOCotMKLMV1FxzErLDhEREbM1lqB18bULBv/Ys8FXCwoE5yIWktpRTX+W7up3/PDusCtnVJwIvPCgkNEZORiuntiUBc3VGp1+PcvJ0XHoVby6a6zuFpSsyx8anSg6DhmhwWHiMjIyWQyvD62B6zkMuw8nY9dp/NFR6I7dO5qKZbtvQAAeGV0d9hY8eO4tfEdJSIyAZ092uHJu4IAAG9sOsHTxk2YJEl4/ecTqNTqMCTYHcNDPERHMkssOEREJuK5ezrD3VGJi4XXsWzfBdFx6Db9cjQX+84WwMZKjjfu78Fl4QbCgkNEZCIcba2xYFQ3AMAnv51FrvqG4ETUUiXlVfp5VLOGdEaAq4PgROaLBYeIyIQ8EN4BfQPa43qlFq//fEJ0HGqhD+IzkF87sfiZu3lauCGx4BARmRCZTIa3HwiDlVyG7SevYNuJPNGRqJlOXtbgq8SLAIA3x4XC1lohNpCZM2jBKSoqQmxsLFQqFVQqFWJjY1FcXNzkY2QyWYO3//73v/prhgwZUu/vJ02aZMiXQkRkNIK9HPH04Jrf/l//+QRKyqsEJ6Jb0ekkvPbzcWh1EkaHeWNwV3fRkcyeQQvO5MmTkZqaiq1bt2Lr1q1ITU1FbGxsk4/Jzc2tc1u+fDlkMhkeeuihOtfNmDGjznWff/65IV8KEZFReX5YFwS42iNPU473tp8RHYduYV1SFpIvFcHB5o+NG8mwrAz1xKdOncLWrVtx4MABREZGAgC++OILREVFIT09HcHBwQ0+zsvLq86ff/75ZwwdOhQdO9b9rtLe3r7etURElsLWWoG3x4fh8WUH8VXiRYwP74Defs6iY1ED8tTleOfXUwCAufd2hZfKVnAiy2CwEZzExESoVCp9uQGAAQMGQKVSYf/+/c16jitXruDXX3/F9OnT6/3d6tWr4ebmhh49emD+/PkoKSlp9HkqKiqg0Wjq3IiITN1dXdzwQHgHSBLwz/VHUaXViY5EfyFJEl796RhKKqrR288ZTwwMEh3JYhis4OTl5cHDo/7mRR4eHsjLa96kuK+++gqOjo548MEH69z/2GOPYc2aNUhISMBrr72G9evX17vmz+Li4vTzgFQqFfz8/Fr2YoiIjNSro0PgbG+N03kl3BvHCG1Mu4wdp/JhrZDhPw/3hELOPW/aSosLzsKFCxudCHzzlpSUBAANbl4kSVKzNzVavnw5HnvsMdja1h3OmzFjBoYPH47Q0FBMmjQJP/zwA3bs2IEjR440+DwLFiyAWq3W37Kyslr4qomIjJNrOyVevi8EAPBB/BmczS8VnIhuKiytwBubava8ee6eLujq6Sg4kWVp8Ryc2bNn33LFUmBgII4ePYorV67U+7urV6/C09Pzlj9n7969SE9Px7p16255bZ8+fWBtbY2MjAz06dOn3t8rlUoolTyllYjM0yMRvvjlaC72nLmKF79Pw/qZUbBScBcQ0RZuOolrZZXo5uWIvw3pJDqOxWlxwXFzc4Obm9str4uKioJarcahQ4fQv39/AMDBgwehVqsRHR19y8cvW7YMERER6NWr1y2vPXHiBKqqquDt7X3rF0BEZGZkMhnefSgMMR/sQVpWMT7fcx6zhnYWHcuixZ+8gk1pl6GQy/Dfh3vBmoWzzRnsHQ8JCcHIkSMxY8YMHDhwAAcOHMCMGTMwZsyYOiuounXrhg0bNtR5rEajwffff4+nnnqq3vOeO3cOb775JpKSknDx4kVs3rwZjzzyCMLDwzFw4EBDvRwiIqPmrbLDwrE9AACLdpzBqVwuphClqKwSr2w4BgCYMagjwnxVghNZJoNWytWrVyMsLAwxMTGIiYlBz549sWrVqjrXpKenQ61W17lv7dq1kCQJjz76aL3ntLGxwc6dOzFixAgEBwfj+eefR0xMDHbs2AGFgrtCEpHlerBPBwwP8USVVsK879JQWc1VVW1NkiQs+PEY8ksq0MndAXOGdxEdyWLJJEmSRIdoaxqNBiqVCmq1Gk5OTqLjEBG1mvyScoz4YA+Krlfh+Xs6Y15Mw3uOkWF8l5SFf/xwFFZyGX6aNRChHTh605pa8vnNLwWJiMyIh6Mt/j0+FADwacI5pGYViw1kQS4VluGNjTUHoM6L6cpyIxgLDhGRmRnT0wdjenpDq5Pw/JoUaHhWlcFVa3WYuy4VZZVa9A9ywTODuWpKNBYcIiIz9PYDYejgbIfMa9fx8o/HYIGzEdrUp7vO4UhmMRxtrfDBxN7c0M8IsOAQEZkhlZ01Pp4cDoVchl+O5mLdYW5waihHMovw0W8ZAIC3xoeig7Od4EQEsOAQEZmtPv7tMb92kvHCTSdw5krjZ/bR7blWVonZq49Aq5MwrrcPxvXuIDoS1WLBISIyY88M7ojBXd1RXqXD7G+P4EalVnQks6HVSXhhbQouq8sR5OaAt2ond5NxYMEhIjJjcrkM70/oBXdHJc5cKcUbm06IjmQ2PtqZgb0ZBbC1lmPJ433gaGstOhL9CQsOEZGZc2unxKKJvSGTAWsPZ2HNoUzRkUxeQnq+ft7NOw+EoZsX91QzNiw4REQWYGBnN7x4b1cAwL9+Po6ki9cEJzJd2UXXMWddKiQJmBzpjwf7+IqORA1gwSEishCzhnbGfWFeqNJKmPnNEeSqb4iOZHLKq7SYtfoIiq9XoaevCv8a0110JGoECw4RkYWQyWpOtu7m5YiC0grMXJWM8ipOOm4unU7C/O/TkJathsrOGp9O7gNba56BaKxYcIiILIiD0gpfTOmL9vbWSMtWcxPAFng//gx+OZoLK7kMSx7vAz8Xe9GRqAksOEREFsbPxR6fTu4DhVyGH1Ny8Nnu86IjGb3vk7Lwya6zAIC4B8MQ3clNcCK6FRYcIiILFN3ZDa+NDgEAvLv1NH5IzhacyHglnivEyxuOAQBmDe2ER/r6CU5EzcGCQ0RkoaYNDMLTgzsCAF5afxS7TucLTmR8zl0txcxvklGllTA6zBsv3hssOhI1EwsOEZEF++fIbngwvAO0OgnPrj6CI5lFoiMZjeyi65iy7BDUN6oQ7u+M9yb0gpyHaJoMFhwiIgsml8vw7sM9MSTYHTeqtHhy5WGczeeZVXnqcjz25UHkFN9AR3cHfDGlL1dMmRgWHCIiC2etkGPxY33Qy88ZxderMGXZIVwqLBMdS5iC0go89uUBXCq8Dn8Xe3z71AC4tVOKjkUtxIJDRESwt7HCimn90MndAZfV5Zj4+QGcv1oqOlabK75eice/PIhzV8vgrbLF6qci4aWyFR2LbgMLDhERAQBcHGyw5ukB6OLRDnmackz4/AAyrljO11XF1ysxZfkhnM4rgbujEt/OGMC9bkwYCw4REel5ONpi7dMDEOLthILSCkxaegCncjWiYxnc5eIbeOSzRBzNVsPFwQbfPhWJIDcH0bHoDrDgEBFRHa7tlFgzIxJhHVQoLKvEo18cQFpWsehYBpNxpQQPLdmPjPxSeDnZYs2MAeji6Sg6Ft0hFhwiIqrH2d4G3zwViXD/monHE5cmYvOxXNGxWl3ypWt4+LNE5KrL0dmjHdY/G41gL5Ybc8CCQ0REDVLZWWPV9EgMCXZHeZUOz64+go92ZpjN2VXbTuThsS8P6ve5+f6ZKHRwthMdi1oJCw4RETWqndIKy6b2w/S7ggDUHDj5/NpUkz6FvFqrw/9tOY1nViWjvEqHe7p54NunBqC9g43oaNSKWHCIiKhJCrkMr43pjrgHw2All2FT2mVM/DwRmYXXRUdrsXxNOSZ/eRCf7T4HAJgWHYjPYyNgZ8NN/MwNCw4RETXLo/39sWp6JJztrZGWrcaoD/dg3eFMk/nKKvFcIe77aB8OXbgGBxsFPp3cBwvv7wFrBT8KzZFMMpV/MluRRqOBSqWCWq2Gk5OT6DhERCYl69p1vPhdGg5dvAYAGB7iif97KMxod/stq6jG+/FnsOL3C9BJQLCnIxY/3ged3NuJjkYt1JLPbxYcFhwiohbT6iR8ufc83tt+BpVaHVwdbLDw/h4Y09MbMpnxHEi5/UQeXt94ArnqcgDAwxG++Pe4UH4lZaJYcG6BBYeIqHWcytVg7rpUnM6r2fG4t58zXhkdgn6BLkJz5RTfwBsbT2D7ySsAAD8XO/x7XCiGBHsIzUV3hgXnFlhwiIhaT0W1Fp8lnMfne87hemXN6qoRPTzx0shu6NjGXwNdKizDkoRzWH8kG1VaCVZyGZ4e3BHP3dOFozZmoCWf3wadWfX2228jOjoa9vb2cHZ2btZjJEnCwoUL4ePjAzs7OwwZMgQnTpyoc01FRQWee+45uLm5wcHBAffffz+ys7MN8AqIiOhWlFYKvDC8CxL+PgSP9veHXAZsO3EFw9/fjRlfJyEhPR86nWF/lz5zpQQvrE3B0P8lYO3hLFRpJQzo6IJfnr8L/xjZjeXGAhl0BOf111+Hs7MzsrOzsWzZMhQXF9/yMe+++y7efvttrFy5El27dsVbb72FPXv2ID09HY6ONbtL/u1vf8OmTZuwcuVKuLq64sUXX8S1a9eQnJwMheLW/xBzBIeIyHAyrpTg/7acxs7T+fr7fNvb4dH+/hgf3qHVNtPLunYdW47n4tejuUjLVuvvHxLsjllDOwv/moxan9F9RbVy5UrMmTPnlgVHkiT4+Phgzpw5eOmllwDUjNZ4enri3XffxTPPPAO1Wg13d3esWrUKEydOBABcvnwZfn5+2Lx5M0aMGHHLPCw4RESGdza/BN8ezMIPyVnQlFfr7w90tUdUJzcM7OyKyCBXuLWzueXEZEmSkF10AydzNTh5WYOE9Pw6pUYuA0b08MKsoZ0R2kFlsNdEYrXk89uqjTI1y4ULF5CXl4eYmBj9fUqlEnfffTf279+PZ555BsnJyaiqqqpzjY+PD0JDQ7F///4GC05FRQUqKir0f9ZozP9kXCIi0Tp7OOJfY7vj7yOC8euxXKw7nIkjmcW4WHgdFwszseZQJgDA3kYBL5UtfFR28FLZQmklR3mVDuVVWpRXaaG+UYX0KyUo+VNJAmpKTWSQK+7r6Y2RPbzg7micy9RJDKMqOHl5eQAAT0/POvd7enri0qVL+mtsbGzQvn37etfcfPxfxcXF4Y033jBAYiIiuhU7GwUejvDFwxG+0JRX4fCFa/j9bCH2nyvA6bwSXK/U4vzVMpy/Wtbk81grZOji4YgQbyeE+ztjBEsNNaHFBWfhwoW3LAuHDx9G3759bzvUX4cqJUlq1vBlY9csWLAA8+bN0/9Zo9HAz8/vtvMREdHtcbK1xrAQTwwLqflFtrxKizx1OS6rbyBPXY5cdTkqq3Wws1HAzloBW2s57G2s0NmjHTq5t4ONFXcdpuZpccGZPXs2Jk2a1OQ1gYGBtxXGy8sLQM0ojbe3t/7+/Px8/aiOl5cXKisrUVRUVGcUJz8/H9HR0Q0+r1KphFLJlk9EZGxsrRUIdHNAoJuD6ChkZlpccNzc3ODm5maILAgKCoKXlxfi4+MRHh4OAKisrMTu3bvx7rvvAgAiIiJgbW2N+Ph4TJgwAQCQm5uL48eP4z//+Y9BchEREZFpMegcnMzMTFy7dg2ZmZnQarVITU0FAHTu3Bnt2tVs/tStWzfExcXhgQcegEwmw5w5c/DOO++gS5cu6NKlC9555x3Y29tj8uTJAACVSoXp06fjxRdfhKurK1xcXDB//nyEhYVh+PDhhnw5REREZCIMWnD+9a9/4auvvtL/+eaozK5duzBkyBAAQHp6OtTqP5b6/eMf/8CNGzfw7LPPoqioCJGRkdi+fbt+DxwA+OCDD2BlZYUJEybgxo0bGDZsGFauXNmsPXCIiIjI/PGoBu6DQ0REZBKM5qgGIiIiIhFYcIiIiMjssOAQERGR2WHBISIiIrPDgkNERERmhwWHiIiIzA4LDhEREZkdFhwiIiIyOyw4REREZHYMelSDsbq5ebNGoxGchIiIiJrr5ud2cw5hsMiCU1JSAgDw8/MTnISIiIhaqqSkBCqVqslrLPIsKp1Oh8uXL8PR0REymaxVn1uj0cDPzw9ZWVk856oBfH8ax/emaXx/msb3p2l8fxpnSu+NJEkoKSmBj48P5PKmZ9lY5AiOXC6Hr6+vQX+Gk5OT0f+DIhLfn8bxvWka35+m8f1pGt+fxpnKe3OrkZubOMmYiIiIzA4LDhEREZkdFpxWplQq8frrr0OpVIqOYpT4/jSO703T+P40je9P0/j+NM5c3xuLnGRMRERE5o0jOERERGR2WHCIiIjI7LDgEBERkdlhwSEiIiKzw4LTihYvXoygoCDY2toiIiICe/fuFR3JaOzZswdjx46Fj48PZDIZfvrpJ9GRjEZcXBz69esHR0dHeHh4YPz48UhPTxcdy2gsWbIEPXv21G9CFhUVhS1btoiOZZTi4uIgk8kwZ84c0VGMwsKFCyGTyercvLy8RMcyKjk5OXj88cfh6uoKe3t79O7dG8nJyaJjtQoWnFaybt06zJkzB6+88gpSUlIwaNAgjBo1CpmZmaKjGYWysjL06tULn3zyiegoRmf37t2YNWsWDhw4gPj4eFRXVyMmJgZlZWWioxkFX19f/N///R+SkpKQlJSEe+65B+PGjcOJEydERzMqhw8fxtKlS9GzZ0/RUYxKjx49kJubq78dO3ZMdCSjUVRUhIEDB8La2hpbtmzByZMn8d5778HZ2Vl0tFbBZeKtJDIyEn369MGSJUv094WEhGD8+PGIi4sTmMz4yGQybNiwAePHjxcdxShdvXoVHh4e2L17NwYPHiw6jlFycXHBf//7X0yfPl10FKNQWlqKPn36YPHixXjrrbfQu3dvLFq0SHQs4RYuXIiffvoJqampoqMYpX/+85/4/fffzfbbBo7gtILKykokJycjJiamzv0xMTHYv3+/oFRkqtRqNYCaD3GqS6vVYu3atSgrK0NUVJToOEZj1qxZGD16NIYPHy46itHJyMiAj48PgoKCMGnSJJw/f150JKOxceNG9O3bF4888gg8PDwQHh6OL774QnSsVsOC0woKCgqg1Wrh6elZ535PT0/k5eUJSkWmSJIkzJs3D3fddRdCQ0NFxzEax44dQ7t27aBUKjFz5kxs2LAB3bt3Fx3LKKxduxZHjhzhSHEDIiMj8fXXX2Pbtm344osvkJeXh+joaBQWFoqOZhTOnz+PJUuWoEuXLti2bRtmzpyJ559/Hl9//bXoaK3CIk8TNxSZTFbnz5Ik1buPqCmzZ8/G0aNHsW/fPtFRjEpwcDBSU1NRXFyM9evXY+rUqdi9e7fFl5ysrCy88MIL2L59O2xtbUXHMTqjRo3S/++wsDBERUWhU6dO+OqrrzBv3jyByYyDTqdD37598c477wAAwsPDceLECSxZsgRTpkwRnO7OcQSnFbi5uUGhUNQbrcnPz683qkPUmOeeew4bN27Erl274OvrKzqOUbGxsUHnzp3Rt29fxMXFoVevXvjwww9FxxIuOTkZ+fn5iIiIgJWVFaysrLB792589NFHsLKyglarFR3RqDg4OCAsLAwZGRmioxgFb2/ver8khISEmM3iGBacVmBjY4OIiAjEx8fXuT8+Ph7R0dGCUpGpkCQJs2fPxo8//ojffvsNQUFBoiMZPUmSUFFRITqGcMOGDcOxY8eQmpqqv/Xt2xePPfYYUlNToVAoREc0KhUVFTh16hS8vb1FRzEKAwcOrLclxZkzZxAQECAoUeviV1StZN68eYiNjUXfvn0RFRWFpUuXIjMzEzNnzhQdzSiUlpbi7Nmz+j9fuHABqampcHFxgb+/v8Bk4s2aNQvffvstfv75Zzg6OupHAlUqFezs7ASnE+/ll1/GqFGj4Ofnh5KSEqxduxYJCQnYunWr6GjCOTo61pur5eDgAFdXV87hAjB//nyMHTsW/v7+yM/Px1tvvQWNRoOpU6eKjmYU5s6di+joaLzzzjuYMGECDh06hKVLl2Lp0qWio7UOiVrNp59+KgUEBEg2NjZSnz59pN27d4uOZDR27dolAah3mzp1quhowjX0vgCQVqxYITqaUXjyySf1/165u7tLw4YNk7Zv3y46ltG6++67pRdeeEF0DKMwceJEydvbW7K2tpZ8fHykBx98UDpx4oToWEZl06ZNUmhoqKRUKqVu3bpJS5cuFR2p1XAfHCIiIjI7nINDREREZocFh4iIiMwOCw4RERGZHRYcIiIiMjssOERERGR2WHCIiIjI7LDgEBERkdlhwSEiIiKzw4JDREREZocFh4iIiMwOCw4RERGZHRYcIiIiMjv/D2TyhEq5HM4LAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4570ae9da644449a87c3fea9c4d7f919", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=3.0, description='omega', max=5.0, min=1.0), Output()), _dom_classes=(…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = np.linspace(0, 2*np.pi, 100)\n", + "fig, ax = plt.subplots()\n", + "line, = ax.plot(x, np.sin(x))\n", + "\n", + "def plot_sine_wave(omega):\n", + " y = np.sin(omega*x)\n", + " line.set_ydata(y)\n", + " fig.canvas.draw_idle()\n", + "\n", + "interact(plot_sine_wave, omega=(1, 5, 0.1))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/cookbook/jupyterlite/jupyterlite-gallery.md b/book/cookbook/jupyterlite/jupyterlite-gallery.md new file mode 100644 index 0000000..0a6b0e5 --- /dev/null +++ b/book/cookbook/jupyterlite/jupyterlite-gallery.md @@ -0,0 +1,11 @@ +# Gallery + +On this page, you can find some example usage of `JupyterLite`. The reader is invited to contribute to this gallery with their own interesting examples. + +## Interactive plot + +```{eval-rst} +.. retrolite:: interactive-wave.ipynb + :width: 100% + :height: 600px +``` \ No newline at end of file From bc8b12cc6f6408aff325b37d7b359dd33e53ca23 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 15:28:52 +0200 Subject: [PATCH 08/14] Update text --- book/cookbook/jupyterlite/including-jupyterlite.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/cookbook/jupyterlite/including-jupyterlite.md b/book/cookbook/jupyterlite/including-jupyterlite.md index efbfbca..0d00108 100644 --- a/book/cookbook/jupyterlite/including-jupyterlite.md +++ b/book/cookbook/jupyterlite/including-jupyterlite.md @@ -4,7 +4,7 @@ There are three different `JupyterLite` directives that you can include in your 1. `retrolite`: this embeds the old Jupyter Notebook environment in your page. This is a good one if you want students to program things on you page, since it allows students to edit and execute cells. 2. `jupyterlite`: this embeds a JupyterLab environment in your page. -3. `replite`: this variant provides an environment similar to the regular `IPython` kernel. This is probably the best solution if you want to include small, interactive pieces of content, like a plot with sliders. +3. `replite`: this variant provides an environment similar to the regular `IPython` kernel. Below are examples demonstrating how to include each variant. Note that the `jupyterlite-sphinx extension` is designed for use with `.rst` files (Restructured Text). Luckily, `MyST` provides a convenient directive that allows us to include Restructured Text content in a regular `.md` file. @@ -68,7 +68,7 @@ Here is the final result: ## `replite` -This is probably the cleanest solution when you want to do something simple, like a `matplotlib` plot with some `ipywidgets` sliders. The `replite` directive provides a REPL environment (Read-Evaluate-Print-Loop) that is very similar to `IPython` in the terminal. Here's how you can include it: +The `replite` directive provides a REPL environment (Read-Evaluate-Print-Loop) that is very similar to `IPython` in the terminal. Here's how you can include it: ```{eval-rst} .. replite:: From 042b2a8bc75cf341d24c22e5e50dc0110b1af704 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 15:29:12 +0200 Subject: [PATCH 09/14] Update table of contents --- book/_toc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/book/_toc.yml b/book/_toc.yml index f6354fb..3d8a946 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -14,5 +14,4 @@ parts: sections: - file: cookbook/jupyterlite/configuration - file: cookbook/jupyterlite/including-jupyterlite - - file: cookbook/jupyterlite/jupyterlite-gallery From 54406100f264178f64af68750b2542e79871f55f Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 15:59:41 +0200 Subject: [PATCH 10/14] Add environment.yml --- environment.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 environment.yml diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000..ec740b8 --- /dev/null +++ b/environment.yml @@ -0,0 +1,9 @@ +name: jupyter-book-env + +dependencies: + - jupyter-book=0.15.1 + - sphinx-inline-tabs + - pip + - pip: + - jupyterlite-sphinx=0.8.0 + - jupyterlite-xeus-python=0.8.1 From bdd4090b2e0303c60338f18ff52607d179f137be Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 16:02:29 +0200 Subject: [PATCH 11/14] Use Miniconda instead of virtualenv for environment --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 70bcc8c..2cc3075 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: python:3.10-bullseye +image: continuumio/miniconda:latest stages: - test @@ -11,14 +11,14 @@ variables: cache: paths: - .cache/pip - - venv/ -# Before running other jobs, setup Python +# Before running other jobs, setup the Anaconda environment before_script: - python -V - - pip install virtualenv - - virtualenv venv - - source venv/bin/activate + - conda env create -f environment.yml + - conda init bash + - source ~/.bashrc + - conda activate jupyter-book-env # This job tests if the book compiles gracefully after a new addition test-build: From 8375da74feb86be716964f981fb0259ba62547ff Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 16:04:25 +0200 Subject: [PATCH 12/14] Install from pip --- environment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/environment.yml b/environment.yml index ec740b8..7ddc152 100644 --- a/environment.yml +++ b/environment.yml @@ -1,9 +1,9 @@ name: jupyter-book-env dependencies: - - jupyter-book=0.15.1 - - sphinx-inline-tabs - pip - pip: - jupyterlite-sphinx=0.8.0 - jupyterlite-xeus-python=0.8.1 + - jupyter-book=0.15.1 + - sphinx-inline-tabs From e62da099126ee7a6428dba6790b4eb300791cfcb Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 16:07:16 +0200 Subject: [PATCH 13/14] =?UTF-8?q?Fix=20syntax=20=F0=9F=99=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/environment.yml b/environment.yml index 7ddc152..f3e1752 100644 --- a/environment.yml +++ b/environment.yml @@ -3,7 +3,7 @@ name: jupyter-book-env dependencies: - pip - pip: - - jupyterlite-sphinx=0.8.0 - - jupyterlite-xeus-python=0.8.1 - - jupyter-book=0.15.1 + - jupyterlite-sphinx==0.8.0 + - jupyterlite-xeus-python==0.8.1 + - jupyter-book==0.15.1 - sphinx-inline-tabs From 0b5dad4292666b09886f039de191df15c63ff3f1 Mon Sep 17 00:00:00 2001 From: Caspar Jungbacker <74240267+CasparJungbacker@users.noreply.github.com> Date: Sat, 10 Jun 2023 16:22:36 +0200 Subject: [PATCH 14/14] Include warning for CI/CD --- book/cookbook/jupyterlite/jupyterlite.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/book/cookbook/jupyterlite/jupyterlite.md b/book/cookbook/jupyterlite/jupyterlite.md index df75c2d..c26432d 100644 --- a/book/cookbook/jupyterlite/jupyterlite.md +++ b/book/cookbook/jupyterlite/jupyterlite.md @@ -17,3 +17,7 @@ You can try JupyterLite below. It has `numpy`, `matplotlib` and `scipy` installe JupyterLite is ideal for including small interactive pieces of content on a page. For example, you may want to include a `matplotlib` plot with some sliders to play with. Or you may have a small model that requires a student to provide some input parameters and then gives some output. It is important to note that JupyterLite makes use of the browser cache for memory, meaning that the state of a JupyterLite element is lost when the user leaves a page. Hence, it may not be a good idea to ask student to code a lot by hand, as they loose all of their progress when the page is closed. It is possible to install packages in the kernel that will be shipped with your book. However, there are some strict limitations to what packages can be installed. For once, they should be listed on `conda-forge`. In addition, the package needs to be a [`noarch`](https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/packages.html#noarch-packages) package. In theory, you can install your own packages if it meets those two requirements, but we have no experience in doing that (feel free to try it out yourself, so that we can add instructions to the manual!). + +```{warning} +Including JupyterLite in your book imposes some requirements on the Docker image that is used in the CI/CD pipeline. Specifically, you need to have access to Anaconda. If you know what you're doing, have a look at the [`.gitlab-ci.yml`](https://gitlab.tudelft.nl/interactivetextbooks-citg/jupyter-book-manual/-/blob/main/.gitlab-ci.yml) of this repository. +``` \ No newline at end of file