From 8afb59c0ac558a39992b8b676b661f363c694ef4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 4 Aug 2023 21:47:41 +0300 Subject: [PATCH] first commit --- .env | 2 + .gitignore | 2 + README.md | 15 + index.js | 237 +++++++++ package-lock.json | 1268 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 23 + public/client.html | 166 ++++++ public/client.js | 200 +++++++ public/img.png | Bin 0 -> 69562 bytes 9 files changed, 1913 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/client.html create mode 100644 public/client.js create mode 100644 public/img.png diff --git a/.env b/.env new file mode 100644 index 0000000..75fabea --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +SERVER_PORT=3000 +SERVER_ADDRESS=93.116.13.156 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c8430c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +movies/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f02bddd --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# SyncApp + +![image](https://github.com/lumijiez/SyncApp/assets/59575049/d153828e-6fc2-46f9-a057-e47b171188da) + +Tiny app based on WebSockets, and implemented using Express.js, Node.js in pair with ws. + +## To-Do List + +The following tasks are on our to-do list: + +1. Automatize syncing between clients +2. Free the clients map on client exit (causes memory leaks) +3. Implement hosts and automatize hosting +4. Workaround for autoplay +5. Implement room authorization for added security diff --git a/index.js b/index.js new file mode 100644 index 0000000..0998745 --- /dev/null +++ b/index.js @@ -0,0 +1,237 @@ +const express = require('express'); +const expressWs = require('express-ws'); +const bodyParser = require('body-parser'); +const dotenv = require('dotenv').config(); +const { v4: uuidv4 } = require('uuid'); + +// Express Initialization + WS piggyback +const app = express(); +expressWs(app); + +// Middlewares +app.use(express.static('public')); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(bodyParser.json()); +app.set('view engine', 'ejs'); +app.set('views', __dirname + '/views'); + +// Server startup +const server = app.listen(process.env.SERVER_PORT, () => { + console.log(`Server on port ${process.env.SERVER_PORT}`); +}); + +// Client mapping +const clients = new Map(); +const rooms = new Map(); +const room_hosts = new Map(); +const room_links = new Map(); + +// Websocket handlers +app.ws('/ws', (ws, req) => { + // Generates an unique ID + const id = uuidv4(); + const clientData = { id: id, name: 'Guest', client: ws }; + clients.set(id, clientData); + let clientRoom; + + // Sets the ID for a new connection + const response = { command: 'set_id', id: id }; + const responseJson = JSON.stringify(response); + ws.send(responseJson); + + ws.on('message', (message) => { + const msg = JSON.parse(message); + + // Null command handler + if (msg.command == null) { + const response = { error: 'Bad command.' }; + const responseJson = JSON.stringify(response); + ws.send(responseJson); + } + + if (msg.command == 'sync') { + syncClients(msg.room_id, msg.time); + } + + // Sets the client into a room + if (msg.command == 'set_room') { + clientRoom = msg.room_id; + if (rooms.get(msg.room_id) != null) { + rooms.get(msg.room_id).push(clients.get(msg.id)); + } else { + rooms.set(msg.room_id, [clients.get(msg.id)]); + } + + if (room_hosts.get(msg.room_id) == null) { + room_hosts.set(msg.room_id, id); + } + refreshAllClients(rooms, clientRoom); + } + + if (msg.command == 'set_link') { + room_links[clientRoom] = msg.link; + console.log(room_links); + console.log(room_links[clientRoom]); + refreshAllClients(rooms, clientRoom); + } + + if (msg.command == 'pause') { + console.log('PAUSED'); + broadcastCommand(msg.room_id, 'pause'); + } + + if (msg.command == 'play') { + console.log('PLAYED'); + broadcastCommand(msg.room_id, 'play'); + } + + // Websocket command to switch hosts + if (msg.command == 'make_host') { + if (room_hosts.get(msg.room_id) != msg.id) { + room_hosts.set(msg.room_id, msg.id); + refreshAllClients(rooms, clientRoom); + } + } + + if (msg.command == 'sync_with_host') { + if (clients.get(room_hosts.get(msg.room_id)) != null) { + const response = { command: 'sync_with_me' }; + const responseJson = JSON.stringify(response); + clients.get(room_hosts.get(msg.room_id)).client.send(responseJson); + } + } + + // Websocket command to change a name + if (msg.command == 'change_name') { + clients.get(id).name = msg.name; + refreshAllClients(rooms, clientRoom); + } + + // Websocket command to send a global message + if (msg.command == 'global') { + broadcastRoom(msg.room_id, msg.message, msg.name); + } + + // Websocket command to send a text to a specific client + if (msg.command == 'text_id') { + const id = msg.id; + const response = { + command: 'message', + message: msg.name + ': ' + msg.message, + }; + const responseJson = JSON.stringify(response); + clients.get(id).client.send(responseJson); + } + }); + + // On close, deletes the client data and randomizes a new host, if it exists + ws.on('close', (data) => { + console.log('CLIENT LEFT'); + clients.delete(id); + if (rooms.has(clientRoom)) { + const clients = rooms.get(clientRoom); + const updatedClients = clients.filter((client) => client.id !== id); + if (updatedClients.length == 0) { + rooms.delete(clientRoom); + randomizeHost(clientRoom); + return; + } + rooms.set(clientRoom, updatedClients); + } + + randomizeHost(clientRoom); + refreshAllClients(rooms, clientRoom); + }); +}); + +// Chooses a random host on call +function randomizeHost(room_id) { + if (rooms.has(room_id)) { + const newHost = + rooms.get(room_id)[Math.floor(Math.random() * rooms.get(room_id).length)]; + room_hosts.set(room_id, newHost.id); + } else { + room_hosts.delete(room_id); + } +} + +function refreshAllClients(rooms, room_id) { + const response = { command: 'refresh' }; + const responseJson = JSON.stringify(response); + for (const client of rooms.get(room_id)) { + client.client.send(responseJson); + } +} + +function syncClients(room_id, time) { + const response = { command: 'sync', time: time }; + const responseJson = JSON.stringify(response); + for (const client of rooms.get(room_id)) { + client.client.send(responseJson); + } +} + +function broadcastCommand(room_id, command) { + const response = { command: command }; + const responseJson = JSON.stringify(response); + for (const client of rooms.get(room_id)) { + client.client.send(responseJson); + } +} + +function broadcastLink(room_id, link) { + const response = { command: 'set_link', link: link }; + const responseJson = JSON.stringify(response); + for (const client of rooms.get(room_id)) { + client.client.send(responseJson); + } +} + +function broadcastRoom(room_id, message, name) { + const response = { command: 'global', message: name + ': ' + message }; + const responseJson = JSON.stringify(response); + for (const client of rooms.get(room_id)) { + client.client.send(responseJson); + } +} + +// Collects information about all clients +function getClientsJson(room_id) { + const clts = []; + for (const client of rooms.get(room_id)) { + const js = { id: client.id, name: client.name }; + clts.push(js); + } + return JSON.stringify(clts); +} + +// Collects and sends back updated data +app.post('/api/getRefreshData', (req, res) => { + const data = req.body; + const client = clients.get(data.id); + const isHost = client.id == room_hosts.get(data.room_id) ? true : false; + const toSend = { + host: isHost, + name: client.name, + client_data: getClientsJson(data.room_id), + link: room_links[data.room_id], + }; + console.log(toSend); + res.json(toSend).status(200); +}); + +app.get('/', (req, res) => { + res.sendFile(__dirname + '/public/join.html'); +}); + +app.get('/img', (req, res) => { + res.sendFile(__dirname + '/public/img.png'); +}); + +app.get('/api/file/:filename', (req, res) => { + res.sendFile(__dirname + '/movies/' + req.params.filename); +}); + +app.get('/a', (req, res) => { + res.sendFile(__dirname + '/public/clt.html'); +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4d49466 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1268 @@ +{ + "name": "nodejs-login-system", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nodejs-login-system", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.2", + "dotenv": "^16.3.1", + "ejs": "^3.1.9", + "express": "^4.18.2", + "express-ws": "^5.0.2", + "jsonwebtoken": "^9.0.0", + "nodemon": "^2.0.22", + "uuid": "^9.0.0", + "ws": "^8.13.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-ws": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz", + "integrity": "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==", + "dependencies": { + "ws": "^7.4.6" + }, + "engines": { + "node": ">=4.5.0" + }, + "peerDependencies": { + "express": "^4.0.0 || ^5.0.0-alpha.1" + } + }, + "node_modules/express-ws/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5077072 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "nodejs-login-system", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "nodemon index.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.2", + "dotenv": "^16.3.1", + "ejs": "^3.1.9", + "express": "^4.18.2", + "express-ws": "^5.0.2", + "jsonwebtoken": "^9.0.0", + "nodemon": "^2.0.22", + "uuid": "^9.0.0", + "ws": "^8.13.0" + } +} diff --git a/public/client.html b/public/client.html new file mode 100644 index 0000000..233f303 --- /dev/null +++ b/public/client.html @@ -0,0 +1,166 @@ + + + + + + Room ID Form + + + + +
+
+

Room ID Form

+ + +

