From ba9f7e5c1773ef121bbebc04cf225841b52aa39c Mon Sep 17 00:00:00 2001 From: Martin Karkowski Date: Tue, 18 Jan 2022 21:51:19 +0100 Subject: [PATCH] adding wiki --- contribute/VERSION | 2 +- contribute/toBrowser.js | 8 + contribute/toNodejs.js | 8 + lib/helpers/index.nodejs.ts | 1 - lib/helpers/singletonMethod.ts | 7 +- lib/index.browser.ts | 1 + lib/index.nodejs.ts | 1 + lib/logger/getLogger.ts | 4 +- lib/logger/index.browser.ts | 5 +- lib/logger/index.nodejs.ts | 3 +- lib/logger/nopeLogger.ts | 48 ++-- lib/types/nope/nopeDispatcher.interface.ts | 23 +- package-lock.json | 11 +- package.json | 3 +- tsconfig.json | 4 +- wiki/.gitignore | 1 + ...-Started.md => 00-Getting-Started copy.md} | 11 +- wiki/01-NoPE.md | 7 + wiki/02-Logging.ipynb | 24 ++ wiki/11-Observables.ipynb | 209 ++++++++++++++++++ wiki/12-Dispatcher.ipynb | 84 +++++++ wiki/install-jupyter.bat | 32 +++ wiki/media/logo.png | Bin 0 -> 27760 bytes wiki/start-jupyter.bat | 7 + 24 files changed, 452 insertions(+), 52 deletions(-) create mode 100644 wiki/.gitignore rename wiki/{00-Getting-Started.md => 00-Getting-Started copy.md} (82%) create mode 100644 wiki/01-NoPE.md create mode 100644 wiki/02-Logging.ipynb create mode 100644 wiki/11-Observables.ipynb create mode 100644 wiki/12-Dispatcher.ipynb create mode 100644 wiki/install-jupyter.bat create mode 100644 wiki/media/logo.png create mode 100644 wiki/start-jupyter.bat diff --git a/contribute/VERSION b/contribute/VERSION index e5a4a5e..437d26b 100644 --- a/contribute/VERSION +++ b/contribute/VERSION @@ -1 +1 @@ -1.0.9 \ No newline at end of file +1.0.10 \ No newline at end of file diff --git a/contribute/toBrowser.js b/contribute/toBrowser.js index ac25172..c7915e0 100644 --- a/contribute/toBrowser.js +++ b/contribute/toBrowser.js @@ -1,3 +1,11 @@ +/** + * @author Martin Karkowski + * @email m.karkowski@zema.de + * @create date 2022-01-18 13:42:41 + * @modify date 2022-01-18 13:42:43 + * @desc [description] + */ + const { readFileSync, writeFileSync } = require("fs"); const version = readFileSync("./contribute/VERSION", { encoding: "utf-8" }); diff --git a/contribute/toNodejs.js b/contribute/toNodejs.js index b0d4440..c091d68 100644 --- a/contribute/toNodejs.js +++ b/contribute/toNodejs.js @@ -1,3 +1,11 @@ +/** + * @author Martin Karkowski + * @email m.karkowski@zema.de + * @create date 2022-01-18 13:42:45 + * @modify date 2022-01-18 13:42:48 + * @desc [description] + */ + const { readFileSync, writeFileSync } = require("fs"); const version = readFileSync("./contribute/VERSION", { encoding: "utf-8" }); diff --git a/lib/helpers/index.nodejs.ts b/lib/helpers/index.nodejs.ts index 04c6f31..fa75b54 100644 --- a/lib/helpers/index.nodejs.ts +++ b/lib/helpers/index.nodejs.ts @@ -10,4 +10,3 @@ export * from "./index.browser"; export { files }; import * as files from "./fileMethods"; - diff --git a/lib/helpers/singletonMethod.ts b/lib/helpers/singletonMethod.ts index dc89d94..19cdcd1 100644 --- a/lib/helpers/singletonMethod.ts +++ b/lib/helpers/singletonMethod.ts @@ -9,7 +9,7 @@ /** * Function to get a singleton. To create the singleton, the parameter *create* is used. This will be called once. * The singleton will be stored as *global* variable and can be accessed by the identifier - * + * * @author M.Karkowski * @export * @template T The Type of the singleton @@ -17,7 +17,10 @@ * @param {() => T} create The Callback which is used to create the instance. * @return An object, containing the key **instances**, where you'll find the instance and an helper function **setInstance** to redefine the instance */ -export function getSingleton(identifier: string, create: () => T): { +export function getSingleton( + identifier: string, + create: () => T +): { instance: T; setInstance: (value: T) => void; } { diff --git a/lib/index.browser.ts b/lib/index.browser.ts index e7ef369..8cb7e94 100644 --- a/lib/index.browser.ts +++ b/lib/index.browser.ts @@ -17,6 +17,7 @@ import * as observables from "./observables/index"; import * as promises from "./promise/index"; import * as types from "./types/index"; +export { getLayer } from "./communication/index.browser"; export * from "./logger/index.browser"; export { communcation, diff --git a/lib/index.nodejs.ts b/lib/index.nodejs.ts index 2aa1293..f96dd21 100644 --- a/lib/index.nodejs.ts +++ b/lib/index.nodejs.ts @@ -21,6 +21,7 @@ export { readInArgs as readInRunNopeBackendArgs, runNopeBackend, } from "./cli/runNopeBackend"; +export { getLayer } from "./communication/index.nodejs"; export * from "./logger/index.nodejs"; export { communcation, diff --git a/lib/logger/getLogger.ts b/lib/logger/getLogger.ts index b574154..599b00a 100644 --- a/lib/logger/getLogger.ts +++ b/lib/logger/getLogger.ts @@ -27,8 +27,8 @@ export function getCentralNopeLogger(): NopeLogger { /** * Helper Function, to create a Logger. Therefore it uses a specific Level and a Lable of the - * Logger. The Logger-Level can be overwritten by the central-logger see {@link getCentralNopeLogger} - * + * Logger. The Logger-Level can be overwritten by the central-logger see {@link getCentralNopeLogger} + * * * @export * @param {LoggerLevel} level The Level, which should be rendered diff --git a/lib/logger/index.browser.ts b/lib/logger/index.browser.ts index ff8c0e8..1aab35a 100644 --- a/lib/logger/index.browser.ts +++ b/lib/logger/index.browser.ts @@ -51,14 +51,13 @@ export { getLogerAsEventEmitter, TCallback, TCallbackWithLevel, - useEventLogger + useEventLogger, } from "./eventLogging"; export { defineNopeLogger, getCentralNopeLogger, getNopeLogger, - ValidLoggerDefinition + ValidLoggerDefinition, } from "./getLogger"; export { LoggerLevel, LoggerLevels } from "./nopeLogger"; export { setGlobalLoggerLevel } from "./setGlobalLoggerLevel"; - diff --git a/lib/logger/index.nodejs.ts b/lib/logger/index.nodejs.ts index 3c33ae6..479e43f 100644 --- a/lib/logger/index.nodejs.ts +++ b/lib/logger/index.nodejs.ts @@ -5,9 +5,8 @@ * @modify date 2021-08-27 20:19:05 * @desc [description] * @module logger - * [[include lib/logger/README.md]] + * [[include:00-Getting-Started.md]] */ export { generateLogfilePath, useLogFile } from "./fileLogging"; export * from "./index.browser"; - diff --git a/lib/logger/nopeLogger.ts b/lib/logger/nopeLogger.ts index e91784a..eed0284 100644 --- a/lib/logger/nopeLogger.ts +++ b/lib/logger/nopeLogger.ts @@ -59,28 +59,28 @@ Logger.useDefaults({ defaultLevel: (Logger as any).DEBUG, formatter: RUNNINGINNODE ? function (messages, context) { - messages.unshift( - colors.FgBlue, - new Date().toISOString(), - colors.Reset, - "-", - colorMatching[context.level.name], - context.level.name + spacer[context.level.name], - "-", - colors.BgWhite + colors.FgBlack, - context.name, - colors.Reset, - ":" - ); - } + messages.unshift( + colors.FgBlue, + new Date().toISOString(), + colors.Reset, + "-", + colorMatching[context.level.name], + context.level.name + spacer[context.level.name], + "-", + colors.BgWhite + colors.FgBlack, + context.name, + colors.Reset, + ":" + ); + } : function (messages, context) { - messages.unshift( - context.level.name + spacer[context.level.name], - "-", - context.name, - ":" - ); - }, + messages.unshift( + context.level.name + spacer[context.level.name], + "-", + context.name, + ":" + ); + }, }); /** @@ -142,7 +142,7 @@ function _getLogger(level: LoggerLevel, label = ""): ILogger { } /** - * The Nope-Logger. It consits o + * The Nope-Logger. It consits o */ export class NopeLogger { protected _logger: ILogger; @@ -183,7 +183,7 @@ export class NopeLogger { /** * Creates a sublogger with the given name and the - * level. + * level. * * @author M.Karkowski * @param {string} [name=""] The name of the logger @@ -285,7 +285,7 @@ export class NopeLogger { protected _pw = ""; /** - * Lock the Logger Level with a password. This prevents chaning the + * Lock the Logger Level with a password. This prevents chaning the * log level to other log-levels. you must {@link NopeLogger.unlock} to * update the Level again. * diff --git a/lib/types/nope/nopeDispatcher.interface.ts b/lib/types/nope/nopeDispatcher.interface.ts index 1bdaaf1..95d2803 100644 --- a/lib/types/nope/nopeDispatcher.interface.ts +++ b/lib/types/nope/nopeDispatcher.interface.ts @@ -11,14 +11,14 @@ import { ICommunicationBridge } from "./nopeCommunication.interface"; import { IHost, INopeINopeConnectivityTimeOptions, - INopeStatusInfo, + INopeStatusInfo } from "./nopeConnectivityManager.interface"; import { INopeCore } from "./nopeCore.interface"; import { INopeDescriptor } from "./nopeDescriptor.interface"; import { IEventAdditionalData, IEventCallback, - INopeObserver, + INopeObserver } from "./nopeEventEmitter.interface"; import { INopeModule, INopeModuleDescription } from "./nopeModule.interface"; import { INopeObservable } from "./nopeObservable.interface"; @@ -33,7 +33,7 @@ export type IGenerateRemoteInstanceCallback = ( ) => Promise; export type IGenerateRemoteInstanceForOtherDispatcherCallback< I extends INopeModule -> = (dispatcher: INopeDispatcher, identifier: string, ...args) => Promise; + > = (dispatcher: INopeDispatcher, identifier: string, ...args) => Promise; export type IValidPromise = Promise | INopePromise; @@ -102,7 +102,7 @@ export interface IHostOverview extends IHost { } export interface IDispatcherConstructor { - new ( + new( options: INopeDispatcherOptions, _generateObservable: () => INopeObservable ): INopeDispatcher; @@ -142,8 +142,19 @@ export interface INopeDispatcherDescription extends INopeStatusInfo { } /** - * Interface for an Dispatcher. - * + * # NoPE - Dispatcher + * + * The NoPE-Dispatcher is designed as Layer between the different Modules / Dispatchers. They allow distributed computing or just a simple ***Service oriented Architecture*** (*SOA*). A dispatcher is used to link the modules, share data and events and provide a remote procedure call (rpc) interface. + * + * ## Building Blocks of a Dispatcher: + * + * | element | description | + * |-|-| + * | `connectivityManager` | establishes a connection to other dispatchers and manages the status of the remotely connected dispatchers. It checks their health and removes dead dispatchers. | + * | `eventDistributor` | shares events accross the network (or internally). You can use this element to listen for specific events. The subscription to those events allows `mqtt`-patterns. Additionaly, you are allowed to emit event on specific topics, or pattern based topics | + * | `dataDistributor` | shares data accross the network (or internally). In comperisson to events, data is persistent and is available all the time. You can use this sub-module to listen for specific data-changes (install data-hooks), pull specific data or push data. You can pull / push data using a `mqtt`-pattern based path. | + * | `rpcManager` | Used to perform `remote procedure calls` (see [here](https://de.wikipedia.org/wiki/Remote_Procedure_Call)). The manager keeps track of the available services. You must use the sub-module to register/unregister (new) services. | + * | `instanceManager` | Used to create/dispose (remote) instances. The manager keeps track of the available instances in the network, allows to create `wrappers` for those instances. You must use the sub-module to register/unregister (new) instances. To allow the system to provide a service for creating instances of as specific type, you can provide a generator and provide it as `service`. | * @export * @interface INopeDispatcher */ diff --git a/package-lock.json b/package-lock.json index f16a900..b6c9c48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "nope", - "version": "1.0.9", + "version": "1.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nope", - "version": "1.0.9", + "version": "1.0.10", "license": "MIT", "dependencies": { + "argparse": "^2.0.1", "async": "^3.2.2", "comment-parser": "^1.3.0", "cors": "^2.8.5", @@ -947,8 +948,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/arr-diff": { "version": "4.0.0", @@ -18992,8 +18992,7 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "arr-diff": { "version": "4.0.0", diff --git a/package.json b/package.json index 9aaa29a..a8d84b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nope", - "version": "1.0.9", + "version": "1.0.10", "description": "NoPE Runtime for Nodejs. For Browser-Support please use nope-browser", "files": [ "dist-nodejs/**/*", @@ -39,6 +39,7 @@ }, "homepage": "https://git.zema.de/tfs/ZISS/_git/nope-js#readme", "dependencies": { + "argparse": "^2.0.1", "async": "^3.2.2", "comment-parser": "^1.3.0", "cors": "^2.8.5", diff --git a/tsconfig.json b/tsconfig.json index 471fa38..634a7ff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,9 +30,7 @@ "location": "local", "format": "png" }, - "includes": [ - "lib" - ] + "includes": "wiki" }, "include": [ "lib", diff --git a/wiki/.gitignore b/wiki/.gitignore new file mode 100644 index 0000000..58461f2 --- /dev/null +++ b/wiki/.gitignore @@ -0,0 +1 @@ +.ipynb_checkpoints \ No newline at end of file diff --git a/wiki/00-Getting-Started.md b/wiki/00-Getting-Started copy.md similarity index 82% rename from wiki/00-Getting-Started.md rename to wiki/00-Getting-Started copy.md index e7faaf3..e890f0a 100644 --- a/wiki/00-Getting-Started.md +++ b/wiki/00-Getting-Started copy.md @@ -20,7 +20,16 @@ Use the following code: `npm --registry https://npm.zema.de/ install nope` The Documentation is contained in here. Alternative you can create a Documentation using `npm run-script doc`. This will create the Documentation under `docs`. -You'll additional help under `wiki` +You'll additional help under `wiki`. + +The `wiki` is mostly running as `Markdown` or `Jupyter`-Notebook. + +### Run the wiki + +1. Install the documents via: `00-install-jupyter.bat` + 1. Install the `jupyter` with `pip3 install jupyter` + 2. Install a Javascript interpreter for `jupyter` with `npm install -g ijavascript`. Afterwards install the extension `%appdata%\npm\ijsinstall` +2. Run the `01-start-jupyter.bat` --- diff --git a/wiki/01-NoPE.md b/wiki/01-NoPE.md new file mode 100644 index 0000000..073042b --- /dev/null +++ b/wiki/01-NoPE.md @@ -0,0 +1,7 @@ +![Logo](./media/logo.png) + +--- + +## No Programming Environment - `NoPE` + +`NoPE`-Library for `javascript` / `python`. diff --git a/wiki/02-Logging.ipynb b/wiki/02-Logging.ipynb new file mode 100644 index 0000000..fc9fbc7 --- /dev/null +++ b/wiki/02-Logging.ipynb @@ -0,0 +1,24 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "JavaScript (Node.js)", + "language": "javascript", + "name": "javascript" + }, + "language_info": { + "name": "javascript" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/wiki/11-Observables.ipynb b/wiki/11-Observables.ipynb new file mode 100644 index 0000000..de5ba8c --- /dev/null +++ b/wiki/11-Observables.ipynb @@ -0,0 +1,209 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Observables\n", + "## Usage of `nope.observables`\n", + "\n", + "Import Nope.\n", + "\n", + "```typescript\n", + "import * as nope from \"nope\";\n", + "```\n", + "\n", + "In our nodebook, we have to use **javascript** instead of **typescript**:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// First lets install nope using npm\n", + "const nope = require(\"../dist-nodejs/index.nodejs\")\n", + "\n", + "// Create our Observable:\n", + "const obs = new nope.observables.NopeObservable()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `setContent`: Change the content of the Observable.\n", + "\n", + "To change the content of an observable use the function `setContent`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// Set the content to \"1337\"\n", + "obs.setContent(5);\n", + "\n", + "// Print the content (see getContent)\n", + "console.log(\"current value =\",obs.getContent());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### `setter`: Define a specific setter for the observable.\n", + "\n", + "You can specify a specifc getter for the observable for instance, to limit the number to the following constrains `> 0` and `< 10`.\n", + "\n", + "---\n", + "\n", + "The setter function will receive multiple parameters, as listed below:\n", + "\n", + "1. `value`,\n", + "2. ``options`` containing:\n", + " * `sender`: The Element, which changed the data\n", + " * `timestamp`: The timestamp of the change\n", + " * `args`: additional args. \n", + "\n", + "---\n", + "\n", + "The setter function have to return a `dict` with the following keys:\n", + "| key | type | content |\n", + "| - | - | - |\n", + "| `valid` | `bool` | A Flag, to show whether the data are valid or not. If the data is invalid, the observable wont store them |\n", + "| `value` | `any` | The Data that has been adapted |\n", + "\n", + "---\n", + "\n", + "Below, we will implement an example to show the setter above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "obs.setter = (value, options) => {\n", + " // Print, which data we received\n", + " console.log(\"setter received\", value, options);\n", + " // Show the result of our comparison\n", + " console.log(\"data is valid:\", (value > 0) && (value < 10));\n", + " return {\n", + " // The Value\n", + " value: value,\n", + " // Valid\n", + " valid: (value > 0) && (value < 10)\n", + " }\n", + "}\n", + "\n", + "// Set the content to \"1337\" ==> But our setter will prevent using this value because it isnt valid.\n", + "obs.setContent(1337);\n", + "\n", + "// Print the content (see getContent) ==> we expect to get \"5\"\n", + "console.log(\"current value =\", obs.getContent());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To remove such a getter just set the getter property to `null`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "obs.setter = null\n", + "\n", + "// Set the content to \"1337\" we do not have any setter ==> we will use this parameter\n", + "obs.setContent(1337);\n", + "\n", + "// Print the content (see getContent) ==> we expect to get \"1337\"\n", + "console.log(\"current value =\", obs.getContent());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `getContent`: Get the current content of the Observable.\n", + "To extract the content of our observable, we are able to use the function `getContent`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "let content = obs.getContent();\n", + "console.log(\"current value =\", content)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If no data is assigned, this will result in `undefined`. Otherwise the current data is returned.\n", + "\n", + "#### `getter`: Define a specific getter for the observable.\n", + "\n", + "You can specify a specifc getter for the observable for instance, to allways return a `string`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// Define a getter\n", + "obs.getter = (value) => \"Allways this result\";\n", + "console.log(\"current value (with getter) =\", obs.getContent());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To remove such a getter just set the getter property to `null`. \n", + "\n", + "The Original value is not changed ==> we expect to get \"1337\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// Reset the getter.\n", + "obs.getter = null;\n", + "console.log(\"current value (after removing the getter) =\", obs.getContent());" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "JavaScript (Node.js)", + "language": "javascript", + "name": "javascript" + }, + "language_info": { + "file_extension": ".js", + "mimetype": "application/javascript", + "name": "javascript", + "version": "17.3.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/wiki/12-Dispatcher.ipynb b/wiki/12-Dispatcher.ipynb new file mode 100644 index 0000000..e47e9a4 --- /dev/null +++ b/wiki/12-Dispatcher.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NoPE - Dispatcher\n", + "\n", + "The NoPE-Dispatcher is designed as Layer between the different Modules / Dispatchers. They allow distributed computing or just a simple ***Service oriented Architecture*** (*SOA*). A dispatcher is used to link the modules, share data and events and provide a remote procedure call (rpc) interface.\n", + "\n", + "## Building Blocks of a Dispatcher:\n", + "\n", + "| element | description | \n", + "|-|-|\n", + "| `connectivityManager` | establishes a connection to other dispatchers and manages the status of the remotely connected dispatchers. It checks their health and removes dead dispatchers. |\n", + "| `eventDistributor` | shares events accross the network (or internally). You can use this element to listen for specific events. The subscription to those events allows `mqtt`-patterns. Additionaly, you are allowed to emit event on specific topics, or pattern based topics |\n", + "| `dataDistributor` | shares data accross the network (or internally). In comperisson to events, data is persistent and is available all the time. You can use this sub-module to listen for specific data-changes (install data-hooks), pull specific data or push data. You can pull / push data using a `mqtt`-pattern based path. |\n", + "| `rpcManager` | Used to perform `remote procedure calls` (see [here](https://de.wikipedia.org/wiki/Remote_Procedure_Call)). The manager keeps track of the available services. You must use the sub-module to register/unregister (new) services. |\n", + "| `instanceManager` | Used to create/dispose (remote) instances. The manager keeps track of the available instances in the network, allows to create `wrappers` for those instances. You must use the sub-module to register/unregister (new) instances. To allow the system to provide a service for creating instances of as specific type, you can provide a generator and provide it as `service`. |\n", + "\n", + "## Create a Dispatcher\n", + "\n", + "To start exploring the capabilities of the dispatcher we will firstly create a dispatcher with the code below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// First lets install nope using npm\n", + "const nope = require(\"../dist-nodejs/index.nodejs\")\n", + "\n", + "// Lets create our dispatcher\n", + "const dispatcher = nope.dispatcher.getDispatcher({\n", + " // We will use the event layer (which just runs internally)\n", + " communicator: nope.getLayer(\"event\"),\n", + "\n", + " // We will adapt the timings (normally, we send a hartbeat and check for dead dispatchers)\n", + " timings: {\n", + "\n", + " /**\n", + " * Interval for the alive message given in [ms]. If \"0\" is provided,\n", + " * no alive messages are provided\n", + " *\n", + " * @author M.Karkowski\n", + " * @type {number}\n", + " */\n", + " sendAliveInterval: 0,\n", + "\n", + " /**\n", + " * Interval, to check the other dispatcher for being slow, dead, etc..\n", + " * should be lager then the \"sendAliveInterval\". The value is given in [ms]\n", + " * If \"0\" is provided, no alive messages are provided\n", + " *\n", + " * @author M.Karkowski\n", + " * @type {number}\n", + " */\n", + " checkInterval: 0\n", + " \n", + " }\n", + "});\n", + "console.log(dispatcher)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "JavaScript (Node.js)", + "language": "javascript", + "name": "javascript" + }, + "language_info": { + "file_extension": ".js", + "mimetype": "application/javascript", + "name": "javascript", + "version": "17.3.1" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/wiki/install-jupyter.bat b/wiki/install-jupyter.bat new file mode 100644 index 0000000..7087e05 --- /dev/null +++ b/wiki/install-jupyter.bat @@ -0,0 +1,32 @@ +set DIR=%~dp0 +cd "%DIR%" + +if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b) + +@REM Link NPM-Folders +mkdir %PROGRAMDATA%\npm +setx PATH "%PROGRAMDATA%\npm;%PATH%" /M +npm config set prefix %PROGRAMDATA%\npm + +%@Try% + @REM Uninstall IO-Server + pip3 install jupyter + npm install -g ijavascript && ( + npm --registry https://npm.zema.de/ install -g nope && ( + %appdata%\npm\ijsinstall + ) || ( + %appdata%\npm\ijsinstall + ) + ) || ( + npm --registry https://npm.zema.de/ install -g nope && ( + %appdata%\npm\ijsinstall + ) || ( + %appdata%\npm\ijsinstall + ) + + ) +%@EndTry% +:@Catch + echo uninstall IO-Server +:@EndCatch + diff --git a/wiki/media/logo.png b/wiki/media/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c26634e08ee97093bf91176987ca22241c381 GIT binary patch literal 27760 zcmbrm1x%b_*DX4n z&b{~l^Cves$sr-+oy_w-zV_a0uT7|`vJ5sR872q>!j_YjR0n~cf(2NY@QmRo3vmH~Nb&#uq6{#ciUS|gLZv=J zKRBBiL#-U_X*8|u%s_9s-g1Gt--5Z`(r^oax%t3vd3gD}I6)wr89B-KnjVJxix@sc z8~5Tz7Ulx(0Rgn%72bEzhp4I%payEQOg+V;Q{^nD`IIwRD86shnfzV5M7Ks4MIoGo z-TK|T=A5qy3OVQ62Omm7C{MnpHt{?jx^K$8h>2PJ>~3Lxd3tf~n!YtVJ6xGEG~%9N zkuC!a^8f1RkHQZ<;02a1{q1vAdGlm{%f_l1l(t0XIBInF?H8D(!BSxo(gtQrR9Q1B zYO+otPe7o%07*0u2u94vYV}rkdd}JLt&4T_Z_D?_IV_mUUWJ4iJ14kA`37U6 z^byOb$nk0{-7OKaY!h_3>?0s2*Ncsft>omZId8q#pC>kl?(2FSOOX;AdQNJgp|+rR zG7>2vG{GpU$aB?gj-QU{#eS{gOUf#c)A7WE zyzy4D`wTy^!(M@t`vzNk;)F|tCAHSpmi1E4$=Qz2{{D&9!AUpCgZ;PE0O z$q(<5B72YT;`I7zYl4s#4Tmypw#r7Q*r)ZZQeAl8tkv)=StHa?+;4xI-_O=X+*+q$ zgt~q5QCoU6(4EiTe>ISlW9x0fy%6Qzs4Y50#ukyPN~Zd)XUh20)c(~Uf^ky3FZLQX zDm%W_MZV%OPZB{$!!&FjbKig+*z^)ldd73E?!%SuHtyxaESR(%pMH$S71U+`PbR7@ z$bX?qKf-W_Y0S4V*=MgDZ-GFrtD`v_ZyN{L8F^Ay935Wps@dAwLYmz6Yuyf)e0MY7 zf2&>g7-XOSfuuov$?VJfX-v`~@6%rK0oEn<`|20uJ6HKzgmIZ_1Wz~!5AO9RY%VmC zQY;B3FE2mvMa=icN9ZPqytVmer|1&VFHAuB20Z5Bt|4MZLaSP`sUj$DSnsb>sEtz; z!Yo`gZUB#K3aMwg8723B)9}_$O2TS9F2(P@+oFeZrvr_m=?&PH1Wsv=FEO+u8El|* zTnj-BK=17uF3mwgSc}D;zZV@JA9piw?x#0egia_K89B>s;)8$4z`E*a5h#z8*|K>| zJk~2oXMygi>m^KjP^OA2y7jWh7eqG`ioytIjqpnC*%SuRhXh+O3~H{u&n$3`ulKfBKbsb%<M8=@l7V zLesssnkox|C{93P&MFABf@fxC zHoW9_yPtu5KO5tnr_@9!dI~!4dhr8$#l{(jff94>H@2RJyYjC1AkRl_yA))3FjK@U z5&)vw4SAJZS{@&~ldvhcKJA>2j&3ugpsdKaiH+7ibC803na(+WL;qfF<0NcRE|726 zW$qe#MQT~Z96)r?9&#+}LxIZub?BZ^6s7Q8QCaKe>^Z3YyX4l3kz{|_p?@B+l|n?8A}q{kUg#zUWF_{YZ4Tiug9=4&Yw~tnjA@k0w&!d z(axu*)23clA#UvRY3!vxZyrBmE7#DUqaAzBAAV-9A7S6QTB;2lec>XJ8)}%=M^b$t z4+52w&|{QJg_GPv72PgE*4Day+CGPo(YIHkx-u(nwkD1-g>q81>oL9oH+wy(R-prv zaJ$^ETXv)5HtCLhgjCQe@uNsmzX4l7MJ~RxJu@n3V*6F6{7U%e>pI}OD&4}ef|ERqC&Z)~f(kTXT*m==rVI@E6~=UsEq=9;sqUHYh_VR{L0z-R@o>< zxS>xj6lWCgBJ+R057OXlwtRcoG+O`eB@G!3La53-L9UX>CsfO+=h-`DdFac_oob$N zJX)?@GSIttkH`DV+YOPc75Yj{yxACJs+yOa4Ft25Bw<*5y@YTIAv9?lR$z{w+|IF! ztcD4i{M!j*O3Hkv`}65CUoMNDE$|fLOJ8juEFAJ(qb6B=_3m{)e3{IDmrwj3WRVl=a44LFT{~Fpp&u22j?C3ZE`?rQQCf zR9fug$>aNeDJPy>TX*4Zf?X@(OCm4E9;`Bqt1;_X<;GDFAnBEtPfk)-ZBUYvlbZ`AWE{85_OPWkx#q0MiH-j|<_V!aZ|Aj( zpFlZp>0LU3`?i@GH}Np53CrRFmCmazg%fy&EQf;bd}A@(B||agI>;&5OHu;n67f}K z#;KCx=RT1v6hxzMn}Sp&(2(sPNs6U}iKc5c^E7Z6wDx4i1wCK~nNWRn}%GgP$Lp*A(u2-s@JCQHS z@Ao|T5VTrN=~@~!Lgf4p5jt#w%RvNtwfZIFqg*p_6R=a?HsI6FHpwQMHaTpTMz zN}|z$GED2Z!#_O}^8kw?j8#+@Y)Cp(gqcRT!xJT7Pw^;iZx`l z?17SKG~gK)L{{AFh&e)0;(zz(+Di|XCP!NwVLae$xl-RsGJ4or;cUBe=1S`({~(sS zb^x4z$DyB2;xq`1umH}zpiHpr7s+0eROAu$*NJr_q7`vv=#Cd<7vx*%noWZEizj1j1@D5Eyr)?bK}MZv4NO8Ft%accfJ1PtzK9`N!*Z0U(q z)Sy`&5#$sr1Yuwc)h8fy$v5<1+s1!4u|1lF`62r2bY>BRZ=vTPNe>ht9bPSI!37^S z$0rM*q67sXtI|zg!ZRY1eUDx1bdse&0X?DBlEGOzfSbHBbddGalEiLTy5SkflITG@ zgOn$%`W5X1HN49lf2Se^)&i*}GB>Eo8Wg2+PiDPm$YQOtE}T*zwk~XDF6PZ5E=az? zrYv|c$ue^&SQWNxr1b(^}3N#3=v?98D<@6_C=&6eI5o47lmPpeMM-@7r zFI|O9@Nj0ke6>YTmW^tj?PyhhfprS8gxV$o-=thi4u{8&Uli@eE=`=p-wlQF(+NXB z?#gU_`f72buE4=Kmy!$Cx5B3`Z_i8X4X=wvCqepr3q zzc(|)5>h4t)@lU}P8lbM_DtE$HZ)z&%UW?>tP&H{aSno8m?N~u0BnjR*bW_;B+4G9 zOMM~=b|f>ftR=5>W6_%M?xzExE<0>YDVM(#1o2`rf`9m_G32I{k`qu0M&@qUQXdpx z<>awFd3RKj)5jBDi%9uuf%_DMF8liuSq_Zclmul(QB$iwUTR*Q2w?yi72fnrChqXs zFNTyL^pCu6z!BcAu|ssSNW_=8&!axAxc9oh`wD%xb%WSY-dR#)UsXY>vEP6}c;%LI zP!D54MMaP!gV^vzi_mkaeZL|LDivB>P*zuHRGOD-X$%l+wMi+!x(@P?CL~`nWzdvi z1)bc}t?}?g;Iz0cAe-2oIwcaJq`Y0V7q+Pu?MC3v`0>emw^r=~bU2xeji6SO!5gfZ?A=F&*PN zC42XCh8eN_?uR*G%g9I~LvcQo;dntaN#O6Nx44wFoFZ}FdF=gOp|y4Uw`ND=8G8pg zmNtK2Sfia6j8!iaaMY^bh9|CVId-#s)v7!-7iA{e;DETImg(%*3tnCgsDc+u}8AB zosan3$-N~b5PD@#cg`#c9^~#$l^XEH3?!2Cm=BQxu5_8ev0m1$m{%K;*~W0LFsyVZ ztQ7GWXn)sqCG95;M1tG*IljDeGLtpQ^H<9T-u`}(*ZT-)BlTkF#g@+a{|p1k+r$UR z2NQFeE1*^i*USx5M;}ZP7 zaY`wXtplU5w1}FuurFRoTz%5->`sg-O~9tw7R9l6BuzLeH>YOR_#kn<&EG$)ROZwQ z>mAgR&%g6}e^Vtn<>aKKiO{eqYv}w&mRe@5$aGMzRm9Jz*HhzR^1SSlw?4#?_Y$cY zJ{5`q_%tS|?>=u04{XI5XYo27i=@4@u|K{>HgEL|B$itd&iDKxy|9^jQMX=DUv+B1 zxsIApcz)6Cq+Y}%kHRQfiP2s$S8La%Lc*S7m3-3nc#jLf9-Zb*r|^iJuV?4YKacak z&h1DCE+;de1lR7l)il^(ie!xzj@3+UEizlJAKtI^o!iWr=XblGZ#j3wfd;Tbw@FMp#(b z9(O1f2vsSC)Zuo1X;W&{xh&H5BxQO-qqb(wRb{Key_Ge^8h{p0Bl{ArkTsGj^f3>S z^~C9tVy*bx5`}CQdFqVZQpz*|ZxOs>q<(Q21dB{~Q{b6=eC-rPUDOG#{b_Wy}WufvPU_TrKH>~-3q zwT6^uNYq(uPZw!R3IE`S{3nk+Z8&Fw{qbD)?85$TvffX4mE1S^z>htKlGk$VJ+SajPTXEl5FM&foD0|Xm`3H?=l=?2BPDy4 zCz9^O8)_s-!yb9U)lfo}@yxb{$;w#0P#762nSb_J+h0!8rj&kkUHLN}%MqVm`BHOX z_bu3e%EZgg{Mo&z)}Mnyz1zJT@gb+ZT^vO3zS}OlUTw8h84dwuK;LQ!6YEi9b!J+e zc0;p?yZUN)rF9V%Ge$Xic`!$KBG~Uv5a<%! zaq5n|iBg`;-Z2dMZvVfB&ilERqr~BGRS)JM^^cw{IHPlp8ITA|dLlV><6v zq8$B+$Z(Se`vnG%jIgk{`5|W|y#(9rFqT5)#j-+kan2gG_gN~UF8=VmakR_^@#X1W zvy7c}{>Fs4$op;2l<1CV>%A?FYU+$&3D<<3>J5eadL<3yrDBc||D1K<@yD~7Kh`2t zlqy5FTdB~Chy35AF+q)p2O&qo=P)j2Q~xi6i&sm)=T3bGf$S6zlz$)-M{x)x)6q7mAZt3 zTkGuBc)G4=%mt`b?*`d)*9XE-`_iTRW7XqFR1=&0~*W9V?b9%uE znT_F_RAned%3m&UfSINJISnq);7E$EhH07E+OHG!Nq$yj>d1%5a;2wAqvF4UMNYG)s^$({c4Zv~$;%+SaDIN-D+z0nxF5d?%x zZ--5~C14ZiHL|IoEQ_hg z8Ld}v#VX5C8|GredB%9a$bpodJt|~c#iaRXG4E;fCdeDvg#D+MrMHG3bakNVWDVw2 zo_Nz^yQj)-OD@aNfQd;2%4>})JY%p{)zC0Z60Lo8tw^Ho!okNZ zbtH~|RtRD2pL3M~sYdm3&2)=3y(|b=geHrqsY%L`BA~od`=#ivmXJd#RZxAzo35uS}_2; z0DtI6D4`h;Y*TQw{H_5AuJD1)jN?QVH+MDYN*KIw8c{GvP9zdPgek%;@uu{Xp)!7> z*oVhiH%dwugM`}f0*}bqC!bK16xojyf3e#r2f0EiTBDRZU|(IRuG${gsniBHHaAO~ z?@k7BkM+K~LPwCcm|~+(%hR+^8B+n`_)704JeIv9>%Wml9w$sP<&`>lYihM+s4p{L&0ddwNWZj)d?x@H|8^?BYIl8beEa`pZ9pFe5jkLFlU zzPf@^RMm-;jQIaK{QRKr1|}w{kpz^A(jYvH3+21sp0o9W2Ea%egn`>mW_d@wD|hlG zEwJE(z?oerG7Yx*_4S!3*p-XpL7PY)gj4$gZTCf4A?Z=MJU|a>hxQNK#UV8{X%HwO zL`}Wo8S@XaH$|0mmImP?4`;XY)YObc&l&0e#ZM92Yi#XkTFP!T5|Ja`_H3h2`XbOp zc321CHu%T!1(cs$`_x{4Rn#)&{l~EmAGMoi)opQV~V<*$1u?Hvd;A5Cq|`}4z39Xu~5j@}Pq`~wNo?t? z)Fe3}sO6$kO!dlWzzhb&c+%i-_-kN|KP@XgoEB29XOKgn6Id2$FRN&Jyzl7(*Slx@ z8*mq{qDkf%#CZ1Ntav=rhIyP#qH)&Yr&B3X3X+{QU|^M`rV|z`(LZ@7TfbO;hR!OC zZ4e$FE(LoE!gjWXbrtVTzLMu2V3T;`czw2!JT_oP+&-mg;19q|XKrQXIDe?Jgv1j9 zN{}UBG`)v6=$y$q?%PIP#PMbM=4eYd2DymHGuxHGc*H zmVl8+yObH9nWr3uTbZh5$w^|OxcLDqQ!IXgX%@@n@Gm?LrFcx*ejgNy1LExqttw3$ z7%)szCb~?K3PF9=;GU=ob1A_iV_*d7AzZm#)kgj#0CRXIOb^ZhVrf;*yh|ikYfs;R zlq7Ygr8x;Lfoi1&Qp4Z_AFcdn!hjm+eL)~k?oa|BsAz^Bv6__v2l5Y@egNysr3@_w zBXd+Ubr?IFA6EWiL*4ob4OVo~%j0vc4ylfaPo9l{w5t?grW>$T&qDz<=@nwK0G+wU=NM3>3B-LSEREc`5cR{ce;LYkWJm<8-V!QtDpzSYg zJ_%G1r47S2VvwK!BSD1I4FFQ2D#r}~*y9?1L)ZMfC?IF~gvapx$4^0gj%7Q9fx}_l0(Si230rtxGL%{sxucH6EKJw>L0I9?~Rja z!~f%QTD<%h=Z0~l$4};~ZWO}0H)90jKe7Q?CldH^?_c)Z(@TqxbhNjhhsA|;5AZWw zuXLvrhgo8~Avw&j^H6P=Qa^+)i^Xt>0K0mzv&diwqsBIbw@!U#L$~ffhxx9%C87=B zI@Z4pYgbtcixA)aJI$#|6@zR~Br|095XK_4zF+=hIO%3Ow>8pX!>s1)l}-{>t@m{% zkV|3{gI><=%__Il#J{K$$MuAK7-M>iVgxoL*ZO-Z9Ik-=!t2N{k>yi-ElVG7NZ4flFLQfkg)gqGyd?T z0R?1+|CQX*3v2r+rSQoh4ZX)EC7&abkul^apYj#itJclUVSDq#;VenR;AyI;o`jIc znp^GWS>GHdB^5dSf@b(NuYv#XPd)KTpNZR}-fm3c90h_vSCNEivdM-wnj%m28Xzy4 z*uqkP942g9|dhgdCwsxQ@b03q=E*PY!PK&|-a7To47rI3XqA#c3-^&4!y4 z0@ua0UB`nuqk5q5wWCT1f@j<;A)E6;Jl65gPgrvB0>p_@O@m3Ixt`ZuqN4c8j1~c0 z%N#+%1;qy4kzj}7`0IrkQlkHwg1Iu@e5mXq+V@-iHLRW5G*UlBPrz}o^*b_n!8fL2 zPJ5b|Pm*+Py3T7;YT|BoMKPOs!5raC&K#8jkjp{GU~u!ekp%$3pGvbeNU5gh=h=cN z8HL@Fbux@8(`a6$Jua|GmH`Yx z<5=QP5-FW-coQey7ExUs`-Qa1rM-}W zCvQ6#JW?I82E>&OI?O%EQuCGbVDM|E!n~5L(fgfIKmR&J6sPXSX!TQRYzoF?f;4U- z?Gj(-pI=G$!Nz~~Iylg{Wf;M;=@t`wb&UqZh5K#4mKR~F#k*H#mK-b7=la~v+aD@7 zGvHmlSW>?jZQf5>IJhG=V(x`!dBG^hUh7_x{doNIZ@~XW7``SaN_*?VahkYe%{&cV ztS>PaU&@26{pGLvA4wMlJ55!j#^{34alsji<-zFXxzlW~ksOl`YYqAB#3?`ZH|oim z(L76WG2Fl%mPspx+X=%nz1*?GU-E6X)svd*708N$Ne>aFZ2neiyKBGdxCZJPyP5K= zYb_na?W{`n2r|B%!R3dGI`Vv32kbV{|Hc@OBb2fqC)A=I4SZg=W$5$Qojr_;k?m*i z=nmW69hSC;xAojzSb`U$4d{u&emBG9m}3r-DzZhhX$JTMl2f|Cxd~Pc}NTQ2o-|w3xp~=Ykz7&ea5A0^6vc z$kIrU3%9@MN-#zdBDoD=apjqYOx;~4tx8poW*ShCaycgI$){U}7(4>y?QNu1iozN5(DU?cbT>`XX=EXYQ+d?0-H? z7ZR%;!4tGSk~=w;mrRhlgaD^9kQaBlU1_c00~>7-QtH8o!ix@zkDoQ^3(qo0v4(Hh zJ5>|kNABEhyrZtFIKJ|tY_$(ATdv>~t)sE9{`BE7745?`1uvBSFe~^5Na`IXK~vcE z{jN7s9*%;=@9J)@PxQWI*?g)9XL_(8p`H21+wF2pbKT67EBjBUeJ^xdanqUzLzX!T z-2ZBm@-IB(7-_kWFseR5c|9jWSEqf&E~Qh29+ih&H|tMqRbKvc_9oa{2kJ{eFPH}J z%TWmw={No$b`pjkZiN3j@hm4pG*&m6H*F8FglmJfB9J&=M8n2kAYarpWc!R}$@g+m z!3;sd(E`oX8k7Y6*^+Juq*Ol|j@Wu-$`BR)r~QCzT7^MtRK zxHWl2%{i`rkvtRN9E19vu?)@epNELpqt7x?E$lxMq&7zAH%c;y#3AJp`lbS$I_vU;%BXEspft)3`_`sf zDm?9SRF4xGUWfB_hZK++eLx#D$?4}rTsn%^0w~S&cRi0`=Pi?fH0aq(E(rvi$+GrEES2zwmgEyDHK z2JpB4405*F<~@^;il!317@!MCo7o%;kmX`IY_O@VnW=i{;;cBi&jm$l8TfZ1pK69_=rD$c;dUVsBcbng$z)`ly8X2cj8zzw@H` zAYxL|x*uA4eM3Xt<$UF@(?hYp(s*y4`nFoO9iN|5wno|vf&K3q9@^ZN!#L;c<!q zMAi7oVKp+rPG!mkfLXN->oCVp%^lJbQY5xkC2f3>=rCtXA{83>bN&mET4GO$4YgVe z`YMf!k0o?qOxAGb1TMt38&a)(jUi*_+Y*%voc%0k(Xng`pXz`HI`#)&6M{!v9pB`s|gh)6rDkalxVB7;#cHoR8I?c z!741q!jY{U!EqE?_& zLSec`+=Wp}FPp?~T8)h-+&FkUN2SB&S9g!5>o}iL5G?;y z!_q;cdVDXc;OF5`Ic2-D=$EpikCe230%E_tG>WMAS~u&NisBXHu$d#tD%2yAvYjj_ zZqnB?^mnX$P4c`DEjOw5_-wrGCI4QcL+kY>0n7Zr>u8aagUmq=R#+R#x~I0dksm9d zCHfdKntgSNPZsL!vb1x8IEMXQ%NzmE-AJ->fA(%Gp3Ysah{BCPq$10gRgZ4?wLdCx zkFf2F$MnWq8=p>00tXY_ZvXsC6C@+M@Va{;9+J z%vcKJ1p#Gw#@^j*C2C|xSAUX4aYD^XBUEO&t)z9(MVR_!Ho)I3tDSL$8~2`;KMt}5 zX>~JzUyF{qt1h;_kkWaJe0nHy^Jz4bF#g5TIOFGTY%FW20|3S0_zDMcW)^yHo!Rc? zIb-msQi!!MWp zm)+!WQh2S#cQ6PUY(K!Bx&=z+SzR@*9Zu8^=sLOzIgWG;*NLa~p!EzBxn1c_3`lN~ zgpmS4>aj>WX)?S#EMGD>kN&qxxi|7Ps|K-kvuzY+;1q)@Y9$qlH6DB9CW7vygraa)u4@DkaVLerK}CU-_~s z?f38Bl^cUeq(`@3B+>RTLzO3dJeG8wn2z&{pXn5ho6oHpjkq79JpF#f7^pR|eUV$g z$R=SLkuG%0aq|}u*#docfXJ39N&eo;S-0Rk!SIjSfn%ixV~V@M@}cu$2uOvA)JZa*O^}+z=^H!o zY}7o(iR!ZL+$U0MA{1g7hff<@;yk0J_2iG!AuohmrT?iKzKroMf2(}y>Y>Jd@B@8J zp4+*AJqS0jJ0HHRN_Y9a_&U(2tA|aM1Oxe$W^s2McHzL3T&&;l_Pmg_tl9IzWpq(Z z*Q;|1i}K-aOZ<`Lb#}P#^y!m;Oxb+QMVi#_g@P3{?#@5h2`S|*-!eIQ2E-;u6A}~7UF2U;b9SzHS-6I#ijBp2BlvxqAtzaWVJvgFnuXEnw=cL& zj@nrU)KiP z+LEiQt1$1wmZUNRV8@bV`(^XHwR;ker`$qu=mk!hoMsh6hXG?zkaQ2e&b#k*IgBp8 z35+fH;^gEs&-@EKB7PaCBDTufXvF7$-2}x1+(51^WsF75+hocZdhzWWFkpA&A>sP3 zlSn4o_%c}~pZc-CM#nXdgXd@MdhPs^8mS-WdeJe(A7|DG5Dn&HjR^WACOgyCBE^T}!7S(sFKUz;NiNK#i0DXlC}CcB0(>S1FS z!Kua4VI%nvDuX8fv3AhQbRq56um0st{*ba$1aBncVX0gcva9TB`SIcMZhIn6B~EG8 zEdrLk5Tq+P)R>qiKF{$ORqmbL8w~5DY(E!j6pM`wpsysET^dp*)k>J(W?L%rI~H^( zu0OcV7|=aq?)%l5@hr)uZ<{BW1lcK2x- zGTnM}GPoH|!m(HBHk{nL45*>#iHV7$ZV8y^={II>4^I_sHf^mpNvcY}lpHTJ@T!jk z#Atd5tG|)mBkm6M_x*WS*p*7K(|*Q`-{T!78N~uUQI(aI93O&S2(8*yI74`r2<77@8hDc=klp+a09M=Rf^ z4ZZh|9RUS*+r1mPyd~Inwy~yb#BP3sm5puB8PI#VRYzwpy3N~BtNe2AWq1Q#p}DKW zP>MO5tEX1(PCQP!dq2_KJX>LEx5wYKVuL_Kza*r-+)7if^a0e55-S~m=C%uxe+KrU|X<4@}91X5M6HOqdZ7QCgU zEoGsl{ZfmO;1n9VWZvJO&>z}wsO1_uFi<%|Xl7P%c1@(GrA4fxtDdZ??^C}4K#qpI za;mJ5n)-O<56|L1Px%<4^6RtQ3DYz{$xP%6TuV zouZf}KFtw4(qJ~xowrHuim68r1~NPl1!@wdhISt_bMs9+h!}3tYs9!{m3H2a`# z2y5-o6{eAH|d*YyVb`7WUW2swg zmu(UDr2DDJQ#6!S6tn;e2VKgkC@egicDSX z|A~$7k|V}21Tr!davPzo)r2KcX)eDPPnH4~d#M_)sjX5N?i-f)xElOJg2P<-tf$^G zyk7ab_XR_c8-qCgOQeNK6}k~+%Lv}*t`n^0t z2Cr=_;&tcLU(C)KO~KF@UI#dmirA_9S@yv13rla2mt(VW_-uN$Y-Y?1 zuR|DKmRP#f?jTkn2&Vpqq%iv`IF(}w&WzlzCjG>_ERuc+qSHq{^u3yA0XQKT8zvzpP%+hQHE{*5;6&_a~B-A{5;Lqu`7($F}oArSadqHXRZ!FCHguO>nab2^~ zg1ycEsdCntj{68th z8u?vQvN*%u^}k1D06Vn)s)Y6v0K9%P==wj|hO4ef&WA(uKWx=r=hmyv4WEbI2G-Zs z=74%5cjg36o|Migi#U%7w&%|XD1%w*X)cg;!WK-~(6Clf!h0+wx?vPQEdk4m*n#_rrXtRHLHPeo_LUCH#xHNn~ z#^Wyz;>{0Ovj)WecwzwFXIjk-R`wYjbnIzibiWJZHphoSOtjt+61c_ATW((3;H}tT zfv~;5u00Qv&wdWVlLp%GKp! zmX=JJL6ci!@d?XF8Ne6qDmVeD0Lz4r2{a0Rs?ay!#>cYv@5P@SJ5pXWmGiXi0G(i1^|7jS=Ncr+zMR&eb zMt%wnTKh;0@@iD6f8=Y8&9s=LlfvV}ecix?F$j{wE=`OIX4hWzv40?Bojd; zsyo#g)t1$RSIaaBV}m5#@ypw1M;~A!qpR`D*x&JmvaT;)a%I+xZtcFmRm`60bVsjEv2T26g@*;G^q_@LS7x8R zFvPOlkCJY#1tCHRDGpjzITy#mpMq*Px+QxRxOLRxN8-m6Vc*TKV`x9r@AD=ZdTl?S z+k(h{7hLVn{hdG7OfNV-F;SxErmOa;ahr)~Jsck}C4I@%9uiO7C($9{RN>O&az6)l zRj%oCnj4Pip1fGSpm{Fj z{>(1QUm2P#;J{&H?2aqNScQ(DtEtWjIqexp7XR~EO`k$^B9^nEl$vs}G^XZx1FzQa zbW3I%yl1=(ffK&U9bK@|tgC16a3W$N5GZOro+?c%{;vq#pi)o2GEj{0M&2#VOe5~i zn>QgT4y}+Wwho~32_Im+XJzL5lQW1m-dA|kFKe(1r;v?38>ft}B?d}7fVW>^iKWBZ zu;6w?r%VqDYEt--V!u6NVB&BUCJ(heY9?}CD zdY)UK5+6rR6+Ogw>!Y+q6()O1504}Ap(N*|I_C)!SND-e0pW3{#vqS|tlpEGYwKBA zZDV!lI>@LIv6f95Uk=!5s_}K~GD^{>V+v)?PX8=b#COnNHkhKrH46S+fIFCMl&tmU z)d!Sp9Y?R)`<3|cYN2b-UtfbA45T_BT+vFcAtr26IB;?1DfRErmRgz>T8qc*pDM>7 zcny(-##z=CC0vil3|M3QevHr&mImxb+7CgF4((XxCEND(tIq*(q6`G9sh{YF_Y*zp z$r{;2n0gW&l{7U-t3Gfua>14J3jBtzd}%nM3#By(Uj}2AoBu0C-pcn?t*~E2b?PrN zE!n>f)~OzmD&Jkgr)wM?@RltEq?m%ck5N%}nXj-q+SHF^pB+s8H6!+TLZCc$)gUT= z%mC-WM5i2TeE#XRi1f8ErWlQ`_4&?Z=LXm}qB+;9S$jkug53yUntoQ{4jQ0^aA-ab zx>~39L=B*SQ07Lk@%M3{nWj%%hCp5{Y*0lv)y!R(N)i96WZq#L{m2^ih9ZH_pLxAI z1YXuB|9K^yMQPn(_P!Mdpmj+*pc>(PL|K4r%lAEu7vJWh#2#K}cx3)C`&GEERxHn;%Ee(IJe13=%x4 zp7l!a&v7B1T3xlT+8TbvTC>XMVIy6Pdxwyh$Itx<_k0}8^TG!Tqo3{%zpBnQ;#FbY z&w0A{`|B%>Z&O8!0hR!h3kFiR|}gxVZQ5nX`TfEgp8a+ z>gc$u+Q_ONrvI~i57Q#=rH)Ub&XV+_1~YMXq)JYN;;LT3;>_~a>97AO@5{Nj;`G`g zj=Y>ewd3>Jjhsh{B_Dg7fq!1+urEiuy}iul_hSERXa0*Sm|A7>%9ZOtLHyf5bKC51 zwS-5}Mo**0jOaO}E6+u?fA}$(wmAPj>m|?Sv@7*uPt#3AFHaqm{E#!l;{5df*v)Go zIjI&Zo^UaVd^|h#6mR`;IBMpiaL5VNJ&6^Lj7~O3J}%Z=ZcYDOrc%ngMWk8!`_V`C z9(it~9glJk7@CS_MEi@0;-5_EIpmB91*CD@0DPEQB(9*F3Y0+=MmX+3@$Cn4?0scO zloMw`;f)Dkc-t}=s3c4$9a++;;-@79<3bdmBcFe7UE^@nO@)i83LOgti`9Y=c^2+B zKeOM+Ze-C#X%pzMERBAY%9BFj#61bjk9hUQo@s@O%0kz9(FZJqX~}>`RmcxL&FT4$ z^CL(Z9FC-L3swcA^S^8-|LkbAAX`9|5-s#$zjZ zbZr$Eal7$@uPx0zKl`eGDZO%21Zo0N-f|{KF1H4bl=F{e`DDYa^;ilC_}PZj@Jb4Y1^E<)?quV3FjUu!<*UIDCoSy5@@&I3>( z6+Hcg%R_`J{fFJlmh?rYo4;FI^BZfvgM?{3uhxG}_HSu7x~Sm!Mr6oPA1!KWQ8GBx zCa~xvc+?H{!bF0~bZ}xyPhY65clYJEiOPw+!qs6__Ka1Y^S~|$=)N-PE+76T=|jx< z%ftctgxTBTj2&9PBzrjVd@{#j#;C!+OQxX#YPiQF3ynca`oK;%^&DzGR(fzh+Rp-h zY=|{bgY63ILe4lj0Y~G5GlG{MY`T3++GpL4T&Z_#4?vl%^oqry1TWNkUmhfV<}3C( z-^qyva-5Hdj!TL#W2p0z+|uX1;o$`O!DsAi#wX#Sh9{BI1kW7i$B+}0H>(+q2&Xw6!80_0<`%*mSrVWZDP#};k(W1-Y- z7b+80e-b~I-3)(S=yx;9qsJ4_IO6;62K@VhP~~AeKzOp3H+hG#)r)m`C_g!1Ow4U& zq18C-z_?zB6nD7$@ps^g7$Zkc#s21;FyobbJ{nMp{q}o-Ar!RAXCh%1vA~Z>Ila^J z#HaH+#--c-oYqw5F5m>HT^uala*4Jv=P?NV2qH*51FGXi;RTp!1|i4A1Dj8R2}q>+@IaaIerw5)xX8?bd}{97bc^#jzQ|%3OW`efyr;x(3*jgLw3an8}_w&N{}d zxIMr4PiGBh;|gX9S0#`t=|nn>5>yM}mS}gxuAM$aSx;c{@Hgu9E7RUj6V04f5;GTT z_lCDkAyNOUv9k_~>g(G*AV?^nq#&Wx(5Up#EhqzsNP|I1$52B`cT2aFfW#0=3rI^0 z2qWD%H0aRbS^S>oeXsX9*E#1p`_EysW9?XL-QWBE?5=er4W}>Z0m19Ou%2%bhTE<_ zqY1aQgEao8X0uj4XMT`v9_{6_rMA3j@7)>ZfNCtW5lt zhYNdnxy+hRK2S2e$l3$b`d*r*QMcWr9n$rVUYuKq!)?LqRmDNNJ;u(wm&Xofb$uim zj9;XecgK_mN|z}ZVcg2kpFj6*1y7rQTcIhq9VBOW>5S2qTEai)VdRG=-Z|r~$(*91 zN9xc%k?xrfy2bYVDLjcLAL^2N&!Z{nCv9^PBwY&dvo%@D%qfiTI`&TFdUXI|FuasA zwm;u)Kkm~L_d`;cLrB`*xjLp_ZvQllob!Ie6W$gPg}EsY2ctx_Sa(Wx(a0_oE1@|# zEYWMxBXx?sDMKNMCbkoir}oTY6=y6s}@9P`bZ*ZCJ_X*|?eTD1=ICKFqNE!c~rc>zqz!+tE3dTbL*$lWUI1R3`msLXJBb8BR`|AwchC#9J% zr}C8tpCX&%02|L7Rb#xB2dGG%mi;Wd z<`K)P8O4Y5yap8!F#?vTWNDi3AJf*4UnY4zaeXSFZihAKo&Nr)D8=3b@%A*+q52L; zcOSF2zWnb0J2he)N&j3bVyJ2LEL`LJuWK=hlv&o^eBafe-QMzq87yR_f5M+bxJ?xy z1KxZvO~@lFqKld0{(*tryN}GmQW6+Ve(a?!Exq2yj%j2_1nGmkb{7UEEah4M6y9M* ze=(i&ewCx?zQYjFY40)<(e$5DuCZdqHVUtFw7AyG5~?v~1@SB+VK@3O{#iOx9d{~{ zHK`}&%Q!|{Za5c7v+=~=1U)z4g}ib*Xd#dMMgzl)hgf0NGX|H=YCj=qjJ9KI_3JD< zGUdF#hT+dV5zHnNl4SejA0y1eNuw$GRFy1eHdMIp6}AS{*^Yb6Ttyfa(S-#CVddqB z;#0DZkF(zKX=0@%Rl_YuI3ON&-7DrOc9G8@2Hu(+zuBg2b z%aj(f6Rkd&IL@)GvlV=}?6r;G?6Ee&cP;9b39Lu3lyq{!6b}8pENnI8KgV$672+)s zDN{QkjxQMYrxY&mM1In|$`XORc9yd-dN{p}?D z@D($gA%{7SWm5eJ`y_bxpIahoZuC-h58Wdhy<5AyN4YZ?!YgeS^GrKM$RANKNtk>e zPUOmLlTk2g*?)93iilBnwAQ9VJ#laHpm=ZPFEEaSldEi?y2qa)ty4Cd)Y+_*Pl*?i zzgIiT4hCg2Ge#ynYg!}&2-g^98U81-y9zQ>PlasWHDpq-eKx3<<+OI6T=5tu9@fd= z7YqrW%nJ>Ls4rw^l!+MgBba(0AmA+FEJ+zi7fTIbpv3VniSv~V3Ws?{`u$0+Oh1cQ z!mH5x7`}=58B+9i6ST8qw|GGV;k(1LY#36|!P10HZA{o)h9D~FMFsax zdBFN-zxx?1sAwvIG^GKZ(RnGq4(=eohA3C9FCfD8hLI7(a^>eNlB;84m^U%a7jBVV zm2EKu3b^NA6+X*s9ZsS^eeq-$YW3`iVMLDoAj7G_(8{Wu&%$E`!q(Z^$(Ix73Vl;T z`sK75qUt@J>_+vax`e)psxT6t$5OmyzI0hfGkVZhVaIHt`?$*xFRut2(VMpeKO4U; z@9doKz^}0krlh+RU;BZ+_~ttQ_o>;=#v3CUs&!Q|?O=Khhz`LQ6T+{PVnEXSOSLkm zKYH-8ICn5$z{50#a?SAEiiIZQ|;Ngd=`DUSh~F=8AMRmwvVE-txX4Fhl3zWg$2Yo^~B*hJQBrbnFr}WJ&)f04BQSAiz5T3lmxsUq# z`m9{U4?`Ylc~W=%08_Dg?+kELL`m7?eJf10w{cv2EN*M}uC!Emxo)KF&0SIs=(42C zGht(w^ObAu9jZ5u8XZTS`zq#?M}J2~r`&a#J(8iGG$j{&z4BSXW=dSV|1>W){s){F zCYtcU3RAZ~_7f#&InO?D3wk_r4W|lsXMDZ7Z6FNP=O)awKkOeg&yrhs(5UA;8(a6U ziPY9aI-7#|OT*EckYqc~d^dVQGv67PT~soV9-@%Rpq@WXGAOmFa@1FRmJOGmE!JR; z&(7wzd6}okj3q(F**2REyfg1D?RRX_?uh$2=d{cUF-cKy zwrcG9%qs4-%$n+@3Yr($iU6(+0Xshz(nC4L$hl7xw3EB`=onN`u!gQn-c!3pl1bw_ zJM^f3Llra&AHvk6e-M+tHhfQ=geJO1L=wP(CnCutzKW zGC3I=yomHH2y640&#@oEy7Fwm=kqhUD9u~|aG=;m;Io{H>W??2r4tPnPby7X6hq1M z*k(yGS2!b_rfgroPR&_*mh~rJkbqv4pLvZ927@0@yJs)j@@JL& zPAZq+Y^GADPI#rt6l-~pU7Xdd4s@)w}fgu&E+TLhkxW*8l=Db%hFbWvHQVGwE%^#M&z3v?9Tr!@cS7-%`@|l z4hF{tMB1p35NR3!tWAEHW)KkoW=RE>TDYN=6+EI^o+&1gdrJ26MV9wD@DR`6h2-*9!Kso_ng zWxqb?La>-?pMvIMw?Yyam_!P`{4js){8bGe$CLw%i1+ocForTt`O89;KSX)xKTztm zeo|HVxwO1|rkOyg0r^JWUsToC+xq}dK5%YK{*!=10(UXF+^rO3*ZR#^E z0tZ&EvtE=kyY&~s#T+ffxlUQ^$Sjk>meo#SV_mFggTgdWjI84#4rr*Z1=-Hk5l`&O; zN}oUccFe_WYZf`f=s*f$m_3Ik%Yl5G?}hb5_kQXPtbR5I4phcWzsnQk_2^qamnutr z<9Ts^W=(JZHoiXqHmXTDeTc!o#{QsElVvPQKChri*sd~v+vmsSvug^Ajb)|umpZ(g z{w7)7ACBURiI4n<@{1N42^}d0EC=8Zj8s5%g8=v)-{MU_^_*z+@j}%=H1G(ch2-t; z7JOt`xSxRY0_9q*bA{W=C3_6tuqbQDLY0kqq!*E3ZK4f(g|iY&}{SxUK_|05|T4J2<4>Pn|^&D)Ri!l_qMg@speqxlE3 z9J~8o*b+hfukItT6WQ>X?TT^PO4xEqX+Px?v-G+UM(j?G^4;PJN%HvNO^W_rG;=1y z2>cAR04V%1dJnik4M~mPfLc0ri`P-IFwux?gWZUVBy}BH0%kRZ00C;|M(Ops%)SA0 zfbzl_!jXa&?|DdOJ=Zy~DbfA{+&6s``0``5mq<(s2*y9bz|husiIo0XoNWTB4-W|R zK?C?-2fdOpb36bCTW8Q*kgY$i8mpbaC@o&}lch{ElB3qSbt0I|<6L?Qksl5=1Dd;o z3^cdPx2J}nE8|l`JmXqVlUITvT7Tu)xxw5#M)8$&mHGSA64X&jV|6y`o^3o1G1lY6 zF&pDh+V81|qmE3jT||qM&pL-;MM@AGz(3s+yE+w^eOsK8p+Y6>*inO=os__+-W>TM z{Czrl_Nb07F{PKL+Nzt;f&cf6(|Zja#E6T}L`|pUmoAa_ z<(_4Kous*-j$NYWy(b4}bVO77;cKhqQYp=oU z8M*cp*k;?pVq;T;r)|2J3h^Ml*?BcjE5Bw zD0y@bXX&HVbn6PahzBOd7zge~CRAXT^^)m z%o&I8&(h8|8)NO4jeWY8(+nGrJEH0G$CS!4Z9PnwzMdyjr08w!t7 z4*vuA`p4$GLu}F51qN0t)0WWv=C~Ofc>L>*d1ZCZFi1sb6M6m(BsXY2+$j5m5ufUs zq-y%kB8y$T2FeLg%?`mRGNTWi%G#reEE#r|>!XEBkpc`TVjV~*J5)ajQ=Vw4-!@)+?<*+XgbKA@K4R{A7u zdx{wA8vj{8SfD%U;8#O91MW#?F6DH6?W&8m=aOw^2|c9zxk|pmzvUeYMit;LZy&X< z39~_V7Gwro8hs@@_74Pz%wu`@)Xk#6pW{^My$2kBXuKQ|l`-00@X~!^gM^apo2Ege;j~xCkFln${|IKdpq7 z2W-%*vV?4{7_2%VAhf0J8|h0@>6iC9Wv)T151#Q34-7O($jG$a5O!J_k#l-q9oThj zkOg{5h9n)L+laOs8tTq>Opo$Ty#q1VdzoM0wIKwoeXnNDntI()Cxtsqqm(mue&E1}h}g&bfQV_$lCKz4h%VA;Rkfs?M zw7#Gy!`0X?7^c<S4#B9Sw9WC0MzpR;1uT2ve;k7|#9jv==qcQ#x!eWva{_%!O(f1_RD=uC*)ljw+ z_fvyQ8{6R*0?~ix<5!j(jzlDm%a#g0Y!AHVS@tQda8Bxe-@~ZN4VxcFI?k-QO-tMT z8MV7RoaW`#Vp9QxAPO}PHBJ*C_}x`e9i~Kz+g7xmS~DHpye}UXoNHoJsSiO+NjiNQ_ux1-{+SsgK`RTsIUV9%g-^*~2GvMFnwc!P%R> z3Yyp3;`tNFGk?32PkgY*l!XFFz0r+TLuN@D)BW+qm8I71aZl0(pF;@q&S|GUAsQgs z`u`wL*dD{>S+~%;@Qoi_1KVx_i8@5mZHe!K$BHEjH&4Z&;%jNT^h&g+32F`<1d>r| zBEdJ0sDxJ=4AefRsdJi{45T$@qPdn91CbxKIQu3SpVgI5Z8GBG$Ubkk-aW9o?B{zz z24T$VYY{>AIb`l_!MHM$E=TQb%(cPPEw7q?2EA2My3q=7#^eLs_@=U*O*BKPjhfUI zdG8MK_e3w(s)|0cdTKqHWN?nC$ab>IHvY(cga~HR@c7zEC~WMfC_-lK z>u9^H&!*)O@BqhuZ<+Yh0@eSedhj)ztWiHODzqBKu>}zV;}0fEX6CzG!c=E0t&+g`!Z)OA9LbyT(B)%V+J&vqgkD0y>;7DCd7%{LkmQ%c@$ zMQ^8?A|>68*vpca&>EE1Mfscdvzvy<2S+d!GJ>1cwh`#>`E}qmu=wX>DqShKZBOt; z4WbV)H!O* z{%e=srpzfmrLohP7uKSOzjV%`{{yI3Jt{M6TKHExqe$~n1&R8|3+?Eh{GOs0%lnw! z-e!USO2?vX?mGw$V8zZoO1moqolH;Zp08aDazvM&@BW*>u3VW>&3s`Pg|0fSerwv0 z)6fPitRi#cmXg^GtGkwOWlki^a&}`sk7-Xd*A||AtgTf3Tbwg|wjb^7_dlRXz7=c# zKRMd<@HlemxNDe$S`E52X_an9Pm3b@%e+ z$-^u0B<5-yxRJk^&WkG%$B^{??gm_P=bMH{q#`7U6GhzjI^?pqzu#FgHbz15{Heb8 zryGpEjBeG<^y!uFz?f8CuBR}f?tS<3-e-F{4P_J_1L0&Q2e-haK=f_;VQP7ZG05+9 zOi zFeqYNHRqlDL2r}kZrf^Q3yUINIZDOB2W;xDFNWVQjin0#-#Ct}-hGs~s=N-S0=3oy zqk3=829*@boU>20n9VY+wA4*6 zvIGV!jI<6d2g&7=ky&UU0=atn`d(`4N0R_56tiyd<7A!bQDL7cpg~!hQ)j*sQUV}{ z72?eeIayi{ATW*%{)!UO^oKh@Ly4`@N+#C%ah-0m94)?CQ$EAZHtLc@zP-L z!N}~S(>{k$D#;`1Z$%&n@G~B-Pkhg-TzzUXL>`4j#&hyk z2L}c+*vf9@g6!W7E5V8K$wZFY-z>YA7R;+_&hIjzrGCrT23=Ke&R8y@Y0*r z!CO$n75m?3&IG`EvWXY6PBHrU0G}{lKVN^=RBOj)rk#l8{yx%3ZH_e+^65uZ{K5T@ zaAQG6&AEG2&M81AH59- zGzHEBG6TF^5nH>D@(1#2geQMkfyxcVl_*@A$j~ite7}b1GMDWa{S=JMqtCPu-j0u)+@Rp29Y2GoSiVBT=Zz%N1gR8Py(B@`)nKoo zoEb|8(df`@f{5KQFH=#Jm%|Y)&Dzs6t_;%i00)uC1#tqa^26fi#Hu1r8 zwAl~0xN5FPueyrAig=q9Ivwywad4^WR?Fx!ZPfHl%K*h6+VN+S#Azlv94rE$%5M2fhRzieN(*x^{E>Wv0wm8P~(hw|$a7m)cHN-m~0T z{{0HpA#ltRu^UYiIhPI^Mw~LlY7reUn@jrnd@!Z52TRzhqLyfBhsG}?&CTc*LRpswl&+G zR*T*#U911Q5@`=^U0aj1xVjNRS1aI5*fch*JSF%m-sNS1dK8oDY6l_+HB?GzEM+lu zW_=X~+L# z3lu&4W>2|ID!}a3zZ_~@D?D>v*C3afu{b;2cETFrS}$)dRY!Q;*~blR(Ri4NH=iWp zA7k29d@X<3wD>lwau~>q8%;2LitSnMi!&!m09UIB)z_s1&qpS}Uh_7G83`0oRvp08 zo!pVh52#dOig#2W_5cV>k?G%4bSSXv=x~(bjEkW{A3zTXex-dYdge$@E)bCRxPAWd zp6{Bdgp7UQ;KNPKNO+yyM4(maHA1p54e1j_@RbOKOfe^UkCrvV+)adf(6a|XasG9z zW@2K3<=Y`%u%*?SQEcD*vahz-d`RR+7L*xq^)Lo~QBf(L{<3|x+ZJouWN*B*W8Cx_ z$c}4E!+Q3`ex0f%>dCMdOjIOz4xao@)s`gTcrIX!^C)1EsKo zgM**kqc}jngri7%X@O7wE+O+{y2WZ7Q%Uq(WRKa^#};sK!eMU!TWzPv?3aZ;K_tq{ zDY$2uj<@XUPqzSDNC=l*Vt1qQGORqH>k97-mT~ZFd_E^A6-N`?w3F2t_hpI=6|leh zdXGP6Xdh94KdeGR3;BmG%j%6iJaXSv8!L?kuCuNK?W=#+x+w*flZA{+U{(+eS!NQi z5nGSD`-&^9^+@N`=|(N_H0@>joBXQg#4Zkc@%NxocyK9wm%jAF=si zxwp_>b|Mw8eznnC<`3X}y%yh7ALhVnGrY5iAY!GZ(rR6kpxC@Rv$pSXs(F_9BWALT zUbd3*2)TbtWV!C@Wc)D!Oj-BtN_y-O!V@lB)ZC`}iu|7+Eoja>g{+rJ11&v$(eXL| z`LN&RAC`+KhqrAxBhsH%)E!9>cF*9(vBl`EYgfZ*a9a3M(EAJf9#Bn|jzr3Wfuie9 z0WQ|$Lun(!Va0>S@V2vcUoH!tAIg={DJB_1Sj0~9zmA+e4iiMg&XNYtzj&Bs)dW;} zJatEyk_;q^=?#IDvil@HM+w9~&lq`{=5~ zf-?jRi1fh;$)C+o4v!`m7wzQ~REILKsk9?+1XBKKe*nVIMa{jR_ScmEO=Sm5cW!#f z*}gbe@b={7L~02Yizq<6!Mwcad{y8}uSb!oS zUJ+-12J)xXqe)_`I~gF;5}S}I2lq2cy!s*tPA&|@ie4sRnjw+u@_qfwjTJ5(WA}jR z5R~z{JTvhq$*$J=N_QXi&R?^m9o<sxc_hQ9;|57GUOn=$|ac*$+tEv)A Ku|oc3!2bdw^q3z2 literal 0 HcmV?d00001 diff --git a/wiki/start-jupyter.bat b/wiki/start-jupyter.bat new file mode 100644 index 0000000..c977f74 --- /dev/null +++ b/wiki/start-jupyter.bat @@ -0,0 +1,7 @@ +set DIR=%~dp0 +cd "%DIR%" + +if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b) +ijsnotebook --notebook-dir=./ +import * as nope from "nope"; +