+ +
+ +
+ + + + diff --git a/public/client.js b/public/client.js new file mode 100644 index 0000000..2a026d6 --- /dev/null +++ b/public/client.js @@ -0,0 +1,200 @@ +class Client { + #ClientSocket; + #ClientData; + + constructor(room_id) { + this.#ClientData = { name: 'Guest', id: 0, room: room_id }; + this.#ClientSocket = new WebSocket('ws://93.116.13.156:3000/ws'); + + this.host_field = document.getElementById('host_field'); + this.name_field = document.getElementById('name_field'); + this.clients_field = document.getElementById('clients_field'); + this.name_input = document.getElementById('name_input'); + this.global_field = document.getElementById('global_field'); + this.global_input = document.getElementById('global_input'); + this.room_field = document.getElementById('room_field'); + this.room_field.textContent += room_id; + this.video_field = document.getElementById('video_field'); + this.link_input = document.getElementById('link_input'); + } + + connect() { + let isManuallySeeked = true; + let isManuallyPlayed = true; + let isManuallyPaused = true; + + this.video_field.addEventListener('play', () => { + if (isManuallyPlayed) { + const js = { + command: 'play', + room_id: this.#ClientData.room, + }; + this.sendCommand(js); + } else isManuallyPlayed = true; + }); + + video_field.addEventListener('pause', () => { + if (isManuallyPaused) { + const js = { + command: 'pause', + room_id: this.#ClientData.room, + }; + this.sendCommand(js); + } else isManuallyPaused = true; + }); + + video_field.addEventListener('seeked', () => { + if (isManuallySeeked) this.syncForVid(); + else isManuallySeeked = true; + }); + + this.#ClientSocket.addEventListener('open', () => { + console.log('Connected'); + }); + + this.#ClientSocket.addEventListener('message', (event) => { + try { + const msg = JSON.parse(event.data); + + if (msg.command == 'set_id') { + this.#ClientData.id = msg.id; + this.refreshData(); + const json = { + command: 'set_room', + room_id: this.#ClientData.room, + id: this.#ClientData.id, + }; + this.sendCommand(json); + } + + if (msg.command == 'set_link') { + this.video_field.src = msg.link; + this.video_field.play(); + } + + if (msg.command == 'sync') { + this.isManuallySeeked = false; + this.video_field.currentTime = msg.time; + // refresh_data(CLIENT.id, CLIENT.room); + } + + if (msg.command == 'refresh') { + this.refreshData(); + } + + if (msg.command == 'play') { + this.isManuallyPlayed = false; + this.video_field.play(); + } + + if (msg.command == 'pause') { + this.isManuallyPaused = false; + this.video_field.pause(); + } + + if (msg.command == 'message') { + this.message_field.innerHTML += msg.message + '
'; + } + + if (msg.command == 'global') { + this.global_field.innerHTML += msg.message + '
'; + } + + if (msg.command == 'sync_with_me') { + this.syncVideo(); + } + } catch (error) { + console.error('Error parsing JSON:', error); + } + }); + } + + getSocket() { + return this.#ClientSocket; + } + + getClientData() { + return this.#ClientData; + } + + sendCommand(json) { + this.#ClientSocket.send(JSON.stringify(json)); + } + + syncForVid() { + const js = { + command: 'sync_with_host', + room_id: this.#ClientData.room, + id: this.#ClientData.id, + }; + this.sendCommand(js); + } + + changeName() { + const js = { + command: 'change_name', + id: this.#ClientData.id, + room_id: this.#ClientData.room, + name: name_input.value, + }; + this.sendCommand(js); + } + + sendGlobal() { + const js = { + command: 'global', + message: global_input.value, + room_id: this.#ClientData.room, + name: this.#ClientData.name, + }; + this.sendCommand(js); + } + + makeHost() { + const js = { + command: 'make_host', + id: this.#ClientData.id, + room_id: this.#ClientData.room, + }; + this.sendCommand(js); + } + + setLink() { + const js = { + command: 'set_link', + link: link_input.value, + room_id: this.#ClientData.room, + }; + this.sendCommand(js); + } + + syncVideo() { + const js = { + command: 'sync', + time: video_field.currentTime, + room_id: this.#ClientData.room, + }; + this.sendCommand(js); + } + + refreshData() { + axios + .post('/api/getRefreshData', { + id: this.#ClientData.id, + room_id: this.#ClientData.room, + }) + .then((response) => { + const data = response.data; + this.host_field.textContent = data.host; + this.#ClientData.name = data.name; + this.name_field.textContent = `Your name: ${data.name}`; + this.clients_field.innerHTML = ''; + let clients = JSON.parse(data.client_data); + for (const client of clients) + this.clients_field.innerHTML += `
${client.name}
`; + if (data.link != undefined) this.video_field.src = data.link; + this.video_field.play(); + this.syncForVid(); + }); + } +} diff --git a/public/img.png b/public/img.png new file mode 100644 index 0000000000000000000000000000000000000000..437fdb3de0aaf252ca570df6cd28c6b39353550d GIT binary patch literal 69562 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 =%Z9t+f0ELa+4va{1ZcGZ+gC6p8^I>gr9zS+ z!zjb}BmfRlQ8zyUUjn3M$6Izl=0*sqB-B*=x}HJ~fEzk-qCcUB5Jw0sMz(^GIk9wF zo6xT&;)Vi8Y)=v^!FYZBC z<%!9H=#jAfEUU$?)i_-9>_`J(4DVZ_&CVP7G=&eW zTp$lGK2B$*7kk;OpiCs2uo+m}oS0>E8W(& z4OW+P19xob@}-FP3TZ0nH_@tf6L~=Ho%Kq#}faTkgvZ%s2UlnuM+Ua;(rH zlcR_BD^u~_{PyYDji0~>!ZE-m9m$T+jS!3(t!;cg_HvJtL)?`;i798j%BSJ;xXlHz`!({ zEo}R_qFKcj!8(P6vd~nVn@&AvMNla9+xgK@(WRL7Wf6!PDz^+y^TL zC-$Bd^GDMeQlDS7cMd0^`h_@7hV%{X*`uML8CDs|F(+l|t#(dgL73ge1mb&|v)CNl zqB4y(P<(L{otoeaS=|o~+QvVX(VC(pJk57-Kl8yj9JD63UWNjzrhV%`w7w4%yeKKn zWd|^EFI?kVc&tk#Oo&6AKQxJPb`{uxry?1PiNC|M8Z98alQ7`|S~-cGIMHJVJaJ8| zA(!RaOn(61IBKMQLP+!A%g?NEw5~WhdVDZ>1(o8aQRX1@6s|62be`##ozT;Qia`4O^`@U(bi^9+;TTG8R*mk(`d4d;1vH44sx@CkBSX>G(7k4J2 z9i$NV*^2KNPCJ`BoUsJ1ab&GfX#@osTI0z#bmha)j^dF6l~LSuh=A^j-RGe%1xs#> z3Rz{Y+|zHG%9gg!KXOKp4c9Tr5p-$W24elc&R83gF>XNCpO1RU+^gm03wMeNEcsPz z2 zT;g+%>NBguaGTDlX4*J8Ld31%ezn1M7wMP*8Uu^g9OH>gR3UDt2Fj++MC#9Zx;ZWk ziBUyIgt(W3XT=`4T)FI*%H}!8Kg8_L(GG$H!ujXZd;@HcaHG=oX{I;!J0UT~{!D{v z{AL;w**+8@Em;g%tMuH7uyu6-NB?}a5#jj`l}Mz!x#T~aseM%IexE_>vhq+I$1LQN zu2k>_nc`V!{o}Y4GTYDo>SNp`-U0NTkn#ILp*J^Lxu%5|%0-n3n9mQ><|t8rVT zcHeQ6>vuJzyuzeUqpSY8f!=E0m67>}I&We0@QqKcx-p9Gh5q?*a~$oFYgl6YH>W+<})FUEp&3I&S zo5I7xa`O?t}THhDDE`b zGtj6{4mx75#v%4{V{;KcrvxMg)LNOa*ztQmREzIMHTOU2eKd{8g&JU5RoDHAtiunm z-gFLE$VGj*N4eWEWU6HZd^1ShB3&K5UtIfB$=V8F>RD!HZf5&&k#PD`agfmBhmSLj zSHm1JpsQ=~2L9UCyMe7@e>d8xdWO`FD4FHFh&%pf_j`4B)5L(gIRt-oh-c&Zpso*i z<9Pg7Fg00+mg4xZQMN3ACBwBp-cj-p!uOTZ=asTD4JM=4x_z3*f->^%VK2YdYiNZf zv*_q6tNZDV&qJJcxo!KVb{*w?f7{gHNQI6r)Dfo=1lI?9ANO zr9S*EmHc3tyxCjzN9Tl*TK$4D7CZm1hR}=npA2I4POZshIfe;T{6PdN0coBNeT5}$ z%$qQa*yDs=9<^8KqR(BM{e2JTz!4KO+O@LG10_M4eXI}5#J!xEe4%~uG(i42)xD3~ z-9=5-`I-C0*T?woeD=28!q~#_(%(r3LT}%XkoawPHdRjH7IA&dAUeKK{Nhz4NPmH% zoixL{mQQN2^Z<*Ku2Ef@@O7DA*E%YJSAaz%(i6w3S)Id27o z+8l!=G*6xFKe=VV`RWJzd~K~*N+_|aZFlgqIFaX&y9LeKclwar> z#9{F17{R&DXUXy(X2vx_`ssZiyhxCvfxo}@$b6CnS!0}34L4fq%``Q-G$F80`_awd zgDYvEbSiD?FkB{P5zqx3^6;Ik9B#kUKRuP&+%`@|9}_{6S6Y6K zvQ9QgK0MK;>nW2}dtQ+!j)DGpp-6}tI-cJxit7iHW#nH9az)=Xm_0eC(I4yK8q0WZ zAz;uUAbSH5lG>6J1E-3C$kGTIR}?fSrwxW?m|BA-37TSNHtp{>Au*E4ib)BV&XGUq=4BO zk;R+Q_b$mDs%gk+6g3MpGIzHTRCAo+6?0e?FC`9)OyC;u!TbGyJt;_{?3>I&EUG(S zwiWmg6OJ>o0R({ohw=CpakKM9PIouMjE7UynGlu6dovHU@BY~5#xJ_i7ZnQTDv^0h zTK-ZGCyoHtQ(><5_;;Z0o`5gz9$atOdXRH-mq=uUr)f*SYYA;M(UqQafkPAN@UDj_ z4kNO!MlLm@VN(Q7e-y!4+xDcWti4K)t8Qg?%rXAtXRZZ+qrf#!I1Ng$>WL$L3ijz& zqMVQg`>TAErNZ32QT9|d{prL{&ROo9czT};$#vi6cD{R~@-90iA>sAbG=GUK1)Sq2)(sq>=P%TXY$us>Ph zHeX)>Sh-kTJ8d@}@iv`VG|}$C5FN04`P&7tB?%VFBJgI(oIQa{QOo|%@VU!i5OceP zn3i2Zm8xeUu7U-z#pZ6JOcyEZa3{SC8;@~f@5aR+q(On1wvK7mnzd$}b!LU_ZH5)d zA1Thj0n}GQ90Le|M!R?c#kZe^uRz0(1UAwdYI@8WOh+0Kr~3*3AW?uAVqDWh4n{zo zeia{M4#NN~Cgb#}u08QytvO7D5*9`4nNTS^;DFv!do5eX7;^HfHeEy;*3BTblq&Ke z)BE8=iL`xsd!GZ$Lt+1r_pe?!6{hnno33fjLs=D*crkCn@}dIKJ4~0u(Vt5sXnV48nOBrl#s6v1 z;l`yUxow^Di|BY2G{;3R9}WPU|7ac9=&|RwW*8K%bxyL*hInC@f{o&;@lB>77Y;m0 z*}&tkp$(e5=B7>LJ);;zE_vG3{dK+<-#ST_F+_;1fuU&q-t5>9ai_el--G!TNtkgF z7Hf`+w#R$_DR(bb*mF@vcC;7A>}MZ_e6=jyheb2aVPdbKcfl%`zrY1!f5wS{^Sx*1 z9mA#k9x~;M5V|O)2Z}dfs_#jLMSEPWgq{yeug6byH5V;t^Geou7fxEW!zwX9yMAG3 zO|D+`;97vt847Fg$@6PjcpUl6=8Ea0Ge?+hZC)#oc_Tc+CeGc4G%*o%?LA`AMTr8+W<&oj8Ht#>HH~Cc??wGWfH73&1hd?B z63f>RC8IyE?<0E|CZSb?9d#@II-$u)Xa!CCOuGR6z3%jIB{xYq4U`U)sz#FzKHfmN zN^(C&5dr?&Jh#S)n}@A+9e|{PyCX^RK_8=PW~jzC;sNNXpUmk~5~ux3w}a~~iO858 z*x2Tx4sL3b4{=vp(*ad+(;9;*?*Pr`(wQvhx)-}hGaUb6j zww;lp1#Y_8Ifr$e1g9gk80f)7Ofo7(c@Oxb2Ws7DIrOiRvtc;t(d2gRoS1?zll}IW zj_#}!ZQq4T818zK%YJeq#kIn5CU1CKW0uofqjxNMm;|TZA+twS2HY*$^j~SfDON4J zZ@g31+9{c+VDPu{9HtBDkB}=8vUNH>3HICO04!HoIpbTHf4RuYcD|T7?CHxU(JDY9hq_CH!^*p zZxY*RSxop*J@U25rTEt}Po4}r-?pJU$ndO!<6r8PC|MJzd5GU+W_fQWnvyk}NcvR7 zYFl9?ERnBXANDl)0B`_GMh0W8ox@ta=L|}h%3q;j(_11Rpumni-fw)9->s`A#59Y6 zqk<})8iufm90dzzJt++_cF7aTJQ4k%i*67~cwT8OOU27m}Ck z+*fc(uv0QrSeB~2Y`Sd@Pabkz(a~g$bp@7WO~>K2&5&z%9l=(MdXOx(*-xG1rztKL zM-wiPgi>q6XAngmoSO`c96v=1+Es*0n@-b0(4yfFC<_l=EU9IVT=9~*Qfa*4&f9bk z4#JISI?v4v#7RjIsjX4Nr~3@osKTkg10NG4{%H66yum#pUWSbV!gFt8cRmlr(t|h z=tzx#q6JkE>AjCFJV&(A@m+Dt?eZN}$D0g3c)CSo%U(e|z8{eS$3AuQV)M#BLEJov zA9(X#`P1?6d0y&2;(t?;)YUm1hKq~8j$-mgEHeQI z=}V$${TLB*UH0jYPRF-CTxz&wra=_i1?&NINgmZUd!8Aya0!3RKr*bTBdj)!DbnYu z$RyD^6q9@Fd&|`xSSp!erqOoE>tjsqqOj4XQJJKm+HNtUHmI?$wW z4Izq!Qul@4otq4*7aLRstDg)MDzMU>ZL-0;=Y_24q~R>MbWvg))qi&i=+N3|IDKwx z##P^`Cp#FNtyiHa^hEB{~`T=aT*jHTatQIV3JHEf`Es7c3HP z31-9js>09=QS0OPn=s~)I(d@Ht^GXo;JgPF?t^GAJH9ZijxAyQ67EhCuCFf9kn}WE z+!-iawiA8U%!2ROYxa{mZjzU|LK0te=6n(b)n-xDVrp4Ynn-#K%%Qk^a)|ffHCVui zbnjbjGlIIjJMW9(0kK(R=BQbBlzqdF^|LQ6C)w~mi}@EudZ(siN7go|6YGtkm1VDR zhUcUkmBCpliO<6$oy^u&tTY*TYxHm))vuchUKEts0125HBFA)#7Ps_tv zfLJ2uLg43VEYhTIOkSg8klr%(J*#7|Om!9^CdW@d$;A#4J6tfO{SKD+kuhRU+HEJw znkTzPZrJb!-1*+Nv-t<*z^l6K{j(TRU!g%&p8j2rr}{$XSB#fVQ_hZ{#E2JF@|2KE z8xu!2L%vI-fDiPT-4;b@NVCxR3*UK&Z1GSAv9@zu%&Hojyh`Bboz1P)$>6Hh)IKlwEtRTS~i z*sJ=Q{{EwHn*wuU;HgpTdWkB>xtK`Hx5AIGec;THZPc${+M=RgwF3@yPHCZ%%nOT5 zmtvN)3&q5WkjyCpe=tOo*Nopb(C1foRGz&eP4dFK)4o1a2RL#Qut7J0W7mnQBdr}i6Mts=UIx2a zJFPnLit^g}Gg63$yq zp)R?@m{d9?R{dqE4!8{&il3u;8*VH~6GSPL0D114==6zQO^MRyx{3ybg?vICeKX9! z@dLe+=n{1n-ps-dLAWgNFX=^>XU_NU1(`8<wpFU) zyDPuJvC^)UUSHYse8Y;+GJ|xI2Jg7xuB6d=q&mg=Wb)`TZSso}1oEQI>hic1sm9P~ zywGpsQ`J3%z4oiHWy@?`roBe{#oJ#VaS&og&k_MJ#rMNxu|9SjQTiI}VCh*>YQD@6 z*+y?lT##0cMQ=Jrxx^tL^%C=1@6{ud=@?TR(k6$+E$DwipnEYASvT#IA|&-~lT5rZ zkB;&aB3+Abuk&uBOhm(xIBNYaQDMH1OwYCc-W;)EqkY56<=zU8GsGRy>S|2kOk6CTdA#st=*fYAnw%#-=gGbajt``;8BqCT~2POB|YyW!yzg5ydn>IfsNxP-nKI z)-rIa*+GhFeb|++%7m&k-$0SH2C=utI!Ddl*i~og!FKleYKh)UfTGf;ssv8gE`GVOBHSr&Eu`}IxGbS>)xkpq z&+R-?46J9PY-0z{26q58jyCM@er-QL7J0A1VH$t0$?#uCr)HkCH#Mvko4vucE&p~~ zg1{M4L9a11@QQiv`r9nwuVYzt9jy?LJRYJQmnz}mxKEA5Y z(@o}4+WT;1iY#-y5Q%&n4cX$k81FinXENg&R+O*_-A2WPEPP6v3*9>xYeyB4-9nMa zt!9BaTF2lbc@MzMP1Eb0n1ZRl*Wb{$sHG zO6B2i`RictyW8C6euvpWi~LbN?@_H~Ax5P2##H1isTIQdrhBfi&1^SWzR*4o;(L&{ z+cXZ*jlpC(b6=Ymirg8Y#MgfU2|}MCxi`dI8ueDBl!XBjX(I^5p*?k$GkfZ-kATg9 zUid(S#g4pJJI;@W-Wv)gTlKC#)e~`Ktlnx`1bMr3&}Y4Y*tgjd>%UdOZsvZF37u^d%y)^69!_1@VqLxJ|zD$Ns?Iz*YL|*raGD!Izim zP)P|1AYe?K#H&&^J({;k9{`8pYQh5ZlnIHun|l56-ITmr*TGO^Ly0sZR=gf_)+s1@ zwm_wL%waaZFbm=$Vc77~lo)*yRAb^WuXVze z=7%+sZN}bYp}5V#YN($cb*Op*hlJhck z5Qz#Oe;z(li5s~P%H$2kKKeU%DAQ&xhEBPa{JknLqWPPv=29`L#fvMp=<>*drtNzE zzRGub!X}yva;~04G%*BBjv%u)jmpH$cl0ynJAQ$=wmp+{$c2Wu0?WOb$dNw{#eVwd z;ph+NVj0&~P%)I_l(5)Cj*-2884Ui^Yd1|n1!@s0P%m`gHr%P4usrTX{M)OD8EV~( zMS>m^+iGQyg_RP0Uzv!WB?8yswhSZJ`~niV=dE7xq6{4J*>1nmWWROE&o(Hao<7)MyN*TLh+avCu}j-@6a9!l_*bC7=hD0GWPNkO`qt$!55L{v{7bvb zG6JhbDRHrSS82_mBa`M>#!9*2;4=7A2$~>uP&(w&PZ*$*ZOYcy*XvR~<}wFjYYu!g z82rJX2ZG;&I7Or0Zo+GJMirevLN_xIY(cKOQwAob9VRJ+4V*t<-uG8aHAzXgAL1og zknWs^m&9h&YiUuOHo_IX3vos}KqQ`_9(rzoY(}%T#68Iq1{)17q_{cO<_i888<6C3 z|8z@Kev>LG#}Ove47v*knyl;x4OVG#d~R`})myW;NmbJIwpCBySahbvICtkw!`zLt za>{^Zq9bH!(u#j5L@dX2RDz>9k0)Jf3IJIuA9*p2Aa1e+PPs-dg16>r@2e2GJcY>u z*Q({@S;v&J^V-4PFDEdvN_ndZoA6dSb@<52lGZp>BxjKh;0|kh{~ww6$R%d?%}555 zF0O*`J2a9s|L^*OzxvNTk$)Y9Nqd96KGyZHEJ-J4*iB5BSe$+fiC?FXDVb);a<~w^MM|1xJ4PTv%dH8SoEFK&CW~M<(^${;?~7j+5s!-t}h@$19#=t zO5}<{{1}64$`tZxT{+q0xaP4MN_{EnLPkm*qePlvg{}X5B>difuk8-<)sb+;V5#M7 z)$?J6G(Db+?fQHu^qt@JF8-8qidDNu#71CEFgNTF=)}Rvyy|&vMk;ihCwrY0ZHv^T8yC=oN!Sd<* zcqs54h(%p{GO-ZY+fp}CVhsp0^{2#3x8CVXBrYr6oQc1(&1HOlr#DUUgSWR{OP1HT zstMfU!mKqs`)I#;;n`7hWOVzIflIZ3QDc;6cP+t^HP1uAWMw038<96T){V%LV(nTc z(~nzg1wrzxY@8QOQNkuGm8agH>o~3KzkFYn*zxyOuF(=o5VtIdTgKKno^tQGldM1f zr?h9!6=v~_*E*a1dJXE~=>_-a{j;xsFc|&CUq_duV>zgA;R1?r{P z;{1ZYr@pRM*H|UJa4)x<1;5_}Qse2HTG)4OJoF}nT)Z!cdU!!dXt9P^Kj-7w=HEB378_U$_?PVq>$qgr)Z%hVX z`)Yu_`)Z^0GxWzoU2SbC)~sAR(GE)w`tiz0^zEBdk)xGxoup~SWs=x-mo#{yo_%3T zgcdEH;;lo|^9$yub0JqEk+4=sSaHQifjX85?L;`y_;J7gyYxGEyR*u!O=H^Wfm1v8$`AtZ_krU~Jg#kIxy{=Ii6!>16l z*Rq-YMHoTZ)^d9?bo!M#>8j5VBLODe)(*wC4bPl;I2dw8qcKM|tM4;cY#lcGJbCWI z=HnP*yFTe(__;G-2t4ZT|8#%%j-ta{0)c=%9ErG7sWk6ew$V-5(EHJtrFS>1m#=Pf z8lH{JEDU!v)RjHoZ)oLLxmi^cxO8}`!8m{KHN#@hekn~#?%K^3Epg%Fzm&h_#;e4J z`>lRWRyJ9ngvgs}b))w$H&^o{DF-Ic*pzbf&g00GwgZ-(M<-~>DE^&C3i(1fOQL)! zZw=({t6CnHgjli$TPS1o&Zazj?k3%P&Zk}5uV-v64>Oipzt86@dr_cm9t2BVNC5lB z9|xnqIyVu27lI((tz>!Awug2*;d0k`ZBlxp(`o4Wc86_ZW_C8!pd)6RJs~8LDHGz| z>ad{OhGea65Hff!6tvlutI+*PCVe`ZZoW7XIeVziaLZ-1%+*;9YRU+Dc(B{S(q0Rj zI8<-GdCY4$b9pLpit^#Yn0eQ%Vnt4% zmeO1|7)p2En@gNI?vGu-bLDSp&~M#ak&3TTXw?$9P{41L79Q*}2cNuRjE?MlPN-C( zBQqCG^EiU1ekBvNLIYJ%mo#E7q#q)2vcjZ#;6jz;<=)4INEw~SlP|tX-1)MwiSk{^ zcYuJiHDLHn!WKA?VLWpsjV6Lvm%(EM+l6$Th9PJO8*|SjV_LQ|?S!rDLPx~E@ z=Hn;-JRJK4$lE)^p)}lcHe+b(drz3)S#Kb<{pw8et>aCOD-bpzw;J6@ufDY{y)?7M zno1^;j*& z-`ysCHW&_cMj-Z}w@V_q^&v-F0jnow-=N~j$tmfHBqW!^Q<^+;< z@2P|wJk2g}D@*M6+Mk_jb$!`cXB+m`cuEp7uvu*>izS;d8jUH5m2{~tgMvC&7PN_` z>u=2_PazhvudCKRh>yz>DzaK_X-hg4Ga5~3PeRuj4`VcIG#P=HIc>2(Y^uy7E}7kr z1F0kDCX(NLu#nt~jfkp!|CiZBT`rRsdz7>q@2;=#4r_Lr$Lk!{S$`n-sMh1&@WE=b zSfyAZ<$1gqJv1H5csF})R-YYMG@1rNnLV>fLvtV)?Dx3cx`bX7+liP%GL~d2X)>j# zPjr3eimk(DoTuVH5y`YX2}nox)*5yXjg0kocC@W2k>A+h%TCM(GG=osX^=K$?`$(5 zlkZ9M{X!yJ(;Lj}e!Q4DzSnCe(p$9Ua?>il%8jdb0(V-Oo293^S!`?vODuw2apa6| zP>!JG*b%-}El)i0p^KC<y?qd8y&VC&t=6cZ~*9T&lps3&9c- z0^<*UG@knDha<7?O-ItTFG_5MyuglSd=LHUBX|7lbaS0;5|)iA!~wk!FAlrIkxoYA z=AlSrg?XI?+hY`hKm`0;Y&t68aLHzy!x#$1+>aJB#}<>>+DgsMrL>Fo zpfO)bL*eZ9sidjXVs}tVfs*E`Qtnsi+`1Zf`q_LeYPBX~^o*>xysdQo68;(1A2x0u zjG2y}wb%*&qGI8kPG{U^OGk~y&23@EsN&>yVRn7fM1c6DHz59MM_pJaU;dfwY+%O9YONTwI+}PF~!YQtM?x zDGG_oOFy8JDU~QHWoye*xu|-rOy~-fm**Nu?JQKDT4!YqB%2jX>8#o1m)zU>S?k;X zg*Be~6snR>C8K4{9hzeMNP8Ys&CF0PJo($6#b5p7!-ao?KzUk>zfcEBY$GZ1o9W~aGI=gWO zpWy{8CoHu?`O^jB?}IC6(_kRc4w-$E-s8xOIzV}H4&obkkn`!&*V~+*?5wpsahg{a zEAUv2VZ_Gtyx!{k0t@vHh#lMH`wkUYqDQ}iepiWh860e-C@(ax@(q4u@R6(w`1-)+Tt|- z=&;ZBaC&Zjw9#8%4tUg_O>a}7Mk8fF+m*@4+aC=Czk_&7pWb74O`umffdC^#Q?iDW zyKl9;HmDvE%=t(;as=c28(nToKR&v+p0<{AEmZVspj5jZN$9&#pQ_n(CrjW!Ai1q) zA#ninmJe+kE2n+yyr$Z?|2msf{N=RKIT}v2^(>|iPejt4xU$%}xN7IA;#*(dnb;Gi z7}q+eQXYX&TjydtHC$uWN3^fJ8m;fDs+kP(nvqVpS#+w4`Je8G_01`Nw=B*}`Hat@ zCO^swJIWI_q1UQnb(4vkB2>a#>gfCxW66}-sg|=m(wJv5Te`nW*m6XTu2(OnKUFK4 zQr%_cDX*}CLMaMqqH}8JQ_ilZ8Sn8=Z0)ap#B9DnW_B-typ^*cDQa{P zc|$Vdv;W+?_^Utl2fqIzk~ac^hy-4s2Ba3)jik3<0}yHJBWLm zwHgg;Zf-b{+#A=NM}EAMl!poNWo|uzqPD3i4)8p^0fPGsX$9trO)G%BK(!wa1y4a8 z?g&I^>h-LfI)fqUHEVa9M$RCAT6eAW**cSUR|VN2;ye{jHAA@K%xA;F_g<^d{0Z$P zWy*4oa);?k_fy{_Wz`4iB;1$A!pD%)@`qy(%h?PUJbM0Ym;oN$Mj?Sdjrr4$ zc_9Wbh7=x63LebB=w-lbSW0HImS`&LKqC4Yh;}qjf`CF1*rd1X@>+n>R5%|`d2UTb zkHcF3EqIyqA@|nQdR1cAy07{@-lYa8hIZhYK8ekldYT`qM zy8-WswyAK^TZwTiuSZf@`)D}b0TQ<#{c#P?QnBkiT`{9ENgJarF0;S8#`Lt+Cg)Hz zz;hrDH+iZPPa0_u=LWL;yl1jjtgYPGOsgFYC)-G*C4vn|y@xy9l==c|4By@9*vVbB z)`$3Lx>}y8QtMHj1THqy0`hj0#bz5>S`E?StYZapys1s+&r_Bivce>+Z8CYIyl&KN zb^NNtO8LDOiBoT*wfxDS^NdX`k8Y*ZNt;lcpNk8ULM<63lBrZ(zLtm^5mQSXDv}FG zzI`j{=)MxScixp;+wR&t+s8rND(bVp5KCFH*gW%_9{=BeJ{7e~oesb=6pG`|7RN=b9ZYVy-BjvvG0%(4I zUMeLQ9Brl{Ma3?tue}Z{<6(>o!$!@|WL2YQ&u2F-!s0!KXK)_R+&Cp6MhtPU&taUv z_hGnEr{%_h#9^UKKIu{-&9Ir1ae*K-!xE2;oWve%m^9)2(ug^s1@nNDh<7P-L6QBJ zcbdH5gKIPD(1m=8Z(;N2#@RNoCQK&9&Dtw z^)ANuW6nB;je)LV2<5;t2!bp69q0mvGHdV8Mo+%i>G}&w76eW&c(d^ZC!4*qi_P6V z%~Ii-eDM+*5(72P$9;6LU8R#fiQ3*2g%P7TH_+K);!>P_bfxXDxOM zub2kYBFWne%0tOB6cu8X|`Gx+!)C(pT;iMZ`sM62}=(ae&fi= zGz|;bH!e?vDJivOtwpFx9I<#zW5GCd1bNatfv5@p)o_Yo3<1F$=)m0*&h8D4DO!16u^A)Fu_pv)6|2Y$Q0M=K@dL9@)JU|Hs1I2}0Qf!vGc)8*}*M886tt|7p~^ldi{w**C!&cBT4+(zQy=s7u`Et0`*!1o<~${b30t(yl`h+s)&R$;(KAbN2E?~&d;>wTB$Ii8CytNJW(sfdS#M|ZIK2Zvc&gDKB_ znx$MTzt!naDJlWHfTb8hiraXRn zqIS`b*%e^UwqaIx;2di>{t1$BU&Ln%E}fEauQh_;O5((WbsULc|Mm~PfgfQ<6pI7B zrlqy+zPaC1E79KOdsr~Tnsf&*)_z!-wsb%+-owTv_m8YuueS>gTe8}C?Z&y&Esk?Y z_Iwd87Dd0{vA83sgVGxD;s&xu_w^rdwBJ9~>^OI# z$#L$0&w3jR$XNq~Q_3AdL|U+M@dV{wx;-5`G93vYrx!xm1s13Xt<$g=vf}wVaCIX5 zCb^u_kXxzFSfo2J7I%I*8hQ`Jue}o1HxuSDFR(k@V1IDB#d)#bW|}L(U1v48bzgjy z)3>sv1pyLRj5c1Fh`o=5uY;|%nOS_i8E#>Pn!uB|qM8T-WJIjTb}WR>ASQBmrISBX z1<7(j3Z>YIAEQkhJSSK7)LHNB#zq%N+YB~MidxX&*{97F`k@6WxvD<`fwE6Ul1)7e zw*7FcK6VpUMOdcxW0$^z<^w$m4z&gIguH2id1PUCopk_hxr|u2AVfNIOEx;`mE^cI1yikHiA=Hz5GQ##K;#Y9 zWD7!6aw?NV&hS-Eu!R0r%FtTV^3EedrxH8Oc-LLnM7b9=A&>ZRL{&0nnc2ArRmrQY z?Y;lV8eaKSvil}Ca^xZK({^h*dYmk85G?suc+sqB5!uN4ZN$CiqiNH_xj0#24#6Vv zSDLIh;=Wtz9vIHF@UOF)g4l`ggVl=`#3dhavrJ-#uFoX7evcwE*afeDx)9&ay@+yU zlDj4rT=9MNww~8o9p}!rIzPoO=uO1kjF}7uT}U>_q<_EHb{FMexIGm;6oea*-kTTL zq@_GdoybM?)|uA$7g!iw!osLvT7mgkstHz!L+3}sZ(w)VruRaRrbCKf>U5ij--PuI zZo@-%vu>_Zl~_cSJjUn(!VPm7d$f?;e|akYURPbRFOkYjTTE+{4v-}Y7NN54Tf{{r zlQ$|83lk3rzzKLs9GeWM>Wa8e*{4tiDb5vEH$PNeZ@$*z`0{L<^K+252S|spZlyP6 zVN7Ih02YpsQ_apxM;jv7E{;XsJ2x7B7w@Bkm=|=}rB^qBTxLTCF}u%BHQTRX6X*i0 zh&K?o`xxV4L)-+(eG(SOT~8pKrPt!M><(VxLV9>H&J2iIYQ8-aJ+-seN;%0kWHF3) zf&|j2ca!+?md#D2=F5fW1if=06Og%#IWvk)A`7|ipzmJ?|DFiR<6vYu@y|qV=kOeB7JP{BsQUj|# z#nzL~#=^QgV-pIfDgu{{&DF4}tH;^=!;?~0*(Fc~KU5~iKT;~O%1aM`CLyI0ggcbP z+-g#8h3w@Cj40N&JmC5B@I@ZUTg4K$>^!y5Libh5ElJpfR>LscJ6i@>i;?7(3(}N0_~Q=T{4b%g`N|Q_G`%1 zclnhj`$dQ)jKUg+mw|`)q+sX`RwyL9bM}NvHPK zS$h!U`o;U(+<)GKSW|4I%v8b}qgdw_V0pd><8bcmR|3nk`a(-8{)@W zvHwKYq|GF7{KB`ug1Pt>Q-}lJZxa-APD$fOL#YmEE;w|6je>2Fj6P$d%}>N}E(s-W z!K11O97~4kS!ifC3-s^IvwG!7Tmght5~sRMn$Z^~{20kiomWFwtyqdRjn7%+vjdHNN^g)^z%h%+cH@nVlsk`qg8MI?Phc zZ8ikpPKNETbv>hcRA*DlpsvAAnj4Cg`?33b_IQ*12JyO0sf<21Eo+y5)msB3BDy4u zg7}+e{Py7dvKRkwL5X84bKsp0*N0fx9D=`m9bQ^ix5bd&S!)}H1pNKet@d-+DZfnd zHc-5qgGypW77|#nF7C#{@x2b$U$Oh#5>J6l>TLR=^58Poj5vTdUxhUh76IBN%n66U zJ;#6rYa3$aPC+H_L=-N7dV4X`pujF@X0O-U3roaB;5xikJf1$oaq~(c>nAC@-I$J_ z?XHhJqeTS8Yi(YQ#fEaufsU~>0szq&0o>59LzwG0#A&>G+<@>W;S^ZlI$@!L z^X1!X~`C=dx86R~}DR)%IIzf~;=uZCKuZ&l*qu8KNaUl}N;0 z>>zA*n8!~vJHCV(V|yT;`8F(3wR)Jgi@krfoCgVChTXJQ1aKcC^(44a4OfaVRJzTu zU}fOCkikMGsTU`gCrON91asFQR^=7QGC#y(coB=?vUdn!O$&oe+T zbeaq=ysI$b4!2k%u|RldZNVA-H&VFGbjQF7HZOH#@>#J&mg z+8sz{S6$ywhv9k#*Y0RLVsrOllLB$N=MdL?t*gfT4CHNMooO;kY|Zo2(T5IFFogAO zJLUjgt@~wHYK03`*JHd3n?d3ZV4lB^Q~i41XRDV-7Nwa;avF-v&!EOSfs`IzJvQ9v zJqu415>07+K~}#5JXb??5bGjhK9SZtw@B|_XF#^azwu8<$o*%@*+Tg>HuXSYX%Ol?7a^Hz zgyLPp`LXa>h%V@2+TPTLm3VV`0)Rg|Ua~t8n0%Y&_F6|wk~ShbQ*r$Axsc12<3 ziD1oMS8@R>z1*=`21}&_!XvLi)oT*gvM~JgAHh$*EVV4`>Squ~08td@XQ^b$I=*P= zguuYPGo3Y`z&bSGFdNG%x19EpYbJJ7AHCY*xPU~vEwB#m&?z=OH-*v02wuz{B@v02h^Fxdq1c;^00Y#*$Vx-arn8F;wE^^zMIg31Rgkn^x=hz~yo$SrIF z`3PYJIe|E?uR#TM3Kq|yN?Vmy8HYt%$Z7Ep$?`V1_MSqlZe1maJ;j=O%!cINTI18N zwc9>?zr*ndq~>_CS*~+VVgN6C~~~+^#1PcU#fms@3Kj%x@;-zN>o#`FW5cs9vsn9bC@zR?;<8N4yJb zFc%#o!6`f8HU^;; z?ov+tTcM&XSew)#?i>opeZcQ1T3e$>!(`PIjxvu||K>iE$s2ecxlCHI-juCw>e!|8lr*xlg z!X~JL!J0;#TQ6&U`#*uaeE{;ds>0Al4j?RO0@IP?g=D7A0)Ot-2dVg8>{9E#h}_6F zm2)rhW5-Tf6S=V=DfBIrvEea^<Qk;JS9n=HbTUUI8kL;QPRppb)-qwxG0v?ROi}kVtQ#}0 zwK>1IHyb@pYIv~3>AC|d?{3325~3};k!bpL#QXF?DHO)OjPvP2Y(L^oUPB(Hc0G1- z`8Ly3C=0^Cee5)15cb#G?!txjg}1)(7?7aJU@)=m!@8Gj>2-(yR z`V-yH=HojsC+j*M)z>N9=;5|(9{7Hj^>^>L+5Xh!HuY^5c~d(BsS6^}RQgV^!(JPT zC0vkKuNexZ8~DzmO$jqLM%$dGg_F(p+wdg040p*(P?)?od?Xw3R8p4r;nE3JCv1Xh8Et8#2^e54um76) zj(x&xzNyU{CWY_Z=rH^H7vtA|*j@9RNXq{&ut?vjM}TRywR5%lP?A@;Pd430ZX(LV zlFDRsQ#;&99BAhn*0&JiK<2PHt@}Yl7s)yIlkyWRmb>AqbQwF}_nywjp2D4E1mvKk zyoDsB;jF^1_xx( z2jAc3{OJ95(;u7c#y*eJv1!jBk0ZHG56><>c(cX&$zmewoga#ROIE7|dX$?E<9Hfk zJdY4BdjnRtFL&2j9${fPgA^rUJ%x@+?AzSw6xRyUR`URsED)g<)Lr*yyWG01b{#Fx zXsjX0dUMZ0;?U8?B;^6y2m)7$=2WuGqMqY2Do}y9b{Vx0mux5kRYBmg8H#^qTGyP-guAAysqHNR;_!> zNTGT!?itOyFJGXBQ1a&yA+QN`T=edp9}NwH$PI%)&SIezL+sV6FFMLW77mBw zDg4G`xM|`sR8Od5&K_@cTtUprA&3raM?z?QW8p9wC`VbpKhXt?+ZnivksGA}>XUCG zkBwLFO%s~lVC7^K0|ZsUPY~1c1VScNu|VJG2SZKpePKNECgL#qC>I`{`M&k!5-g() z>a(!s;t%5lVg{*JxO5+cdyq+Q%Pei~AjWj|l_tlXcRO5vY;h!ev58StOx$gj=J(c^ zA1t>YBAcmfG}XZ~;K)$G-i^BVZgFMiB3oYkX_Rjj zF;{jdsMhKR{L<}9?Z!$Hz5)yJ;xW>mNplzkz06oQ)FGrm*LQ3AwW^LQtAfB`>=}@> z+sP8J!X?Ap!jZSAQ9KyMyCK$%EN>L|MoN>*2ogVb3XP)`#+E#swb!bh#MNWjx-#c? z`TQALCPbnwTPe4YunB!;aR*t=&ijgB$y1QGP4mZJYnUSDC^;TVJbtys{uQioI}v+P zk(i6M>akhh)5xGWB`Ae8BBcPu%RJti1Wro9rEwlEde6ubhZjt}-o${g!lIH*rc(CV zNNPKhCbxj}>;Q2)+u^YcP{Qh+HP)wa&z*#2X%^xF(?}S-8gZaa4SE3AFH5zK0R)Ro zge+qqaTg)hvUg!3azO72QD1-fla$z-xU<3D`lZ zkxW%iwEEH=wDCZ)^u7MX&P(Irw=q_SkPM!Zs%u@PE4d)zabI!f`^x=zo4JD&TI)Mhb$hJZ=SeIr}zmjVvyi%g% zZdgL0m7KG5D;w)86V@X&5Y6kt_#!21T@I=sdC<`2wJrs2LLpT`;NT{ZiaJ5w93XOl z0Rx*SLF6831g|6VW~sq%q`DyS68Sv(rT$hCEI{H4@T}*SI}Z6Z1xA#Da*4&4spSKz58I9L!$Iy5XvAH9!Ogug|T74zo3Y~@xIgR!l2xX zNhu47wr3Cnc@wUbhv5FSH(GCSU3=g?dY32c!Nc;gYMC5@x{+zi0xy@do>2j z`WG}FXt%yxY}U9=x0if{>L(XV{fIfua&szr1ZstELCmEO&-`t&0$1|B<&+IowOT9= zJEkIOA9)Apbx=paD9a%5F?FKJei^x$&SBp7o88q#-sHD17Gzk=20C2Er{Ae@&LB7B zE%J;&F2z2?xh-t4^|a_NfcvBg!bJ5wNF4wI-bQ3d&x1B*kehD~@9NtJefH}k!PL%p zI?miQ6?DPLi6qU(Ysd<+3R8IQrE$6iDtI4JBIi>Roy^5hIqUMGPl4 zFRE%YMUVc1B5(~b>w?lUg$wA$Stv{Z7WjF1n^fxkrbqKvEkidj)>YGV+y({8dX|dV zSQccM7aftw8{*w8Al}ycrFb{_kWFt(zw?Ac)UOocB%iCEN8c%r&1yt#S$Ud!tXdv_ zU!|(02%FgIr&#U&3#{(IdC6KkyDnTe=wdARvJg@j#E$IsJN4GXNGg0#_k>g%)RuB? zBPahw@+e4mw_~B_#p2FTjf=ar+6IaEaHrcmxU0_6kG8as;K*9ntoM6*8p*-|tAPtY zhp>rw2sxzUaOE7^S8sWU-SVL(r+IQaq?eIg_h~Sm9o(-%dmRLB08-#Rc+Nu{HnfpYDMCt*$(rlE7(}EXrsN|F z4tA^^I`TL96>EX`2PNx9Oyv2UwU&Of*;ti}MYr3X!Mu=g!8@d_#ySV=dh{L-l_(FE z1`9T|TCfRv5@``?^>&|x6`f%NV(M6<C<%S2v zUTkRY0Z!zRvXu|ro@tN|7o~={HxoTR6G=Df^?cHtjdx>QtEH)+!eTs9q-SahbI1qXLCQlg|Im;Vi7 zC6wFEQoBUpa^x*<$+7fq%M&6|Uw2wdobrlQUx%A2Y@+Qm)YV|hGCR@))a|$hFTc>!XO*$MqN|n*5eW-C0epyoYoa9ZdR7AC z0L0$lhvn@G#YEbThN_N-n2kJYY4u`&h zb(LK&uL4-%8P*mNtSzSCVX|e_l{cNhu`HzLlc8D`nc4;moU#)nlbNMhHzIFld@PHV zs056ErZko~dTq%csg|%pZjH*Lv+O+je5LY~ukxNc&f1o9YqlhFa@q zSpB|>NYwq98SPaS7{1nIgXGK!EV_pg3-q|bW(r{;;nI5tajiOR=J(X4NI2<&3Red- z-o5zemLqV4A6yFjNQiy)a-H=p?0B{6Eyz(!9}$U5WBC;cC!!5af&67(&gkGgqlf*jQ7Cd+MTS)9aDaJ(!02Xm7$hQga zjV8p7?SY%!HoaY=>Dfk1@jPMxpTK(DUu!e?4`CCc#bKPA3`?yM9e3&|CLH-;y|BRT zpF}zYJR<{mMk;Bo)pNM3y``49uCn14D z{ykPH2v3!1Sm4%r2d=9VJ~tZv+9yN7@ANFhcGI}hqw*^0 zg@ryu@%FI5ZK<_3-v`w|;3)ph4fV-JmX1T21n`nL30dAKzne_n$Ze7*O9k8%bMa>! zVaxqlz!E2;pbm!uBu`tOd}@JBR&6qm+<81pBMYGlyHa=Uc?L_0*_*~#?Y_%Uo$Qwk z#x1pjNUcMB!E7f~4B>(|5S&gQdYK3uwLg^1c;LRY4P*nk4B4|HC%dXT4S80g5Hfj+ zq|sNgnAjFb#JXwX+^j?1(S;c+o=%&wcy6NP)%}ZxF4V2F(I(BcIi%5j_38U_8S8}y zv(bL+LXI~$%$v5O<~AD^_STvo9QRp}13Kfym}uDwRydlTWb0dLW|?K&2Debp%P zQ0zFQU1=J&dX8Kwi+0YTwA=FKX!u=9`s}ng$^C{>EL3v7E~*)LPHgk>ln-jaHO1mo z%z0#eLmX-tYO&9@BQ}+k8;iM4oKrjk$o*y^k%k_)*deynt(SY9ylTO-V8;G1+|fr# zB&rcAqP1324Cyfjw|mU}q?{W`rFC?pME(GzuozrS?u7dr@}rw51=5zxkBWNd<+g=u zt^wBFHLXifCN?d`Gj$K<;;lo72P6R`qW77fr ziny#QPpJk1XJnbUoh1WxESoYfkvCZ0DBjJ2-(;Cmk36!Zk}jT9DW7Rcm3;jQmbhis zumT(Al@>OkI6spk#GLIC_}%sS zNa!0-^BcxujnamwW3AGU%8KO^fx|+l7V)@vaq4#v8HPgbB1C#_kpd^IDOH)$M!yzs zd`V%bPr~xn4Hw-Vdb_{UW+k_MdKPofBW=@T zelWm=)OLR+R@)y)bVH!)2$edz=bxaaiks_=p~F?-RCKy zrHJ!0&qUL$BOz(;?ZK&p)8$NA%x3yZU0AD_J;x20C9r|>y5H7yl7dz!KQ{TOx335_Ube70Vgz6~2ac)~3U$I>e4OWwTkt z7O$SmtishPyLkA7MO1(vLZ{dMMhM|_z(gQ0YLU_RYm zP1tEGytIoeWf9vnNXnD4^$j91>+Pe>xLy|9fLtO(HhM{f2QFLhpGaG= zJA4-Lf{&V!SRFA%1KeV6Q@WdSz#-S73yUboH0yKFD-4!c61E9Jz~mm>jTZGOS(Kt8 zKkhO8+f_NZp|H0kA&ECLrW?4DG8kKWudvXL=S>JMiG@E<9fOq)MuTDl^&t@|$9*3a;?{$+okuu>w z%Ja@yo3do}Hxhxvrd=K0ojZw;!z;&IDK8epys<``VP+T7WE2z2MXt{fIO12ox;==b z13*GgpN~Yo(?8F4qu`9il1dtkvhhq+i{=TOf?XDPXRRR2P|!_oLr&rDpl=3#8z~O;_@}wCLhLxEiR6>fAMB>VhVWZ}A zmN&VB~IBCP(PB-Q;AjHhfB|Do=^&%r-hooukv`W+79JjGb$gd%}WnX^TBKqPVn1rB4nRZ|Yyp|Nj(BifH(W@2|#7oSQ6%LDE zFU2#E5)`>IR^uU)In)hO!%awjOLg6IXF7W7Osn%NB<(#nA5A^2x0@C=s_q!>iF&JH z>SVM1%b`ei`w-MgDT#Tt9^_5}N%*<9I-H*)M&=<%??!t7aEqYzp+qwcg40v`>TFN# zNIw2>F1GLLMD&QBF-1$82U#{6O0_}I!OJau6|8qPKf2BiLAd zQpZ_o;BArUaG8dYZegs}Vu(ye(+FYF=b(i*<~%bjC~ymnb+LNIc{L+R6xggz=<4D|{*CVqbPieK@J=$*JfWut z01qB5s~jdN-tIDv?}8P}gZoN3C+UCNWV)yh+DmDe*|U6xtkG~`ijqtO~= z*4jztYVDEC&Mp0dL=07o)cCL~Jx#(B;Y0xiGpWHYS1sHyrmHpQ z&|1w!a_Ttbp!?6ZIX_#7r+vwk|0jbGHPJKJeXTl_^1ZsK2JR-jd^Yy<)K>G4J+J2a|uaEDZ#SHcQu6_)@yM6n?r0-3wDMZOBqjVol8?Um*&}HHn#V}f#5fP z)8qfuU;2YT!$RVSAL^)OKvB{q2y)M2lP`i@zA?znUpvw4xP@Kt43VX3J7_l&3%hYx zD=$(EA&FH~TOG@(50MVIQ9eE0;`j`Tn)eXrkkuQ1aub^hrqAHl3{A*vy1#Yy1_&QX?;B z2JThj&$OlG=k%maIB&39`p(qxI{ZulHkV*M&|x&<$RHkWA}&%+h0QOT`$OXINl z7C2%tWQCK78}?3l_s3;jSilljim-`n@#0^vh00UDm%qxH_?8bQy@X8+mJCuQ%rRR- zKLlI0{O%^6k2KyOis z{`A!r$2rJHpMgk0hn{gJ>qVak4Ho8Ms3vfo3-iu?A_egDzV$jGHXuW+? z&h>b`8HmW~Ngt_mu;__Fayy6x{+4wKF9*+!xCU`P4#fLxN37H?xKBcQTfc*zZ^SG{ zx54!l!eV!@IkTuOo%*)jWg3DNrw5)hryy9RTODY*MHWTMod{2e-3NTOd$|9Yel2`C zOOp5fu~G&xpFU7;xre@chz+Z9Hdm_o6|Q^d%I`a~A+W2)(t||ym+)+C>2M_iX!9*_ z#FDZZlN<-f@LN8(cY02UMEPtbOIyytL_JS_k1Idiwad;cuzrvUhcbTD`^l$iyjb$i zQ@+ouA6FMOIeD%;7?WR`+;b|i`qmRP zvPM8u#&%;Wa`>N~F8l&Ne|L8#dI}`Y2Wv^itB+h^Q-`762MgCV$ghX1DIC;{RX~T! zg55~_74+$KECM!MwNuZ&=E|aemB>X5*2S?iEspbVv^g(ffx4)-6^<+>c-C!*wcGX4 zK=8ZRC}_eQpsQ#~2^i_VAfxdL5sV}(m{GWFZTStx60qEmQ}M2-!{)*|U40+zSipGPOMz-I6|=VQM?v@H*V)aXlwQ8jNJ6o(v}&o-QN~Odw`d zPf)Shr2BZ+vwoE-i=Igvd;#~@BPn~mXVfCdCL~e=PTO=>ef9~GhW_a4c;uDINYbl!+(rr2D(X}@ z9s_Qbu)s9`sW14wWSZIFX6b-?-FbXfiu7_(_v25(hDLlWl;|VNAEc!ZMN+Zd)gWlH zWPLNl4mDUG!b12JEO85)9Ry!8xGP^EZ&Kqw1}Njk5LDm${hglQ39nt zrUglup@y3BAaBtrN|+o;ZW@6jL@KhVRkk!MQnrr$zNLzSd!hB&e7qT(ORvHDR;RoB zB-A%xU7I)xH|~`b3Nc($5W-l1m9FogFY^eSTf6jB9Hy5aVnuDw7Git*7vsB-)cY>t zkcB0;%#lhH8@au=I8Ebkcewttx888uZpxOEV^3YgmRXanbs4=3AS@O*>b2ZE(O^Aa zV=-3L181YqsRjbaF(&Q)4^OP<)kLI=CsUgDm3ny|iBqA}kS==9EhBrH_fx_0@;+R8 zU*-v=6ncfK$-wtw{G}=N)T<(_)Rqd5l^q3^~CG6U!0Lybi%DYikLSCro+Ew;M z1ZtDph#9UiRT;#)p4N9ZHwI_?!3SQqWd;Opyu)SwE|P4Xq~xU2aJ{LNRPuW2tX@kC z2_l-4kyIU$Fu#Qj%oKL0QxHA*3XA-5UVuec3onaVSmAD;Zn0mP!$KeO(z?dF6kQSJ zM4F9Ac@pUYkhI%=4a$>GHaclH7IE2I6BQG?q>U4q#8H!Bd7C-XV88ix2LyQ_Zu4k9 zwu=;F^*U(bO=Al#x=vasY~pjEU!%BJ6~)!TI%EY=)lD2lFYLE+IiWwJ0=;e_;1k|nW9i-JwLQRGx6q z?(F;LV=3f_5^j{`j$29z0k4jExP_mC!t$3*_S8sYeT^W*s{pDfv9d$;=Eo-+E$3lv ze)^(pR#pLlTT&2(@?>U-2=N4odPPIxp%j3$;{aL^gC*MLLdxh$f z`%Jl3eueTxly|%2-mmI;24iZ8z}YLdnkjd(DEGSOyS3zFr}Pz1+O++$VtZQYoRz6lqyJ>zhdnT@1s;uVqrUT>@D zk)y@+NHEcKaa?*GZlGZ#tX@PM(=`M$SIm77R=CVUEHy$o*5FFC4`jC)%5&>&PTAL! zRsl#&x)kHT)bUm!GUOm|k zJ@U27S5y~XzB!Fu!M8jDm> zubYhow+aXx@f{F2$%G&JjR5dvuPW7orM1whWJzl|(-N^2ti`J3ED!NQgmH<(EpauT z0BX7_XJt~(m%lDh7x_HpD~7l?gEnW%{9=|soJ3=pO%7;fO2lQMB6j`-3 zPou>W78BdfjfUTb>!2Uj#7Qiu1`)ftEJkF_!iqeh&Svssv3B$Dbo4Gl+fDpT~>s$qVSxM9}6<`cAVkf;gl5NR{x#806Y#qp5nh(H454 zl!RxsoQ&x-OR;LOtR~^ciQNI&eS6)79vM;L!0tf9ZnZzKV5J9OqqC`EwTiQ4x#0#6` zxmEHwaM$J$EB?K%{9R0W+W4(p44tODyz^)of$s~oLvD`p9i>trE947uP!dbLkYG{; z8P~c_=JDAA{kz4jakLYU7y=^4139z&rrzU!|;!Ef!Xu{?dh(;Y;>{Zu7g zEAS#2JlW*<3UM!cut;j!jMzci#f3|!A8~J&jx^e?K*?+~t#2yPT2FVbc5U85#S4ou zNb3c%0>GWC3nadI3$0|-surv=6o0dbUy6``6o?#cMCc;fj^xFZ56g}it;R** z$PH5 zdhXSAOqWxb37Fyi7C6;xzwx8)n*U>mEqSk_q5g&ObR$fvfWU#gkouy*lu|5kOMRtU zsq%VGV~LZwlS%>#SJiZ+(SmNX)^!V-tTIyqAYJml&Ca1<$ zDE=*H$W;1BZvWN?L2;opVV6-?p@ecKu#LI~i$_v(f}Tlc?m)fm!9XCfgIt3i;|G85 z=~+nZL?Y!*h({RpTokOQeZ)M&$t+30cmJU;@QY55r5C%k($fXO0xSfqqwjRMK5TcHhd{#h+zBtWN*lWPqP8L>#vqB;fV}O3 zV&wM_+a*=Y#zGO`t%?_N4MrjNAHuFPc9_%p5I9r{i*E@FdKZXqJCq8aRPq@q0)s7o zN+=pL^#oImB&`pB#YW1Prq@BwIK{Uj*VQDf>yKI-=J7Skmg7ZnNvg(TSUA#PyAI)# zNm#2}f(iZVMQw!D+ea2S5Z4{pKwE%ovmPpd`c+b|PSCL&>Q8Jc%H$0~SRa0)%l*$g zk@iK$TfC4((MDyn!xV-B@wK1qs{Mx}jgIRG8z?8$LRI6l`2>!vPbB1FFehaKr@9>S zmbg3!IU>Ycv2rSrbTao$tDGQ@?C}Niq!1^qNeY!~3zo-KT6NFNeWaada_t}n11AQ3 zTwXSNw1pCB>Ct?`=1*jNa3fSmjACizt&u!_Tioi#V@}P2kck8<+)Eem52Z6A12foN z_G1Cjiv-FS5Z}=OYuu}d_c#ofp*FBQALOK);b!S3+3d|+Jd?yVNx^;C2HJh!rrjaRS!2%lqnW53x(X*}IYI zE^wuGZk8cSYJ9uvtq-8!_9000-bZus-Ea-u0QA>&3&My0DOeau{lm>F;518=->7z7 zcjR7k6gLV2=ON2F#CY!Ft06tgei_S{nVmHt7a_S5?sz&MJBUpr^3>4npjW9C3;sQI zw#N`Kc}A&A)+n6BwkTvSW`Q~+=Iyavb=C*S-PVQ_2aS4FjOKYfXJ#byZn`raJx&{D zD4UeG#jyecYWx=E@%z?x50SUuLXhUZPVw4$4!f%9LzVDi90$&}IZYQl|tld^J|pn?Z_g1LOKz3rXm41PSVS*VACF`P$X*gM-ufj zkwg<*ZyZY%QQEGx#Jz~ZCTJ7fj-*s7X^cjr6f@%Aw9eS18-o}Sk(*l#g%=x4(nPbx zG67EJe>9=Hh{s=6X-NasqHRl=#Lno6he4$9koE549|XD&T|$yCY`i^Xh_NQA_MXgtb8D;bMr z-7GV=$ITwT-efsH8%frTg|n2qZJqb6+~rI2Ny;3L$Ia1bnv#SUv|MBoF=mreQHP1? z8c$8ulf_uN_U=^V*S+)sqZZzacr_)A@B^fhYQ(rF#}m_3n9S};U)iTT|85wcVR5}HEnVg`zdeXliJ zFTC4g{$sZ@`_PBj^Yzp*7!FI3Xw(uXrcxVc>#1Vd*HUB1)wI=V^q+3BUVpFE z^1I`8(ia|nnE~6-601~6-)GqwAEyS~K2%k8^NWlQ|&nR}T(g#roh*_|Qv(bI`r=(Mzwsarr z{1kmwu?1?4lpNdZk!~HXH$4P#eJvT+cNe}8W)R|HjaF%LugCCkzbAW7O2*dOnXf4H zk!Zvei^Z)VCX_ox*M$W7R7xe2W)L__B!c{+ON-H*wU07=_)M9J*PF~=KAATifWU%# zE|zs{z;G)IQ<=aeQ@|^0iJ4Qz>FH?$j;uPb&>Vw;O@VlfIiz&hW0G|3+YHcyXNCRo zY;G#X7Qq>7M+f@xUa(ynzhwcw>hR{il* z&Hd@f(Y`s;PA9YU{;L=_rz?L>+Q;?yfQSoo=$6d$-N{ z$GvWL(~(UqlwMl?712o4fcKpx5l>jtFA#wv!i%w^O;iP zZddJ=UQ@5u=bKL8Fmq%KkkQYYTr;v7qkM1{v7Eq&GCREx!Y0&2#S)m!n50a?Y0Snv zkb_!rcXhoF?nYgYup+xZnXQ?QWg23%x5oFE>O!f$X$r>1@fK2L9Bd&MOR6g6z@vB@ zsKKRuK3&zyH>w-Uy3hRlyt>1it*@__->6t*(&CwZ$O;n0IsQ(Mxd&?u8(eBU)6q=p zP$=Cs6in{I-%Z1z^!C0$5;1eBHdyCe6f;MOk}G8(p-R%iVk(+$d$yQ5G!{-@L4G@O z@2S|aqqQ+`cX;~Q+pYGGdKS|=L0a1@EokDv8*ZoD(0|NpI^W_lk2HF{n;H9tEZc?* zq|LDfO#jpWkf6i}l0!f0$}aaC_e<7*%pUR@Zok=@{$e(stq&#>yDQxX<+c*_&7eJ4 zW#b1E3{T#aXDo~7Dr+{eh}UkMY;YLn3T$DPdwcoerPLr}k#x&bf9l|_TJw#$x%oM- zw_bNEP1%)P<-+ONIYXn*yXke6kmxm;&AJDI>D@Hv1>ruacYA4&!$p(bn@@JrPif^> zY|l!r2F>Bo6f@B{>ItNFZ}*t5;p4Ii96bk;A&aybm2-J74ZroBO`E?aJl{UMA#~hl zz58a1^%Gd%KHpPozK8DuUge#-p1aT-VlW_Phvt(Pfc45dR{#g`oAK@%)4-cZ74UYe z?W28lrduAfVG46pWe4?oIzxwRH=V%M)Yc_g!Z;zteM3^v1_1$%yzxo0sjV4JT(U6e5YT;$fGG>b*?J!#;JFBVDp-VTn zh>X=`pU(sv5?SPh$a#wLeX7*&1r;{IOPZO?=9JCph}P89RLm7`b9*`e?r_0TiJSa| z(YUfo9f%##dio(LUw=HA9@&@8-hm674e=ljC9&-xxLF<;2_$zv^T&5U&9W1*Y8Jhv zw$)ZFEqWLmiL#EVw58MG@l+h%uEx5-w=9WIZu{A5i^-4&q5+;t?IDw>0TT6&9c!}R zJkjd84)V6?cR72MXIO_mt4t9ybMq#n-EBhh=%%@FBH*za0%nt` zY?ruIwrkYt``A!+{`CI`jXjh1pfe{Pe{ zn|Lx84cYD4up|XHouHT74tZWuEJ(ZRYy(Jj^3~hz&X12a+OA>Vp0t@wx+Usv@Om@; zXfoz-8p1|XlT&1RdS?@z*|HFSjbA1AVofiE4Mj%n0>amy>;h?c(eOn1{v?uj!J~r3pvJ4|= zKS)ABdWBa~IrQ8;UWo6xH61&iH<4`EJ`^HrC9mt7KL011h zM3o-H0zJ7Im4=w7eKwYD?O#mposFfda9#&FQlg_IX75S6ry5<>1wG2wvy4C>Xq*qn8W78M@Wb)=4=;{~-*lP{;R9aV zLnz~3xi%5L+3vOs)Z2`6$eXA80=ZCIBC)t}WY*u%6G-kE4kepIi42MBymSW*M-mJg z4JKQ$DR=O2L;5yA7*aVSZ@mK&8{gh!jmK|+=WbSS|Ya6%Wkb}3w3RwYn1cy1U&HmNQT`k1`Av= z=*1b;w7@E9%+AL$ZP;Dh_tc-1R>&iNLA(pB^E~ED0Kyn9O%9efg)_cekHHgA=iLY{7jpRBq43ap3 zmt0SGt@ZIXkGc1w!O(X>diEo^uv0G;H(FR=1Hy%!@ut~Gsu2s{C+i`i#Q;i+$C*fK z;1#4>c)AeZJswKdlK_EU2jvd}L5Uu1wBI@GwOnbk8^_?*`@#lvYj7*->7!Ux2sVts z1?M7MD7yw1lXCKTy~dSZeW|`V)+!GR!*G++G=UxbVT`FAdS*zVkr_rJZ=_$?(>i8) zx65UGHa0bT+hSnhhKA}fC?U?wF&#~J-kD9D{B$_>-qVHH4#Ev{RR>(MyFug*pG3lH z%vX2u{0&3xk1QSfJ$MB=37bu3xS%#Xm`@&?iliGTrtoDv)Qtdm9MnIVj~yNf+P4Fn zVZ_&`G9xl2&_jH z%R^eu{J4>L(Y@s56#hfFSwPtEj?5Bfl>Vg-UInnC_XD>(yKAivcGOs&ZpXR+;w2%I zVPiI8HX4t$?pGZIj%sPJhMA>yf|;B_Sf%Qh+!pb9Zl2@FSv3orP^Ec`Q?4DVDLV?uUZo{V-s@h1)~#4~2zb5yP*PrC95 ztb&CMi-J*}%c|yDwZ+v!;>gfufw9q!bULuWnIRzsx%LnOX#EAYAgZRn)>DyaDr17X zYy{A;*Y?u8J5 zE|yLjd9>-^hg>>b&zdoQSJ{DC4|@66(&F(@gZde&z%OuM(4BF%QgQ&fm@ z&u#hvE1_X{F3|L7A$9oNcOp-8SLFsMKQ`Q*jvjnGA3yX8tluY^?3WMv zY;=;QXSgm~I;YaHw zauY{fTNT{SDDIqcVOdg|>Jb8JLNVm>nm|g4gt@J%q?u@B)#-21)uPPZxBM|u^#VmTD!0O6LYHn(NC2JUZq5jeUb1$g^xrbR5~A9yS&j7Q|Q zsGg%D3$JpUS7$TMVj+L)yF1)}91kU022;tFYR(O}QaiC@okE=G6s$~l;cm1TNhKY6 zt83Cm$6z4d`PZTB_g#`L^!0YzKL^5*M;@m`H?f6s`w_&z@o+wI^vj9Z*RIVZP9T*{ zZk4TW(o98C?k|QzuRVq(@y<;2RaoOL9`V_3ywc>jjE#k9Jd?V%1McO*Qy_2yh}# z#<_iUmPZ{9*)3MGSj=(6Av7OPQUq;yG$r)Rt15Ba$hzZU+^=lcL-u83vyqtWQEZZF^<>eVXC#z zRI{*27Hi$uf{z6Uj_Th5Ke?wboZS0hF>~zFc;xIzFxdt-N|(IQg?swV$>Vp?^#vZPzla8%+3 zGW0S8PfYmg<&+LD(^0fF1;i%_>+2|#%s#s_89E(C9;}H-+Ff)3RfH-mihjh>^kVVZ z3peAscv?=(tlL44J1pR=Kakk|r{Tg2gL89Dvo zaO4M9rxGV;W0__BNBv3O{UA{c);Mo4k$Dw!$hMo4mb0)39oP>N57pa8u#^mAOz1-7 zP&dmAT(cj{rw%V9GBtX-wd&TX8(a{LAv|w&{r>oF;Jy=?Q~RJETk7Lh5h6@;rxmYv z#9lxA!A{TriH)6mNP3+O27@&qawfaY7PZ<)F+DFxLTk|i8DS(Ak^$jJS`CIcNLvJB zDoUFy8w~e`+>R`kT^`HW*S9%7IPI0bz)dqwr!!)PDz^r!g5-_PArMha7UVXKn70__ zlPE}V_+=6%DW$Wjg22fYHsXP>!2)M?lXw7`sF#vJ=N9rxv$RInJmCB|*e@07VJWseQ0uC^#!n<@KM6F@48bP`8q>3B|jaFuPlcydmz*1j`$(l$FD7 zlop%q#*t2^X#h=RW*dUgTSzrg?MC#w zv3D`i`RQ=zn^4u7JZ6+`pb{04tB0#o+-EnjFM1H~wFDB1f)# zwN}Fd#4-l=)Z1k1;N0At5d_ZYa9C0fhfQ>&rekRt1hJqvi74&#NTg63^ZDE_Bw4MF znI6l}YN-e_K!MUyGs&!;Nm-3DjkqxN$i+;p;@-$NB#)%2q^r;~uC)MBA%#9Ggi<-z zu2Ob31=)+4Hs*i&I&-x2Wi#n{2pMk5Ze}TC0%}?|Sl{+vn~uLW5KL_^h+iSnT(FN; z!Jbl=UX$mxs2k++^8W??*%ZbdNuvWJNlOLMTsogWRq)8a6V!<{mS#oRqC=5*P` z=G%f>8Q{ic#rxm%GRKmvr+=&DTJ28krdJDYtnP)^^QdA?Ru)6ZbSp& z0+^YPrshCIuAUnUzXNfc7HqIAZHVf0P{*b4AH;J>H)j*a4W>{Ae_GydcYW-SrJmN> zOdBG`086P2n@MdDRyq3dQ1H8-4~5=Gx{-EB)fd%LmB=CP)r2_i?%`mf9dTLP5!ZVF zB<==O?kBE^;5cDU>$$7bfAz1nE`5}OqrQ_*-M z+z?@E-}IxTwvcKYEC&zwB8CUgr#Np_=* z!;Nw=(T(@Z9;m^N!Tq;XYiFhAP8zor8@pA~EtSBo64OkTz*T+Ks2Tz%Lu0fBn9VoH z>`f!GHA-ICbD-r3U#Oe63W?)=spQ4I7Hs}J?}9LYxL07SZW8khoW2 zh3kbC?kW-6>KisoH9|1B_xxn^0h<4@~+kN(X#%~ z5I_~AN?795csC+$idadZKCz(bF4$2W)s<_j=-~san`1PPY`YGN8`DnegYv!>08@fzsF}!^$OOeMH_?%_TQL_ot_9Mn~H9n zI8h)_Bmx+_i~DNL_okZJm*X+1@xoa6=vG^J%Q1cN^dz}aKAwy32Z?CZGerdtB~9%} zfNr=u9or8)EqwO-{Wc!PakBdSD6ft()u;}e4 zm(8{2(4qi%K~7q7qs$uMy4r%x!ZRSrxA4)XBw2q!AgzXG@C);5sLu;shw375Ci^0@ zH})}S%R{#C@FWK36LWn`lUgw!GYs(2&Aq z)!(9{|iLn_9F3vQv!^ zFsZjl(~!@tx;|S80w_D$5YWHv)1lB|NZFqz;@0brZ=XiKBDh{jrMUf2qv2M|?$5>! zU?<#+7`nQ*;8q1?yhn&zn=W?YqpfQSu1Ijv^j)8f9Q#v$;7507qKC1Fd+ugkPXB7I zp^;}o&^ZN9>rk91Vr>K}u>-vJUDr6nTVIzLnVcCp;yR`oLmxH%QB&qm8!fAX<-iAzu@c zjQh#LSxz0&nT!E~BOb((wSO`c+Jm^<{SYiUi+SeYXeil+?__Zjy$)&*scpidh-7iG z1F-BhLM?U=_KzHpH=o9R)^rU|W-=y_w?@pRdjF{LzHCzaa>oC)O+7lB-udE%(}r@p{EEN%DINPCKonw4o*jt zK3LqvC%y%aZssLG_3w4Y}AB$NAPzornjQv2~%lihBa~r$n!pI zcvg%&SEB73RVFF_!q48(vykZSh2T!B)BFtgE;%RMM%7o`r)UH!^H3Ij`Z3 z7eqP%|2*6%hnS;zm<3}s5HrCFy3n!O2FYqx9GM{~OrqFMUhDi4>ymfd0@o%&ZWic2 z07cFpGe_evb9USZi3?T(iNlN8@^B$>;EVC-w>}w-etkHUs#|J~mb~&XbL2X=d?>Py z)`DKeQm>deDhD}Wm>Hyv#7dByTPAa>Sl-mu*IA_5Znx=iyVE#Y?8w@z^N745;kxh2 zc;sye9lQ&%k`q1tcsB^0O^=zE7Cx|$vG8213rcUb*ooc=0{3uFo%J!|avn50%@a@N zVlh&bgnWJ+N{QquEN=tgKSnH=%vhM&Kq%c5BXJLlHn>inK<=hp*v)PsHzz&n$>VQC zA45eeT92Gyo769r*io)TnVSU9#@)8D!Izv51n2geE%(3P<^BLJ;_b2d_->NV-=sqw z?j;TT8jEq^pwD{yWV3w_o}Jxfg{u(X$-zQI4$6)!w2*FwMXnj-5h-Tk2OI6iiB^|s zWE*lGB45-X6dos_@E8IiOOfQd^2T6T)En;2#O&lIiI}vOp+I~Gh|qRe-?mZe5|p_O z)_CJak!hOx;a!nzw43HSJ(fP?S6tKj2A6XQuIC^o@x8FzwQb_K*`(oG+-+$vlWQrg zZw*AuDSu%&66tk1DCJtwMPAN$z z^%fNlF#%IJk#T|e`C#>^17Smud!m~bgCsp&iGywoGMR>S^n4>!H1Y4s+^7lQzw-s4VU&KrNT-Srt<^^U_5T!Y1UQ>6*eDzKHZsFjO>h)8lSn(BSE*?#`f zTm%jF9NFTDtQHF@yTJU+Uz^Lz#}P!W zwtO)pj?SSNH;Q-DB};;kI9IVt$8#g|z4fx<$X@=91k~7<&{s*Jh|D? z@6A{hQf{kyyD@yC*>M9Y5sthI#jqB3kp+%6qV&M>5yFG_o=wjEVR;NV7?$tJ^#aG~r4iF*PU${Lmk zdY)UecuvJzbyQ+N-z%hyxAG_kq2~#t3y=kwukqI^Zx~fzB==iAkFSf`#~guKRvt$v z`P1d|=w+s{7G;x^8?KctJbr_@w%up;2FjDN=I)=~qm9%iuTIB~|9&9+i%-X*-=HL^ z@=jjbMMFkmayjmaLS1s&U_4;T#mL63bZJXXj5GZlqYxJD#T7LHs>-)RyU*y zC?ejCuMu62+;9GUHO6~Bn_;tGJVkXscEcmI1O7^*X$_|c#V_DeG)M)e#Bsmk_+V)A>n#7{Y5Q9w*{ET zY6>E$^W8VvoL|Cf?Yl7@-CyZvMbjzkY71oVvrvPaI^N{C3L^TKNMGP5u!yyk8{=B; zfRR^q3L(ocV_nTFw>oQHN3SA>$-s^^+8>c+XusEX2XVV=szQTs8ZobVV6{C4(hp&d zjU~%#Hmu4{px&oVI^-So!i|6bevfo@c6N3KA{cANNGnaL&H+?qIE(7McnA~~jJx5@ zHkjc?iF5)rJ1@h9a3*Jk$&m#5Lt~B0x#p>hc6s%#R9)WYTRPR7$yQnTH-B?ue@4l=NO%|hVdB18syk+Z2R zb-4A+4XV-`Sp!H#PW>UbD;i_Pq%K&`{rPK=w~v9mO~b`=5LTBLEr_0fYV?9kk8&zq zFWt(ATkRNxc+Q_{aoj|rdcST3>w#hsWk8rGinz0Z_d8u5o^EkmZ*iKiNm0awFX<`t zYJi{-+f`>7gyroc~E4}N&^E#AGikvpz6!RUs3?<6{i@DnG0+(X_!q+tvv7nZa zl(pg7O#I-bso2|JPQ<=;VLD)mr7L#FifhtMwaS7xh}@ zGZH2t@OTFFXM}qB}aAW*4o^>xaOllBg3YPxlBD^M2^&~!`ms>mCj9hH{{fVyLMdRTkb=KPrb~&l{nwaZ} z?@Lrxv16uGNCcrS6|r@kUzG$-ZV!o>*qeG`eR{yclie&j*|E&EF1L197UlBL;r`CK zP^xnre;!SHE4fQ@-^rJ1T{2fHk8WRpz^HX9O4x+jZi>NOa*WjOM}Bl+D)#1RDD9JTf$?sOGWNsNRs+uh23K!pvpXHq zW4B52uN5CrbVqE^i4AtsBoyk-Ay#7#+^Raz|J6GuQ~(niO;`^xxRXvpA@k8Tk7dAM z*g84ns3pI_rX4l3-u5CzZ(Ty0VCR)U9(4otXyf)(ul5BqgagY{B+k5X! zNB4>Z)A>CJH%SJIs~^HI*S@#Y^Is4@cpsZxMTIVq027hpr}MD`*c@xu+kKJ<8}iWk zUum@8Iosy^%4}c=mVd6`sk|Ty4atHF>u5CQpd5Q5sj5mP$|9EpLgMc^t$81!qHUI2-51Ogfas&=u4 z9idD%5gcdk?blgo^eBsgz^R8Siov@-@{e(zXh!ZLg*0#$o19A>Z^hvV0)Ia~o{k4G zcQ2YciBxFEn1*o3oJS>j+WQi@kdn;SFv@(#zhdq0{r{PJ$4wB9M5RYAUNp9uSf=UR zWb71NCBOgSNbI|F$azB(^wKVyrXBJ}Dv9DTU4nTzk$ql-+?KpPQb5zKJOwReePvW! z!Llxp5Ii^pPjG@I*x(R?yW3#F-QC^Y-3NCVToc^g83^tK8yp_zt@Z9n?pv#W>|foz ztGmCdud1us>M^5T6TywuU}h?hht7gk+eTOAF+ltLc(;%)f@><5K?oHjD zd~Ul(>)bQfCc3i@F*@0-g_;vdjrAg^tbF!0cWTO;`Q$#mh~s#d$fZD%(Vn9UUd5KC znWR{J^0j2?K#Cl`zQ@ZX(IeCLaf-d3Ds=MXJ$3UdF+7NC;?W`#QPiLbv*JyUaOsFl zz7f(Et*yCMHMn|xYoKQWI{W`{IOjz-*3HGw~WHO=(B zhAl2YazgJ*OZ|Wiw{0#&Xn2Ka)2TtIz>R)eb29WShaz{ylS)vV#IKCX)*dVa#c*ik zALd>;Gkz1`frjMs{Tn^TM1VaWCu8ZP<`hmuOnZX@Qs9M2Hf|I@un(@d_%)YRoWqs-- z+ge=G#)Tk6=Uk&oL4O(ir>g&~Rxk||G;I21?)9Q;1H}*PlXnqpmdFgV52}$U;^}ff zKcDZ6YaY#9Glg=1J^?R_fEQG9{?rC}y$Lo}H;=UwIg4Hv+#Vn9I_H~E8hV}(`W6<2 z7_M(EvZ@3?^^{{>ww~gLy+fZ*$JQ5`lNQ9I2WSH6=t-S z?-{9G1kG-0vghgUz~M+J=Phxk+($~ops*VmK?EDWctl0sq_8G#nE;w};uITM5%llG z1Lb?~-hr|R(2IfDw@P9GVaFz>(8tdOhF;8nHiOqkp5$>t;y5i5FiOnfXb7Z-EIsXL zw~pJ>oKeYYDc_)RE%4yhtfpsqBs+-u82!$vN8DNL!y1w211XQBd6Mo84@k|HvzBml zMw~UbKa}Z~O!&Z#klBQ>`j#wtQdAtwb@_Kc`MEW&Cx>>c?)&02S}?>zp7*BqKlQeD z*qQLVRhWET;zPTM$pm7YIj33#n}<<67qKHqL$ecz6%u)^6B71-u4{q^GwnPsgccAIv8$Ti+C)W9$E_BWHitM2jr zZnGDqDVIDN$Ib~>y<21PPc3Y#?X4Olvz{4&9l{idym+RcLX}oIA^Xj6O{Hd@(0qx0 zt6p-Gf;MZVGX(H-8U-3OV-Wpj2Q~3hukUct*F+=@@!HHiYYazFGv?tSl86hxo;~M1 z!ur`Y4Y!2gz7db%0O~0GpaMS6%whY}>-%p$?yqG8;wG%q8R1bvlTu?@a%*kAc6v}I znoiA>(Jf%Ud`riEsnQ%tup+%IYIdin)^q00%;cNZYm4&qb|@q+HIYQ-T9f8IAwev1 zjtNvci4!&-{PDGN$B$B6mF|tx!K$Rb>QJ4O%>jz%Ys_j%5-xDDx}o6Y+i=TMIvq>v zK&+;vVd6fwi)jVZ$YI^`O;G2S0I=NhWNe;6#Pu=0+VZG-eCjrC>Z zk;PlmSP8)mtpAWx%9nhWUu5Llpa7XNhZRih>46lSL{?Wqq4c zV>r_F9J1FD>bl;1vvy?g^W@hzr@b(RljjN1hKJ}FGmm~{R&%kDVHCy%F7;7+Rh&5n zE5~XmvugI@2HcO+DinOzdbBqtCe*9yp6)?f)M>T`HIYkXxjf{@Pr?nc31uT5qw?K4nYNvXjD={9bSjO5ABxglcZVxWUoubjP9OCCfxY3G$*7 z+zTC21nho)ib>0ZmyUkP$nK9$&Uhk z)h`O1T)84eo9hnmIP5glHuN|bZ6D91^4E341cI^%v zmu4pCb64AnWx1T?MqeaA@XU7DdM)|NGlZ_T+H)ZV1odGeiX((+S)+WGVC|hH+I-4Q zMHBD~_m0c`MjUkT0cZ7-H&LZcllw*e6)X@!Q-xAR<`M7XnY*3R0>5BT%Of9phf|rs zD@%ULXU}C#I#L8>Fc3`WQ}yWgHVn%UH{1Q>98|nPGOGPDgko?=jpu0q&bm46uTNkq zaV^{pwehcXd$3j;o7i{%^Ijz9ShvL0z=+0->t~WgiC>lU3#!+>5D43VDM!8ym+{+GSPSg#e^;l-MdAdiUfuK>wiBu8`Ut{b{BcOam0 z=uQ}hQO!f))E_Bv7O2-Fru&_z!WGuU0>MV_Cn`8|&ceBUPszs7P1&o!kifFvhqe2} z^GycMTf*Pu!l?o~J}wz4sk9iPqEmvD{$DWHm`zrZT7p6^TH%R2K>ZzL;wLdrfmkUy z#?}QOQlDRJp9EN|Y+f#7?-w)H(#W*ZSvV5PQ9Ta1rM_Uk%K|qcrsOAcep|#vlO<22 zX_d8SJaL|I+}oiqDV{+W5y@0CF?QNIjc3r4Knfx{%P?;}w?Q7^%OHoKG~nggo86P4#jz+}_kpR?~Q37Q)0E z%D<&U3PcqFW-3<6KB0*eH%vU(qYc){YwG1O+!%<>3P@LNg=9mtF3Urf$$jz>V2VzV;Xxit_G(NCCYSJuAe z8BO^~up)oEo}Vr?SZl4%&I=#{va~^^XJ|5CN={hKj~I48P118^XbiOvtC;hA4W%5_ zov2~LG2v7VN58+hNy~F8E^N*6iR+gODU@#SD`Ek8^D!oZiTJ}c0Ty%O7q5-BcNZ%@Vu9BBmxj0SIQATp$BcLHGb&>OFF3VU zjHWe?`q!vNK0-c#t}*Wpe=$Da+yHJDXO2`Z$uUi)$6EHnuBXfFKO z4Xzdsp~)}LVYCl2{L$6Wy$`U2E$mI;HBWFR8ZzOjQ1q0+_$8nvHU8QraGi-)S?rA&^wdT@}xe*%O^x z+a7mMGUv+h1y;gY*paZlbPNxnky}4M)f6()3w1Bmb#DeXfb-;?D1m-?IH|tb(PotO%FUT%cC>{la}GzAn_(o!`3~Qx4-ORSCv)5yXKT>1mTGE%2WT9x>}5)L zWH11{eE!@S@piSb1tDQ<^h~YDZLmC%fe2ak=*guIdEB+c7 z%1}=-*ZE8{uht>9d9vV#1nF#{tA|;c>``>$BF6!;-U=<(H?W>sKp)*TW;|L5k5alz(iI{AT zt8c(j9eD3O&;NN?A%Zh8lUdrQusvZ~Uunu>z0jvND$F!~Or*>c?B}*nJijiDarwMB!G&?+G8k&x1=&@pQ zaM{)B!heu?JXJNCuw&rS3)3y2T;tp3xXYe(+(5&!G2!hT%(o%koN7%FeX4aepE$=n z+9)ku?Zj5vY+rs6t?NJjMb~qbx zWjXJkZ>=4SKOXA^5>!|d2j#qP;b*vkkSXz>M!I$tf(@F&V^!kR;?sTOrAu}Xa@Ax* zaJdLB)Yo|cMNVi&qaQMIRi~45^Umc-V%aq>=P&g@od=5tE#rG8WJdbxR#Qy95bw1QrNLR~K! zF{!wK(5YWWi4{Ag>gU7NJ%jj`kMr*glPc5!wEp`;V%+35314oH-f1F8ZJK_|yIR}I zBsISam0@kcvL=%xkO4Jx*TEhaw*ms&w_E^0{N=^qR{9@&9~^#DHm%TM+3pP$3IRU$@R-iamI^tGu*ZN`Y#^<_vubi?+yo@Z~gdfVq^H4+h(6^st|Q z4Nv|nq7>3NEnais{Mi(Aj;@&00`2+7cjW`RZ?*J|p{Cs#7!8yjO+v`?%CX= z3pdU*kqO*P=%RDl}uSi8x1%L=c?2kNhQ0Mz6~VeNm|)4Eb#i~ z{S9k`4c&;Yq{b*uz$$IEy#6`!Q01j}vb!vH@eVK>SZjk^){-$Fp;pxGk;GRF6jX)p!C zkXE#p*~KsWm22qxnCBv{?Sq4guVj3@6#^Gadb_7~bAM7U%pB;BChjBnoQgy33ldXr z>IW9oI%K{{K~}Vmx*FgX+Rw|yTXuWt6?@Oi-*nX_*1W8#wP4|Cx0j^*@;0`8b&Q0A z>0nQtCmO`9Ef2&)g81ACGaK1pkoaDFFQVf_KvA9&vkoq9nuE`N^rZEA8Tx%JTNmCd zX=%jZmazDy2@!<6go~nGhy$B5?X*F0&s$eZZQG%&5HO^9Kp;-QP7_>@U|o1c4erGk zPS$E?%8gWLO>jtjIQd+u(rz_HvqmB;q)R4w5RhTF{$8Tnie81L4t8RiP(gV6 z9>rj3?EyP)f`Q&82`eRqWn)Kcj&T9ptQ;z-Aj`F)K3*p^1yxZH?L*=eUE4yD+hHl# zD_qVx6F-P!oSseMi%&z^QF_b3RwKc$PnjXvTp@DY^yt`4kf4Pf<{qt5Q34;WlKMq# zxk}OhbbY$DNmt_cyp$A@I!j)fidus4!bFu3>B~qgbo&6wU_gG}yoiQ=cvO12>e5s+ zOXH~-Hww6x`3@i3IbU!`t5>cqK)5^;E!gYep22?Af9x$vZkFTP5@h_SUz_U06LyA1 z|7)Ic3QdC*QgMZl>M!aplh6vA0a7cpcHmx$)WwxEl8WZMHcvWXa1~l4v3Xdqy9=9J zv`wj$*U3*)XBrLSMzjPA6(pK+DRX=xGzK=#%8Af3b42aM6=L3Da`@@{IHiVhBUAWr z07T~|t%dS^RaT1Arocq_ipdpkllHOk2uGM+Rbt{K&$A$Kn?e(%DFBOj!BNgkhN`UF z3ey&qJAzZ3jKWZZdlmEg`q&JWl%G4*ZDU(}msIj`&CN(?ZE*Z)CtYRT{9_I5PVovH z)lN3$$Yj!*OdR(1=er>$$veU8u6dku8Aw@V(4%Y*hkpQ_*IL-`Q9c8W`l>{~Y;~aN zQ|+uK2sL44Pa)j7eUm{R2bH=duiq!hK2(R3J$_B~_K)i)$_N`N(vK_-GDZgkrehbF z%Vp}ld-hs9DO>jqj)D=)d0GoP=bGT#J?NEydSjaYuCZ zN9$FkF{DH@WSjuABuOkHboX0Lqf+SLzJZRr_YFe7Nm%iGKMEuAf zRv~?H`KG-Hl_kL=UKGag;-v$i%l~{H3nC#q>f_1!+`q-J=a6i8^(Y*%9xytK}5nE)`qmS5!G$i)T7O zQKUGlUo$zD_sf~Jz_bf3{HL9daDbVFeIs{r;p=2}!;l`+Jr3@Sjbt3Kd*9VY;Pa@%?XMWyC0AGDS z7G@_X_0bi!SC2(%heYd=xKTBvpC+Uc9VeWM)NFDKKlwcf?ugKthqn(aeL#yNcPs1P(5wCo=a>acK~-W~d3fgk)YA zx*z;jL4p6%9MUWDy|e=(^?|Z-En)_IEQQ=?KUNz&-sU}0`$-#!Rwwx0dCJSTsteG` zHajkjbQYc1A*!D&BRNr%6=;v&qTnrIop|cts||RCO9rvDktwQ6u6KKC=Eip`m!6;f ztdeDO_2G#vxHan7v?(yvy3SN$s)G57PA?7Lad=2a1(7qz=wSo3LYaczJ5KRUJeSE& z?ifzT^%P}mtyQ^zc0-=&@U1&`FGcVuA^T<~hT=)w&%A}}=L?um7Cr=1WL;m(ET>Y< zx8|vJx;*)Uz9~pM;(G3V`8+IX+N4cc-+6x0w>#dml+BOSwYSE+wll@S%E{W(4;gm{ zSliXRI2~?2XDn2g92Gi@ZFY@qt=7^YUsbPs)uua3(7`WRvD>AlOf z`Jq!!gm2?4V=y~GRhJ$tQQy+|jP_y(U7yy33f0?gZNWLj^^;o-Ocr&^dkTD9BZQGL zLyWcexD2v6?|-JNu$BOytq(B(uzz_MiCvv zbeE@BvXi8RqP_vJ_ka*m6=}%p(~(CZt=Ci4MAR#N1kTRZWh zH9j)WUVFI?JuqsjPE|c>@YJZf-HXM;`_5MLrV%5>6>^$q}BRvsP zvy^3}dQ@RQ?#N(6!)%JYR^H^mW!(5+nQ1K0uOm`m26XI5EUHn z>U?G1q%NLDvND+De5j1>&M=7T^5^ZU zlVy9i>}(kDfU2L=h>#7t_K7lYzTg*>RuIfVD_? zUP6XIiK`4p`|k2t9QL1#YwO6iam-M7ZZvKmV;2fSyt3J{&bDL>jUs}!71Arvzm@}0 zb~cVHRGF+x6sy>Rx4pX-B-#4Qk{K(d?9CO=iA2rSqV`Pd1stO)L@asj0csq(7p#ag zEJj#xI8G7pGSDL(uACWZ9BlZlG`_;+57#=&#M9`-SP3KZRYC77E$xR(QYxNpDlVTq zwP_vMEBDmdB$@Q@b~+aC7@WPblYS7^{rKPv`PL<%_hrO@;iKHF`)p6xP#8DXxh3OA zk7$|caTboCNT~_OU`XzDD1#q24{4j2!*e^==~3vQwk1nj@b)6#-ZqEvQ-LP`QKVA86wYdWl$1-(&Qk4pt6#rGK!r|L`Y>LbE~BIA zj|U)zI(w{G$iq=bn%|q}()#uHktAN497URxBh6;yOw`85XN!MuPfJhFZqMME!p60W z1>0nNQVL8HjB9pURonJRI-DoEi1HdKYK!LGs36BA;c94QEiwbeg$M!!DcPL-X)7+@ zlW1X^3Tp^y)nV)>y<{aGpIH z&0|^}zaQ^Y)p11nm4wm_467$Fn)DOy;Tb{t`A)VsBLOPvK=X3+?yf80`s90EEb6qO z?VMP)*073$E2ZqstX6EV25yH1yHYr{V|hBY?HC0?eG;`JV`47Y52?9=uC{jrc`fwL zZP;d$>ySL6AwvQ%&ES#XOH?ee3?s97PxKw)eea?*T~9Y8ukPs*rCwM@l62*TEYEUQTiBF7IN5TZf*vze zB-X+e3e+WG=b89RacPp;(e7%QuU@XUtYQiiLL?N6YCF9w7Q%f5r+7HAavcPu&(b5) z%BA*O+_7vJznhiwRi(=u`@Kivgu>8>!$kvWxUh}O3mw)CrWdKCG7_U`NhN=5MgfA_ z0qH^)dS3FRdCyse>ojk4=)PeOI0BWn>f~w;G>a#}Rq2Xl4T{3!FiszNx|(e<;HAeW zo#>KYtG>oY1X2`jDhZ=x(OO>sxRw`lEp)^C?dm#O>_l|e--U?5%@(sKQZ)Dxj-$S* zAko69>C8Iulh$eG+Ja0gCsm$JlE9zZkqL^p2#dPZ9M13?GGi8_?5}3J4%<1Jj79U zaO$=2xCk_mw%w^uLWl8Rs(#&6%YkXD8-sZ};^YxGt^Dw-9jUkSLeRZiYeP&~)V>Q* zNn$r)v?$%}hp}h$4T@A?Lk07HcME5Jvx!>!upgYBOLKu_Un;Sn7Bq#Aa*Sg69&SYD zW18`v50l`YPby@N%`S4f@N2KuXNmS&_SHs^i0jgL(edv$9=^ZEebNP4QzV?9<-UIX zMY=Ei>osA?MYk$&%V^(Q=z8PS>(NG)eQMY`; zF}UQwbazm{S65udshdcZxxksiZnj}OmC(V6I*Cu#ms4)`AAGj1%I;UkhSn~b`I54G znp&eHrE0Zh`0AK$OFx4}GI%B~E*{4FB1vXcvaRU#bR#y$N{O0wYkhVXI>K}>PWE}2 z#(S^r+QU3k^t)Ox>dOKTDi(3#JV-5|KDXPg8^9xS2*2hR^q!i~-ygC&!&u5;J>(ej z5s%^EKFa64E&B<*o2U>w=2OiZ69lUv!it$PEKw2q8?}D#`4NPAETU?lg2V|Vy(P!y zQsSWlfBDYIS2~pC_7l$z58LjThhwR!i9w5I$8(2)g}yF}g1p&C9Cfg#7uXC^Ghci{ zD81egh{rvx6GIwzi))Ghq8S}|z#|Yvqzl@h)aCnHbe1;jaG`Iw>$r|@ks)v5K_s@n zt<6x}^%+%mGqFDL0vYNQ{RtTm*RlUu<4Y*XT;Gw&L$Q4x_4DpAn}r^B2&_Xz9e8V1 ze?qLFFhJ{?G?Ff)b86S8gSE`FCAmPB>7vztO%Ueo|FmIYy}8%_8Fqb2%QW(o_0hm_ z*GUMDevB%Nu52S%3`BzYhH5*KSeZ?X-%h~fuJwq6jMcb1hHXxqsPFP3t9f(lW1z|z zbDTBj&5_A|R82WHCeW7sbV_!Az1J!JAtRoFZCz2P56%JSEr%U4GvRR{nR-L-(xyuh z%2qpE#vglQx)?wbaMkkbz|jCaRdoXGqLz>h&LmV$KLkn0suAoZ!r)vH_)hbSPp<6U zBe2qMfz=^ekD>U94K zT}_xlxSiaE2nrg$S@aiLLYSb+WHn0GSr&2tsjHGT*B?2>n!J!+paT1R4u^pWbtK=* zR>bJS&?fXPwjDMhV>hG8{8qc3!}3=2DD69PI|MpA525hn)<+wE5$3b(v>P=?4QML7 zRnd4WT_OCr>Zqi%l#8TwQbr69NYBeiTY8}2&z2%sZJNyV59xD8bT{*v&4mx*xoX`J zDl**P|AFbJLcd{o017O&caQ&Bs0hK`mF2R(YEyJ>&}LybZ~8K|hlzHQ^%h^~{p*v; zc@#M9ln^)>iAw0{P2%!e^}{c#l%Wf?j}Tgxc;2!d{XLqfwwF8mT|3F2Pm?J~_2mKv zeYE;B`Kmi(OK161<0N76ZBgM?I3j8g-@cUzjYZ_WBEND$9Qz{z-G%-er^Y>}8i6!l z2Mqv9VC^N5i=7inBLN-I#faEApjZvISg*2A6% zNUnS%$`~%oHOob^7-;s!`UjTQ5i*ocweR zNF-1BPQ>~dVmq|s+Rx|J)+@csqTxnL=BAU1{p2M@E4ON8kU9g~ zy~<6H{fswF@yx?U{sEFEVen9ruC(}?;C+{_ria}GESSM-;sIHiQS|hS0A&$7&G35| z^|fxptYcR%XhMai=B7xf>hu=KUxU}KeZrZGm{)DmMj_&wXVvGKo<%a=*GG&Hz(R0WX_Nwu%p;w_u7O%MOBOm7^qs#3DGZ}}J@#iM zh2o{(O~rkiHwZrcq1e&pDJ`(!Wzh9>Xhy|MSqqoE9I$24= z^WsK|yQ;KL9{GQT`zqxxuN#79!xD2K-izp9#!zL3as*Y}z$80yIv|U3vponF@M^GN zNpB0uB((HD4K%d!b&;rP)~zK#_=>3;9?;QuI-Ttmmt7bQ?y0YliA+$CEPpx?G&R=B zL5<1B8C5UgMv@1lTh0Zn;XYrez;-;IF-5Gk3uihsljHGFLk=J7TH9o~9$d2W)JRLF zA*E`go#}_>l|S9l=ivWBNcDoZ^M(JBsXhV+7bBSW&xK>?!>WOzaZNzJ5)0;lv|aKx znz?ETd)~rXXKYE^8NQcshrRdol#HMT~daAbbO^k#)uZZ8m+4MD2PrI4XkU zS0RE_rpIFW8G+7gD!f;*;W z2nFY5>}9;#hQh0WDBf@qsHNK^6B2dFBYL6WrgSHwC_=kdMrMZ2xo=zHt4Qi|( z)uCaFHKkJ5ZNHmHRpsRHl8vu&3J#hHq1Uq6pUu-l%Wux2x0Qe_s|nL0tA4|)p_JxY zATzxn^RiRAO{%U&>3j`8i+!$JmpA*bf`{>Am(v?-l@I5WlW2aeE83PsNi`Pu$$n4ioAti<4S|0;!yLNk}Ytk!~Y z^>^%E9CYH%{c1DP)wwvUfoDD`+j##~OaEq^8KlKNuASxu@L2Ng3X*TWygDJWy8dbP z4T+DL(k)F)<6B4-`rvu^F{?7+KZsgnGVdy5@m8u46)Y(e!|oXKp6}|^a1HRxNy_DF zDWn6)S8W}V+27J%k_-Wd zn$?HJ80hrFw#cJ_2gEAW?+AzN?5K$gKH7umYmnq#EAV1qe;o$Z)1#>W%$GSWRU7B8 z|9W-i)As4gMj2j4#QUV%%oDQ24H2CYq%=+vQEFWM<*}A2AqnM z4E!;+&}cVRR5p`8rnA0_Sf?LW?}pi@MRLh?`L?Tnsj-c~*}he{Q;L5f1Bg>+73h9` z;u|D%h%r^%`0GO6j#SQdj92l(f!DDzzt5~}_3)JdAj|D^`(hOKKEOft$ zOZ233b}}a&$U?RCtQ<(bKUyVk$s#bEi=%Vgp?5WNUCdNBA^4!3H-=ZKnj-(T7`_d= z@T-Z|L2{8q4?gSFPx}Jart8MZfDUo*LtFt>VSI_k*Uvn5%yJ)fTYa#3V~_-HOp=084B$QPh|er7=Jp zXDk-y2;u!Qq-7ls55}Vq3s+@Po4GiR8TH?NOuory*p;QTOktKpr8!^BZU#)$8IWXa&=yEqUxJ@e2&HlVj7ZCsL zFRCNB0mW2LfMd#Lw~&?l@SuA(=Y3@!bN~3(XjkXFmip3SS$yzId3x1UD~J0^z6_!$ z%Yr(V2*J8_BgTvVqIXlS!x@hnvL9S6jWSbL46x+uxw<7!TkZi_CVJy;ztG2ul*n>g01erlvq$UXKSh4b+h1g7*Tywww^_qGlWY6 zX-^HJZR(=A8_Pd? z6c+|$YKx^B%p)KE@wmj4Mo%KTcV!B{QP}%_EP9d%!{(CU?LSsuZah*29jsV#Q@`Bi zeNWT;2H2^P2jZ&^h{(P zyrcaoXgva6kj|GrT&OVz1BNO`wwn<-3pw0v+f?9H6zOou#HPr^Pe0VQcLErDTr8eg z;F1{}8T35s?K#h)0) zA4a)}uJU+)iT)Ldl;O&~(TH~(E>Vptp<7%1Ue(tn0*|KZJe;w$Wi}BzV^&66c?^^o@^l!GF?fkEte|S-Y;qAICc1+X9!n9gu=}0NZQ8 zX$F_NpCr*C;#udYtMq3vLR&@P2dvabh~(5A?VG=JVD2U6SPAtU7+UO-GJUP}^-CbBRwz;Ep{7D(w%Ke?H!j}+VTXD3u(HGlFh zoIiDivPHriAw6I~hx{ChSm{=d<~pE;%su<}XfSV+6S~WQZ&JQ8PKa|foo-=1ov%a7 zCrHDO(4j?@=_233*O3-|#4bVGKcyeHd&GN7;v)EOS`bX=%hdT@7OGI)n z@nqVUW7n$9Bm`@P!Lfi203PqPzS@-$UQHp_F-a~CT$2&f7R$}M_Xz)wjr?C)!ire& z8AWTkrrpb|{L)s-XFp2kq)%?^{^?g4uBL6*UO?2B6H(1i1LVToId@K$)F%(0DGLHuNiY*uaWUkN#RanTv6Y= zCYt4}C|+OMRHAp0UXO%fHGSy&hn@)Se#u7*$>nBwD5BdT0^;UiVjAL53~P-~#bjS-YFad)&WV zmramToQwKfx9YAk#rDltoe#$HW_G3e$e=#iqyXd;)Q1Z4)%6nczljCHPzp_AuB_F4 z3`OcmEvAYN1B7#!@l9fJU;Lck?|LOL7&b|~sq!v=Lx>_)i7PCCgG|LeF zI#F#lFTm_{@WPks6m0J4MTl*=I^17rR_~P@?@X1XvT-=LMw|5xC*q67M@tijwr&4q zm1u2Jc!p2sqSo>Ad{M(wXH6qri)tXB#1YK{$)CZk{(l{5UqLP;m?z5bBdwJ1N< z^_35v*F=?_0E%!nEhVLbq_#9#vcJ|2=I!S&!MyZYasx z_^TSDOrlyVe$Y{eMS^QAD~|)1a;ODSuP34p35DPf-nv%0vJIylyrmt>P$p8YL(mi& z@TsA?kHBvdeL*sV8-`?X{v*Ml|E$_TOF89ye5=Y#3L6J0$vEU?88n1HF~ABOn08MT zDPc>KqSA@@7(3DG#fqQFLzBs~FX6Z7(0uuk=4U5MY11nj@GRopUG-Vby=$GuL!pBX8CVEKhzpDPB$~A{b72L1`9+83R zfb6dZy3(dD+2JP8oCuQ}Vv^z28CDRON|{x-6oGaeslq;j@VAJFR$Lxi#G=6_Bi;q* z%o;iC?l<(%$Ged6O4dTXrM9G1kLIu0!(ym^f2&&Qi~V3L$yz={-gNiWc?FO|E56Yt zR%&vRGbd?~ts2%7ivFo8G%{u|d)ZBGInyG%TCuW2DUu9QSC=@pK+f{Ewisj1hJ1K7 zidyI4iYYL_{&$GWxATF%TOHCz8{5x`wa*1a2Q-k*?Aw)u?`dlkbRA5kX+NUudzZe^ zFFeMo!}!8$ZmP$hw#Md@n7+C&s><*8UR7Yu0nhM(FaAHe*7rZIGCJ4+zd}cP-lFs< zUD~tHi$=GGasSNg6ueTmaa?p%O@0$gl_Lp3Zfs*WSgz!Ay zwugb4H2Q3kjio%?pn4wQrRvU2`VGf}z{Aw|J(<9=&h>k^(Wxc(m0nByGDPSM!+{*Wn{;#=X*#7(=FEc_mkuD<^T!&858Rs2XVdqgLYkKsM z;BKJ`;A5cUoE~bCB_ypW484~5bUyz93WBn|8|Pj7?XhK1`MlmRujYdA2KG%c>Hm`W zPb9(avDc@`=`G}<${yCwWV|i|vbU9S*NqQgvQ= zRsP;uKSAw+X5k&M6IvS7s!QwMe)<1q9SQSxm3YgST{Lh2~ zwEJrkYb%zPvnByKVdWnDB;r0h)la1eA@QFp;|la>Y6fMLD1Y~_QkTDxgyuoZD45q2 zE-!vr{dUO^8veuk<$rBy7(XC}uP?A0<5NVY3#9>vcJ^#zHt7(=MPKi*bIZ=k#%5YQ zWs;%#Tg&!*ox-@7cS3C_Gq{?{b2G$c_WAOAWu5?7)DwW``yt~W!e;(mJ9g3{-YmgC*sJ;(7O|P?YIJciRa&)0ef6S}hyN2vF1x+YO`oapFZtn6 znNs6W@A`nO3g=IIAYL1^AG*7**K9BM8s{I6E`jB`MNYQm9ZOOlxE68$=^0P#b;fq9 z#>XN@+d_t37My^p6YuNkS*eiwcmxj`a3iWn%4*WM448aRt8QOUaQCmU&!QWk%EFr>?cBzyjZD!oSY-Y*L zQwH(!X7gBx>ly8dFjzYIPREx|kdz}8UFjAPssY|pg5M<}aUlaW%;M1H# zKv7m>D@|5<>J(xWb)n>@Z7-`h>

AyQaN1j2gqVV2t-~{s9^c+Y!EZgXG1AV_MAu zX4bdbE*C8>RWzMm#*|(I%Kd*zW$*oVs%AW6#N1jz>A4fHp7@+jSFw{AjqZ3~wfWsP zfyOs~GyPX>LHO$RN$$6q@-RV@3NsmNgaks|g6D^xKmym`m8q+frzXHc>&z+4mJ+Hcv(TYARJlfLF- zPwB88mN$A@p0FHTXzps7mYId~=-hcsxwg&G(#39n81gF2|M>JOP}jz}e=q)nfi-xq zr@k^)r&y0VJMo9eM3k9}4@au^?XB%@r<8&D9tf$DK93Mt>RWfCXevnZi^6KyX`)uz8Th&o8Esk{CJtPt}FGpG3;7o@Uavi zBOlE*_7Ss5S}6L}*c$i_ zV%PIK5oPDon`g40Kf3vLdvKI)wDR_l)iTmNcCOQA9oqM?S|j14clnh+KY)AOfRUB* zp=_(?!I~V%e}QKsaH}R}|naZN@Ak1_7t7T7j16y?e?l0{Wud7dem9O8odT!+1Nv7J* zQ#H9}^eG#fuf6%=zud3>CLb>y$MS%QXLY|Ge0~33$lu%frEc+eg}G&xa!i@h$fu8D zK11VF7hs-H{d!F3wbM&>o7%@GeeXVgse4y5`|!z@^81|=&;0wRxmR_iq+|1>Hsim~ zRKrhhIKTSXp;JemN!5Sfdv>9}Tn6vom5Wc6@3ng&+x6qg8==)rchU0QDF68}nM>8*0o_+Sz6(6;GcmAH8cKqeR1c7&xvJ+$$bfT#q<_sU&MyWa@O1TaS?83{1OSe-Qv?72 literal 0 HcmV?d00001