From 0f15a10ca3d723b41d0c881ea57e9a29744fbae3 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Thu, 24 Apr 2025 15:32:06 +0800 Subject: [PATCH 1/2] Add whiteboard sample and MCP server implementation --- .../Controllers/BackgroundController.cs | 41 + samples/Whiteboard/Diagram.cs | 77 ++ samples/Whiteboard/Hub/DrawHub.cs | 85 ++ samples/Whiteboard/MCPServer/index.js | 131 ++ .../Whiteboard/MCPServer/package-lock.json | 1190 +++++++++++++++++ samples/Whiteboard/MCPServer/package.json | 18 + samples/Whiteboard/Program.cs | 19 + .../Whiteboard/Properties/launchSettings.json | 27 + samples/Whiteboard/README.md | 107 ++ samples/Whiteboard/Startup.cs | 31 + samples/Whiteboard/Whiteboard.csproj | 15 + samples/Whiteboard/Whiteboard.sln | 24 + samples/Whiteboard/appsettings.json | 15 + samples/Whiteboard/mcp.gif | Bin 0 -> 994556 bytes .../wwwroot/images/signalr-logo.png | Bin 0 -> 2213 bytes samples/Whiteboard/wwwroot/index.html | 197 +++ samples/Whiteboard/wwwroot/script.js | 518 +++++++ samples/Whiteboard/wwwroot/style.css | 72 + 18 files changed, 2567 insertions(+) create mode 100644 samples/Whiteboard/Controllers/BackgroundController.cs create mode 100644 samples/Whiteboard/Diagram.cs create mode 100644 samples/Whiteboard/Hub/DrawHub.cs create mode 100644 samples/Whiteboard/MCPServer/index.js create mode 100644 samples/Whiteboard/MCPServer/package-lock.json create mode 100644 samples/Whiteboard/MCPServer/package.json create mode 100644 samples/Whiteboard/Program.cs create mode 100644 samples/Whiteboard/Properties/launchSettings.json create mode 100644 samples/Whiteboard/README.md create mode 100644 samples/Whiteboard/Startup.cs create mode 100644 samples/Whiteboard/Whiteboard.csproj create mode 100644 samples/Whiteboard/Whiteboard.sln create mode 100644 samples/Whiteboard/appsettings.json create mode 100644 samples/Whiteboard/mcp.gif create mode 100644 samples/Whiteboard/wwwroot/images/signalr-logo.png create mode 100644 samples/Whiteboard/wwwroot/index.html create mode 100644 samples/Whiteboard/wwwroot/script.js create mode 100644 samples/Whiteboard/wwwroot/style.css diff --git a/samples/Whiteboard/Controllers/BackgroundController.cs b/samples/Whiteboard/Controllers/BackgroundController.cs new file mode 100644 index 00000000..54c6522c --- /dev/null +++ b/samples/Whiteboard/Controllers/BackgroundController.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Azure.SignalR.Samples.Whiteboard; + +[Route("/background")] +public class BackgroundController(IHubContext context, Diagram diagram) : Controller +{ + private readonly IHubContext hubContext = context; + private readonly Diagram diagram = diagram; + + [HttpPost("upload")] + public async Task Upload(IFormFile file) + { + diagram.BackgroundId = Guid.NewGuid().ToString().Substring(0, 8); + diagram.Background = new byte[file.Length]; + diagram.BackgroundContentType = file.ContentType; + using (var stream = new MemoryStream(diagram.Background)) + { + await file.CopyToAsync(stream); + } + + await hubContext.Clients.All.SendAsync("BackgroundUpdated", diagram.BackgroundId); + + return Ok(); + } + + [HttpGet("{id}")] + public IActionResult Download(string id) + { + if (diagram.BackgroundId != id) return NotFound(); + return File(diagram.Background, diagram.BackgroundContentType); + } +} \ No newline at end of file diff --git a/samples/Whiteboard/Diagram.cs b/samples/Whiteboard/Diagram.cs new file mode 100644 index 00000000..fc733c16 --- /dev/null +++ b/samples/Whiteboard/Diagram.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; + +namespace Microsoft.Azure.SignalR.Samples.Whiteboard; + +public class Point +{ + public int X { get; set; } + public int Y { get; set; } +} + +public abstract class Shape +{ + public string Color { get; set; } + + public int Width { get; set; } +} + +public class Polyline : Shape +{ + public List Points { get; set; } +} + +public class Line : Shape +{ + public Point Start { get; set; } + + public Point End { get; set; } +} + +public class Circle : Shape +{ + public Point Center { get; set; } + + public int Radius { get; set; } +} + +public class Rect : Shape +{ + public Point TopLeft { get; set; } + + public Point BottomRight { get; set; } +} + +public class Ellipse : Shape +{ + public Point TopLeft { get; set; } + + public Point BottomRight { get; set; } +} + +public class Diagram +{ + private int totalUsers = 0; + + public byte[] Background { get; set; } + + public string BackgroundContentType { get; set; } + + public string BackgroundId { get; set; } + + public ConcurrentDictionary Shapes { get; } = new ConcurrentDictionary(); + + public int UserEnter() + { + return Interlocked.Increment(ref totalUsers); + } + + public int UserLeave() + { + return Interlocked.Decrement(ref totalUsers); + } +} \ No newline at end of file diff --git a/samples/Whiteboard/Hub/DrawHub.cs b/samples/Whiteboard/Hub/DrawHub.cs new file mode 100644 index 00000000..ab7de76d --- /dev/null +++ b/samples/Whiteboard/Hub/DrawHub.cs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.AspNetCore.SignalR; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System; + +namespace Microsoft.Azure.SignalR.Samples.Whiteboard; + +public class DrawHub(Diagram diagram) : Hub +{ + private readonly Diagram diagram = diagram; + + private async Task UpdateShape(string id, Shape shape) + { + diagram.Shapes[id] = shape; + await Clients.Others.SendAsync("ShapeUpdated", id, shape.GetType().Name, shape); + } + + public override Task OnConnectedAsync() + { + var t = Task.WhenAll(diagram.Shapes.AsEnumerable().Select(l => Clients.Client(Context.ConnectionId).SendAsync("ShapeUpdated", l.Key, l.Value.GetType().Name, l.Value))); + if (diagram.Background != null) t = t.ContinueWith(_ => Clients.Client(Context.ConnectionId).SendAsync("BackgroundUpdated", diagram.BackgroundId)); + return t.ContinueWith(_ => Clients.All.SendAsync("UserUpdated", diagram.UserEnter())); + } + + public override Task OnDisconnectedAsync(Exception exception) + { + return Clients.All.SendAsync("UserUpdated", diagram.UserLeave()); + } + + public async Task RemoveShape(string id) + { + diagram.Shapes.Remove(id, out _); + await Clients.Others.SendAsync("ShapeRemoved", id); + } + + public async Task AddOrUpdatePolyline(string id, Polyline polyline) + { + await this.UpdateShape(id, polyline); + } + + public async Task PatchPolyline(string id, Polyline polyline) + { + if (diagram.Shapes[id] is not Polyline p) throw new InvalidOperationException($"Shape {id} does not exist or is not a polyline."); + if (polyline.Color != null) p.Color = polyline.Color; + if (polyline.Width != 0) p.Width = polyline.Width; + p.Points.AddRange(polyline.Points); + await Clients.Others.SendAsync("ShapePatched", id, polyline); + } + + public async Task AddOrUpdateLine(string id, Line line) + { + await this.UpdateShape(id, line); + } + + public async Task AddOrUpdateCircle(string id, Circle circle) + { + await this.UpdateShape(id, circle); + } + + public async Task AddOrUpdateRect(string id, Rect rect) + { + await this.UpdateShape(id, rect); + } + + public async Task AddOrUpdateEllipse(string id, Ellipse ellipse) + { + await this.UpdateShape(id, ellipse); + } + + public async Task Clear() + { + diagram.Shapes.Clear(); + diagram.Background = null; + await Clients.Others.SendAsync("Clear"); + } + + public async Task SendMessage(string name, string message) + { + await Clients.Others.SendAsync("NewMessage", name, message); + } +} \ No newline at end of file diff --git a/samples/Whiteboard/MCPServer/index.js b/samples/Whiteboard/MCPServer/index.js new file mode 100644 index 00000000..37643a95 --- /dev/null +++ b/samples/Whiteboard/MCPServer/index.js @@ -0,0 +1,131 @@ +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { z } from 'zod'; +import { HubConnectionBuilder } from '@microsoft/signalr'; +import dotenv from 'dotenv'; + +dotenv.config(); + +const logger = new class { + log = (level, message) => level > 1 && console.error(`[${level}] ${message}`); +}; + +const connection = new HubConnectionBuilder().withUrl(`${process.env['WHITEBOARD_ENDPOINT'] || 'http://localhost:5000'}/draw`).withAutomaticReconnect().configureLogging(logger).build(); + +const server = new McpServer({ + name: 'Whiteboard', + version: '1.0.0' +}); + +let color = z.string().describe('color of the shape, valid values are: black, grey, darkred, red, orange, yellow, green, deepskyblue, indigo, purple'); +let width = z.number().describe('width of the shape, valid values are: 1, 2, 4, 8'); +let point = z.object({ + x: z.number().describe('x coordinate of the point, 0 denotes the left edge of the whiteboard'), + y: z.number().describe('y coordinate of the point, 0 denotes the top edge of the whiteboard') +}); +let id = z.string().describe('unique identifier of the shape, if it does not exist, it will be created, if it exists, it will be updated'); + +server.tool('send_message', 'post a message on whiteboard', { name: z.string(), message: z.string() }, async ({ name, message }) => { + await connection.send('sendMessage', name, message); + return { content: [{ type: 'text', text: 'Message sent' }] } +}); + +server.tool( + 'add_or_update_polyline', 'add or update a polyline on whiteboard', + { + id, polyline: z.object({ + color, width, + points: z.array(point).describe('array of points that define the polyline') + }) + }, + async ({ id, polyline }) => { + await connection.send('addOrUpdatePolyline', id, polyline); + return { content: [{ type: 'text', text: 'Polyline added or updated' }] }; + }); + +server.tool( + 'add_or_update_line', 'add or update a line on whiteboard', + { + id, line: z.object({ + color, width, + start: point.describe('start point of the line'), + end: point.describe('end point of the line') + }) + }, + async ({ id, line }) => { + await connection.send('addOrUpdateLine', id, line); + return { content: [{ type: 'text', text: 'Line added or updated' }] }; + }); + +server.tool( + 'add_or_update_circle', 'add or update a circle on whiteboard', + { + id, circle: z.object({ + color, width, + center: point.describe('center point of the circle'), + radius: z.number().describe('radius of the circle') + }) + }, + async ({ id, circle }) => { + await connection.send('addOrUpdateCircle', id, circle); + return { content: [{ type: 'text', text: 'Circle added or updated' }] }; + }); + +server.tool( + 'add_or_update_rect', 'add or update a rectangle on whiteboard', + { + id, rect: z.object({ + color, width, + topLeft: point.describe('top left corner of the rectangle'), + bottomRight: point.describe('bottom right of the rectangle') + }) + }, + async ({ id, rect }) => { + await connection.send('addOrUpdateRect', id, rect); + return { content: [{ type: 'text', text: 'Rectangle added or updated' }] }; + }); + +server.tool( + 'add_or_update_ellipse', 'add or update an ellipse on whiteboard', + { + id, ellipse: z.object({ + color, width, + topLeft: point.describe('top left corner of the bounding rectangle of the ellipse'), + bottomRight: point.describe('bottom right of the bounding rectangle of the ellipse') + }) + }, + async ({ id, ellipse }) => { + await connection.send('addOrUpdateEllipse', id, ellipse); + return { content: [{ type: 'text', text: 'Ellipse added or updated' }] }; + }); + +server.tool( + 'remove_shape', 'remove a shape from whiteboard', + { id }, + async ({ id }) => { + await connection.send('removeShape', id); + return { content: [{ type: 'text', text: 'Shape removed' }] }; + }); + +server.tool( + 'clear', 'clear the whiteboard', + {}, + async () => { + await connection.send('clear'); + return { content: [{ type: 'text', text: 'Whiteboard cleared' }] }; + }); + +const transport = new StdioServerTransport(); + +await server.connect(transport); + +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +for (;;) { + try { + await connection.start(); + break; + } catch (e) { + console.error('Failed to start SignalR connection: ' + e.message); + await sleep(5000); + } +} \ No newline at end of file diff --git a/samples/Whiteboard/MCPServer/package-lock.json b/samples/Whiteboard/MCPServer/package-lock.json new file mode 100644 index 00000000..dca6fda4 --- /dev/null +++ b/samples/Whiteboard/MCPServer/package-lock.json @@ -0,0 +1,1190 @@ +{ + "name": "signalrmcp", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "signalrmcp", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@microsoft/signalr": "^8.0.7", + "@modelcontextprotocol/sdk": "^1.9.0", + "dotenv": "^16.4.7" + } + }, + "node_modules/@microsoft/signalr": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-8.0.7.tgz", + "integrity": "sha512-PHcdMv8v5hJlBkRHAuKG5trGViQEkPYee36LnJQx4xHOQ5LL4X0nEWIxOp5cCtZ7tu+30quz5V3k0b1YNuc6lw==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "eventsource": "^2.0.2", + "fetch-cookie": "^2.0.3", + "node-fetch": "^2.6.7", + "ws": "^7.4.5" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz", + "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/eventsource": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", + "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, + "node_modules/fetch-cookie": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz", + "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==", + "license": "Unlicense", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "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.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "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/zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + } + } +} diff --git a/samples/Whiteboard/MCPServer/package.json b/samples/Whiteboard/MCPServer/package.json new file mode 100644 index 00000000..988bbfb8 --- /dev/null +++ b/samples/Whiteboard/MCPServer/package.json @@ -0,0 +1,18 @@ +{ + "name": "signalrmcp", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "type": "module", + "dependencies": { + "@microsoft/signalr": "^8.0.7", + "@modelcontextprotocol/sdk": "^1.9.0", + "dotenv": "^16.4.7" + } +} \ No newline at end of file diff --git a/samples/Whiteboard/Program.cs b/samples/Whiteboard/Program.cs new file mode 100644 index 00000000..b669e6ef --- /dev/null +++ b/samples/Whiteboard/Program.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; + +namespace Microsoft.Azure.SignalR.Samples.Whiteboard; + +public class Program +{ + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); +} \ No newline at end of file diff --git a/samples/Whiteboard/Properties/launchSettings.json b/samples/Whiteboard/Properties/launchSettings.json new file mode 100644 index 00000000..3f820e4e --- /dev/null +++ b/samples/Whiteboard/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5000/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Whiteboard": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000/" + } + } +} \ No newline at end of file diff --git a/samples/Whiteboard/README.md b/samples/Whiteboard/README.md new file mode 100644 index 00000000..a56bd7af --- /dev/null +++ b/samples/Whiteboard/README.md @@ -0,0 +1,107 @@ +# Whiteboard: Real Time Collaboration using Azure SignalR Service + +This is a sample project to demonstrate how to build a web application for real time collaboration using Azure, ASP.NET Core and other related technologies. This sample application includes the following features: + +* A whiteboard that anyone can paint on it and others can see you paint in real time +* Painting features: + 1. Basic paint tools (freehand, line, rectangle, circle, ellipse) with customizable color and stroke thickness + 2. Upload a background image + 3. Pan and zoom canvas + 4. Undo and redo + 5. Touch support for mobile devices +* Real time chat + +This application is based on the following technologies: + +* For frontend: HTML5/javascript, bootstrap and vue.js +* For backend: ASP.NET Core +* For realtime communication: SignalR and Azure SignalR Service + +## Build and run locally + +1. Create an Azure SignalR Service instance +2. Go to Access control (IAM) tab on portal, add "SignalR App Server" role to your own Azure account +3. Set connection string + ``` + set Azure__SignalR__ConnectionString=Endpoint=https://.service.signalr.net;Type=azure; + ``` +4. Make sure you log into Azure using Azure CLI +5. Build and run the application locally + + ``` + dotnet build + dotnet run + ``` + +> Alternatively you can also use access key based connection string to authenticate with Azure (which may be simpler but less secure than using Entra ID): +> 1. Go to portal and copy connection string from Connection strings tab +> 2. Save it to .NET secret store +> ``` +> dotnet user-secrets set Azure:SignalR:ConnectionString "" +> ``` + +Open multiple windows on http://localhost:5000/, when you paint in one window, others will see the update immediately. + +## Deploy to Azure + +1. To deploy the application to Azure Web App, first package it into a zip file: + + ``` + dotnet build + dotnet publish -c Release + ``` + Then package all files under `bin/Release/net9.0/publish` to a zip file. + +2. Then use the following command to deploy it to Azure Web App: + + ``` + az webapp deployment source config-zip --src -n -g + ``` + +3. Set Azure SignalR Service connection string in the application settings. You can do it through portal or using Azure CLI: + ``` + az webapp config appsettings set --resource-group --name \ + --setting Azure__SignalR__ConnectionString="Endpoint=https://.service.signalr.net;Type=azure;" + ``` + And add "SignalR App Server" role to your web app instance + + > You can also use access key based connection string but it's highly unrecommended + +Now your whiteboard is running in Azure at `https://.azurewebsites.net`. Enjoy! + +## Interact with Large Language Model + +[Model Context Protocol](https://github.com/modelcontextprotocol) (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. With MCP we can expose the painting capability of whiteboard to LLM so it can draw the picture for you! + +![mcp](./mcp.gif) + +[MCPServer](MCPServer/) is a MCP server implementation that exposes hub methods from the whiteboard SignalR hub so LLM can directly operate on the whiteboard. + +To install the MCP server: + +1. Install dependencies + + ``` + npm install + ``` + +2. The MCP server will by default connect to local server (http://localhost:5000). If your whiteboard is not running locally, set the endpoint in `WHITEBOARD_ENDPOINT` environment variable or `.env` file + +3. Configure the MCP server in your LLM app (like Claude Desktop or GitHub Copilot in VS Code): + + ```json + "mcpServers": { + "Whiteboard": { + "command": "node", + "args": [ + "/index.js" + ] + } + } + ``` + + > Change `mcpServers` to `mcp` if you're using VS Code + +4. Start the server if it's not automatically started (like in VS Code) + +5. Now open your favorite LLM app and ask it to paint something on whiteboard, you'll see it paint in real time. \ No newline at end of file diff --git a/samples/Whiteboard/Startup.cs b/samples/Whiteboard/Startup.cs new file mode 100644 index 00000000..20606354 --- /dev/null +++ b/samples/Whiteboard/Startup.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Azure.SignalR.Samples.Whiteboard; + +public class Startup(IConfiguration configuration) +{ + public IConfiguration Configuration { get; } = configuration; + + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.AddMvc(); + services.AddSignalR().AddAzureSignalR(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseRouting(); + app.UseFileServer(); + app.UseEndpoints(routes => + { + routes.MapControllers(); + routes.MapHub("/draw"); + }); + } +} \ No newline at end of file diff --git a/samples/Whiteboard/Whiteboard.csproj b/samples/Whiteboard/Whiteboard.csproj new file mode 100644 index 00000000..cb731ee7 --- /dev/null +++ b/samples/Whiteboard/Whiteboard.csproj @@ -0,0 +1,15 @@ + + + net9.0 + whiteboard + Microsoft.Azure.SignalR.Samples.Whiteboard + + + + + + + + + + diff --git a/samples/Whiteboard/Whiteboard.sln b/samples/Whiteboard/Whiteboard.sln new file mode 100644 index 00000000..85a8562a --- /dev/null +++ b/samples/Whiteboard/Whiteboard.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Whiteboard", "Whiteboard.csproj", "{E4CDAD0A-E491-036F-B3BE-BDF81466BF12}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4CDAD0A-E491-036F-B3BE-BDF81466BF12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4CDAD0A-E491-036F-B3BE-BDF81466BF12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4CDAD0A-E491-036F-B3BE-BDF81466BF12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4CDAD0A-E491-036F-B3BE-BDF81466BF12}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1E3E8FF2-65C4-40E1-A734-AA964A438553} + EndGlobalSection +EndGlobal diff --git a/samples/Whiteboard/appsettings.json b/samples/Whiteboard/appsettings.json new file mode 100644 index 00000000..26bb0ac7 --- /dev/null +++ b/samples/Whiteboard/appsettings.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } +} diff --git a/samples/Whiteboard/mcp.gif b/samples/Whiteboard/mcp.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f768cc0f8e4b0e24c3b44e98420646ee55456fe GIT binary patch literal 994556 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�oEB=>&1W&~`Df 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%0D&i_UK&-*C(T9iVint zbO!OP9`Q0hV-sKF`hIaN&vGr_axU-kJdSa6TWG5=XecmX5h!!4SOO3jaty81Bu}v> zx9um-?f0JYuJ&y!2W~Ilb3X5LKmT*J2J;UP^OzuWGlzm!n1LE-fkSE+Hb2oKe{(jA z^AA^NBj^Dh*a1!7bWZPdPw#Xd=mA%VV=X9kQ$KZ7Pjyvabyjb6SATU_k9Ap}by}}= zTfcQ&&vjkjbzbjvU;lMr4|ZW6c49B~S_ktPhXNaSge@qv9k1>gkQ)`4fq{i|EB==B zNvG{BfWUKRNGSIKA83VD*y<98=lQ+9~D5SLD_aar+mPfCT?{@a?fmRT4 za;Nf>&+~03%q0FaW1nGN>_ht~G=s0_$jd zQ_u@*7vHem1Z(R?Xyg9khV{d3AE8w5%MU$Mv;A?9T@|R^6{tN8SDrHNxL_`xZ|qlw zA&4@a_tS$<`2ciOv&-w(DB02@iNfyD#7s@mE;j{{qY!5QEn{5-mMVYJ2^pS zpz^x7qmXb|X%n~L_Y?5>Q5uu9`Cz?J?aeeM?Fb;?c0r;tA?pgEc#|xaWkTNbg+|H7 zjLeimJlY5}-Dy`MAOQF1nFB;zkq*pY0*_AjE`%x7NV-G$VL0 z1|9HurZ_^P(%7*aElWHi74{LJKfx5n(q*EtXFJ;-FED)GH}*`XNWCxlea|?xLY0Bt z?qSlrFzQT|`APliWA?l2^MjQEB|28eC?h+ji%>)(o{R)%Sdz#@mnrQse4Y6`ta#nk zHVXm}s>NAS8%kd3#k^u|pXPfGf?AhJR!q2}M4xBHlO%$7XB9AL;1ESHCPP(`DFN)q zaFG@n<{7wFdH%35)?5mdk{;}>E<&~?o0v*om{NsK;U7aJRYgg4v?sl(&au-Y)jVKG z{qlMx`4Oo{Y5AYsE{UYanhwim2ymN3Ok3u9U&vV(6MH9lRJ5U!d*K~Dm^q=CM0osiP0*XB z`)vv}C+?O=sDboWS}MA{USK@Q3}I$F{Y-9&OBC*EJUZ4@hCB9h+EQ)}e)WU={@rbm zUtzeMvvasIm-HHhtOR57vvnG${ge++w|gTnpQCNnB91;D;{3R-`=b8CHQP|VtV5PT z!;u%yLGpG!`)X6&R|~=#bXA3SzMjQ zXNo42Ts?{=8L1J=r!*b!=-l|vUo8bcN*2!SECnyX^@MoK6__H^c3_T!mJED$4e z#q*iCocZPPnyZ1bTSTK;^gTAJ)(<3p%d6Fo@)%RMxb7_1FfncidxH2CY6jBYDcOrA z22xj_&6pl6Z;kluGUXVx>dQaRe>R#Y6!I>J1iF5ji)MWapj#^plSSmWOcgl!xF|qm2saU$95|yvkv#CFj5~18)z7K^ z5>gD!SACZLxe9&qA<9L;H1w{(T{rH*wlGfyD+;_4243Vev5+^IueQr$B5Y6`T^aUz zvMy52L_TFArH5d5z&l0~!YAYI+z|9ZE_h_bh}xa}z^YUq1v1jdTb;su^dTX!WaQ7Z zyI!l(hepqmJz?MKdLxAHjgyPjCFdSNuK&!w@bMDCl~k?h8jbRK&F~0lgKudJ$%-5S zuf^o7LUd%#EgM|y+e1y445?EJl&@X`1@6#f#;$e1Pi>FK+e?NN2& z_Y_iXic)mzZ%5q?-_xgQE9&`-1ajy^R-91D_8?#;<}bn&S@CgSg`zmJq^mH{W>1ny zx@K{`EU=k-rgWpz??4Om0(=Ed+or@yXEG%yzzFN)_I7iIuesTkQ+U> ztKpRWf%1}p_3Y3|?Q?NpyJ{{0eI}3g-S+fEGgEnSxHlKNksJLeu&hE$5a+xJj8s{S zkWR*33~-_sZ4ioIjVkL=+CJ*Bd07%0M`Qk#WO%>>gZ1zb>{(DU2o)PGf?~@H48p<} zZ#?@;z6g$?wLJUGMKg2#@ym=)pXuix4Zeq9tiH2g`p+HBk$$<%sT!;AugJ0Y<|CLJVYmkp|PX+Q=8YkbRc%-1wQVfG28P+Md4B$tXnh}jzK?+mnBnu%<~Kh zHymn?VLS+LGr{1o(I9!57b&~CJ(IPM1BtPxcok?5<81~JKokRlO#`24g;a(hpSiM) zQf_H}shC|uB38|#4OTa@7#5E$e3FcUwggA~49p?oY+7Kcv^E_cH^*-TLWZUWpH zSm_B)t0l-m;{>MOKvWyA%J`N5UzZhw*`%uA9&2g zx5YkMaS%<@JC}*6@98S{sN-XKLFWe+f6|_)nP{M3YC<$H3JIxzq4`kmr;-{dG|)N? zydXuk{}7UxwxTQA!Nlwly&JJs(kuyKmEf(lt1RWxlRP6nc}z$R!j=_?yhTqWub6om zM7)K7MbG4o=MNp>k|@pzE}MJ}PE#UGJK!WMIanHZkwLYuAlA-`GH#Phg?AyB?~*EU z`jw3dOI0!H<|-@dsu5%^mEj`bSi5HC&rNl4GCQ>sNN=5I9iZ?x8J*2zbm*kxzN*m~KIJ)D;e|NqP^`axMx|guv-@BYLAUQa2H-&OAtVyqGzQrR6BcJoF=tFOL6A4}*Uw|> zcZ3;jYRon(%yP;+U|_^o zP~b>lU%{RWf>}U-gJFPWfPsO5gM&jrKtMu5LP0@6Lqo&Bz`(-7!ok78!^0yWARrG$v7fB5j> zR#sL~QBhS@RZ~+_S6Bc1`Ll+GhNh;bmX?;bwziIrj;^k*o}Qk*zP^EhfuW(Hk&%(H zv9XDXiK(fnnVFfnxw(afg{7sXm6esXwY80njjgS%ot>S%y}g5jgQKIPlarIPv$Knf zi>s@vo12@vySs;nho`5fmzS5fx3`avkFT$lT%VsQd3jY z($dn?(=#$MGBY!?va+(XvvYECa&vR@^78WY^9u?J3JVL1ii(Phi%UvMN=r-2%F4>i z%PT4>Dl03is;a81fw!mE)YjJ4)z#J4*EcjYG&VLiH8r)jxApgTkB#-u&5f?EPHt_@ z9vm#3o-SWptX^HM-`s56-ED$Ee|f&W<>dD`J0Q>j2y_AhU4TGWAkYm6bPEFAeLtXI zdcJ=BO5aBhhYWTHk5`$W$mgjL5F;*A284F6IrcUKf(h*3+?<1CJoZ1yi`7T?5s*tQFf>y2DZp$RS zFNVdGi*d7HgF6Ay76FqjIJ4iAM~Q+{ZfLVf&&)z(P9=A3AWZ^V<5M>V*+f2Ji3!Ft zw5KJ-97K03-r>OZQe{C0e|C#~!Q!vID7_S(vQ9}KJ)6g#V$(=AInPiSumdx$?E$dY zWTH4mtKFdwUQqZ=<*D?AfWPp#oupgojA6C($gw0!Rn_B$<&wGD)*FOka3m0ud8s~= zqJ4m(IC-JhUtw9mHD6<4uvQ)V`jIXho5nI{A4(pyZMEi9ls|~H)IqMqdN#$^_t74s z_SHrwKV%2u^{w4$V9W`ZAuD@ai5#!0m|nTmqj-aKcuNKAy&_K~^LV zM9JuIZi2*7q09prwf!=5*^jAML@AKL;Ul@(Cb=+fa3$sjxvK2;ql7OLb>>MfLSMR8 zd?m%pTt7InUSL_JCQ&3vDecK<`ggvx!uL}q=~C0NH1J-DZvU*69_;2oh5O136KBg) z`HDqbJY3EuES-MoW!8H$&TFcSXGd35ypi$Q+u7Oa-P<`(h0Pdff4UYW0O9ZzoaVp6 z;hz%@`kFdM>UySX`sOMImdb|KN=7zHMz%`Ec1k98%BI$8R_2-xCOR%U`aW95fuGGn zG_1lj9HI=ILXDln%v{4P-9zm>L!7;XJ$wWIQX1T=gL{DhXoP#204Rk&djR1O9TAcc z6_^t3ml^Aw8|P7&;98pKT#@8ZlVVq&YSWZv)tYY6o?+INY0{Hr+?Q=MkZmxOqd%Oh zH=3(AmZv+Or#q3SGm)<|37i6*sRCW#Ocv-(7V1wH8cY@%O%xiB7nzP1nU57)jTPIB zme`M!IuDn*50`rlRrn271`kw!>92|DuS@E0$mng#>uo9RX{+h!Z0YXq?*0Ds_4W1l z_YVvV3=R$s4Gj$s508wDjE;_ujg5_uk52&4)bzyk?8MCc#O&h4+|uOy^5nwG%+lJz z>gMX^_U7*H-of7S@&3ix!PUj#_2tpc)zR(s@$JpY-OcIU?b+QOAQ>)y`J8{hYJn^G z{s7nR`PZ+P_t)ax-Q!Etzj`fVGwA%d7VRj55}Sg*U5j1CY2UBK*r~$R#!yDn?b)u9 zjDZ9mSDI2;$;_b?kQyIwq z)Ki`}ZExbTcL+I_H&v+2hW2x>) z2Hky~s{QqWM1I)4=hdZKBlIK5ihb2*LSy-AJ@I*HOnWnxA7}deYAV*}>Rk~DC2A{= zRysqUDfQP@ooo!IyiSm)t3KPAEYV%)udBH@SZwL_C45s~dv&rolA|T_cx_rOTUJh`zF&Z!OuF0S;u(IWErl{YslBNRNf=t{9 zk&h_@Lb#c#Wb7f9GrJzpKQ)t}a0%L6{bCbNO3XWvDdow4OtJbVN+DhQBdsl*I?`k7 z)r|Gn(6VJ=IwL=kjria_$c_it$5dKsYl*T_Jb$|1-U0U;?4M*Gp!|O60n#Sm`H?x@ zr%gc41SCvAwglu!K#~MxNI-h@Z%d56%RX*E@cls&BV#>nGkq;<0}WF{eM2Kt9b+3E z6I)$VI|DOYV{_|&J~0aR^9c8MjSO&!3v`GMa*GW1`w|l77m^Sb784#G^{+^b@{7yU zOB$j|yEDofYs>T6D^i;(bN@zS)ZEA2vJw3n; z_pA5Ylq|_4Uoo&F$^&-5rnv{gvlFGXhei`*Q~ZbR=*G0yiOW-Ch5b7>R-b_Zv&06OYSR zBoZ;JphP}5RD34jb0JJf^& zg~%TXrDm2a_q&0E{|PTy058Pfgx5WG_k`U;cJEC9#suI>0E7W%1V9*IKmhK;|F^z_ zvA&MIv4)4Ks;{|SYn`W%0$;BFfe> z#=8U;%yu01l9w0X_uaXKaH&`=Glc(DgY8$lwk^pxy7k2J8>ukNaQ0o_v!J zpTXwt9*YDef;&Sa5{PA@5w|!Z67rdK(k}D+V(N0@vh)PkI+l>(Oj>HqbIba!ucf5) z@zk?SpA)-Ky_;_eDkEDPWeLVjk)O8fA7(OEiVJ)8PJ*NAL25@DIvqvWv?R%>?@#2x zee*Na0P>*z4)T8R_an#w`~k+`eS`zdK)?q45#Ijm`2GLp`28w*|4d+8Utd2sI5;~y zySlpi8)59PM7F>AtDgcJ0T9@3EP04{U7=wqI5N?aT0GEjL={AimIQoZAt3$~tTX^* z;C>w$0FWPy00!Zo2|*xC0i*zKIS{G-4JJ7UD=QZp8z2OQI5>DX_&7PmxVQxVm?pWY zKH!o6&L+7pV3NE3`%LnRlA@Z@{Hn6z-(r&gUC8tejrI;t^o~sSk4}z`jm(VqO;3#c zk``Q8S)E_sT-#jV-CjM|T{$|~Iyu@0@VU6S00{b3IS4=l2tgox-G2KHq`1J>pPrwP zdGk#RihR?8kjQ`*L<9EZ-D^Q&Rswbl;C;J6A1WQk?Ph%=4~9e>uW0wtWQh`D1IdL$ zLQPT0UOSf3v(e)OFY^UpI)iqjXoHjw@{kIVH`xT=8F2??a~C}1003b)m6YYI6XZD41@cm=6~+||A6m5g(diJwOf%w z;i8kZ^K+*Q|&IX`p`)9SjoEChGe*fCItRY23}EqR#`ztRbg5~QDSRxTz5(2V3FTsk;`1M{baH0P-$RK zMSOc@MoU$GeN9E}UvxJ7T>%9UZJonY?IW{YqccNellKLRUkWITi;GK3OF&pzSy=&K z1k5}jzHDr40G8g?*4EDU=HAZ6-tHCv>HhvckPZP3-_g<0@$oU>^8wfb@(ytO0EGwe z`$Od2-JJv44JcK7a~K4^)om{ez?z(4P_d*dB~_f|f>5~pM2wOJyh<&0BR>?5w>y>* zT$NlJ#>E0}^ge#=7P8#^<*96lU6dqAOEjk8JQCcWz_J3sLi_b>=!aeY^R(z+YTW_- zLO+^?n3*}*ShzV@x%gRGU$L@Eu(3(8v3+1?S7B%W%)z0;!6D7bDZ$PCiihX_$(A8M zFSjU9vm7s#avzz7fDi4VGQH7C-Eo=~u~v~$K{ny(@*#ENK^?CHyCehKl>=+7gY$yI z6QiQy{;`&!?1JLV!t(T@>a^n8)RKnOlE&21ru4GrjPmB}il)5E#-gf*^6I+3+A{Q8 zzyjWrUE4oX(7%#4uoE|U6g_knJ$xQFa+WrBTsFSlF|iE9v8AcLt;zcRiTvZqjMK@q z%h~M9#iEO~>dW2stK-qDv$^ZbwcD%ByPKW6+k?A1fQ=vBK|cjLzzqkW`EmY6+t5#8 z$MilMQs#w(Kz@qnWdzJmpdj-BV3D*rVo_=MdC@AMK4wZqHWScKWPXj^aYkt!AoVJQ zLJHT(jeeaw@~ecZ8<~l6rP!&_cC0MJ6VW7k&SJBxz;*6$`a5eV+2bwY$8*VwxsgUY zLY_*57Ij)g_Zido#w1UGLzv&n;m;wwZ(jPjg?C@1`gdCB?CiWhy7&H2u7sYUsg{wg znz4(jiMzU~o35F|KUtv)^l=aMbBXYGiuQMi4R8P|RB=I$5y74zA^!d$VQ!&uj$x@T z;VC{}5(6UQL!;vU`PRMM!qV*G%FL3Q%#ymy()zrz>XP#En)3Yiij>~U_@2t-w(7j5 zn$pI)s-L&+{T2@IEAS&jz2n2()5GnvBW<&zozr9eQ{%%x0sfZ)+>Z*?&dv@H!hpzi zZ%O=ZKLX$oC`ADUse4TSsu=x=L-ubRUJd}R1PnYD2MaARp9dl)o8BhsZ~%TO(rUJw zQFN>|hUwnrrcnxiAnuFfNM^caes45+T)3abHNXF4!T61)Z+h_$+6rrKtZ!?mXKiR` zVf?$b!iM;Jg$KAt2f9QAc?S9ixrD^~heqD_xcrMMzIi28S*7&_W!2^7rHvK2wUs5m zW5u_Bc&vY9VsLcgM@P%A^0cwNv%b5(dvN#zsUHIH*W7XdD!|{n0U-PN^Ak@JzvS{Q zH3+j?3|?y7 zeF3n6{}pWh5*48Sbl)R!Ps@)+q<`;_20uHyC?}`DA2u>s8ta+pn_K+e^(SCRBRtUS z-!`OCQBqJ}npss=SW;g3t3w)pFE(St0}~_t6QhIOW3#`-$^c9Zz`j`D+F9G(-`+ns zI@ksf0-TD!Y)bmG_KBZE14JgEmEwDR`YA|#vohX;eZ9I7E+hh)C4l=FN;Od1D=5GSYLACokFBQpzQeJc}vOH)HLGrQk$94aEfEi=$4 zD#+b8IQ-u*4pmT6mQvbOSXS}7S9f3f@Q@H74fb1Gk_zxfG-56@8A(+^$3QL4;ii>%UO$e` zJ6nt`wRY!`%~^J<;{=xQ=i112Rp=>V5w!aKyHe6|y)R|)val-K;7=AJ~`eF640>lSY28ms4;s^*%b;8y&>ty0pX?zMM|uwREjK#xFBzfkbN>(D`&hynGO0o{at z!;}Hjv_9+fc9)bI-=w0Dgv_Y;q`0`hHKd!FmYJQFU67JqniN+T7tk8x&=X@i6sJ8J zr!kT6c{WXRC0}o&$Y`^~WUJI{yV7c>)?u&7eXrGLr#)!1J#4uxda@;@zbU`Dq56JE z_gD2_SN~wkz(mc^e97=y?(k05*kSh6asJFn(cE$Q++p?He#`9U=*;ZG?D*3B*xKUo z&Pwm$ddK-z^Yu>M?QYH8ZuQ+k!|iFu&Begw<;3a5;_ms@`q}>c>Dlzf)x_29*ez)6 z?%Nr^15Mt67H&c7x1jyI+f&fZIq3QtbaDGl``r)P06%;i3skvQ`5+5Y??y5w^8xZBFEvc{ju#KQL-Np=l?{#33)9ZyCTNz~cw3H_w}f9(11(AEOb zBL606|1x#E_vY{0+kfP3|GEJZ09v43kd>7KXc%N;6JTc-W@ne+-~jTrS6p1e+}wiy zHfVp#WWAn|xu&tbx{0f{se_T3^*<~n{k>d6e4M`c+Q<1>rupdRc`BB9ysz=FPn8-b;fK`730;Ws=RSEnBINyZjPf}9r zK50vAf&j{7x1L6e%`V7!KKfyPc99kV?%Hm z3}!brv6{3?)j=s#Z&UH&ZYaIkCyi6OA|BpJ)$krGrN&o~dm;FTe9Y zGmirR1PWv9?Bbl9{C~_m?tZO>k;(7S`~j@B0BU2Ae)jSHmMH;dSpfz`{;JjfABuxC z(t|DIL);?60)R=?-_gs@DJaP*sz@oWPb_JPF75nM+8bOs8eQIb(IR>xBmWsUg?64)qf$`sz zRFiT+BmB8zG6;}{`kTVsy+Zw^VE6l4`oMY&U}Fpm3mYpdCo3yA8!In6D=!xtj}RLt z&<7&J#-_-|_L-es`}@)4;85e_l;`4-=H?dV<^6ZJS$)>hQP1^L6J;tNVWb*jpyO+3;%;Q^Xy#yPXh1OoZO|8I-->^sh2ZrUcBgBzwO<&AKY~q-MO08I#^p<(pH@@SQ$G|72jW- z++Ca9R$ulTwdr4y2F!sEk5BYZ&vz_twyf+ouO79m9(Jy54=pZDFO09vckIvAoXwY9 zEfrm_l-z7o-t5%h9Ch8EkKSF)fNoboclVQ8z-$&Up#_M}DB(=@ zeS3Z)&HP@Q5`FIm0m57o&<%pf=f`41BIx^oj!l3vz!M3l1m?>LT*#7${MXSwUU-zW zN~TGqT^B(#JaL!p{nlAblf+8S6KRLsqLX#*n5R-@F~R)oWZx%Y>% zj8!H);i>46Y=iaM?;9S!3(k3f#Q&&%5Ka~rK2}yCHZ~EUMgSZRj#r$V!dzT}+}wWz z!D*cWP?CSr;IUve8FxoXJ z+A}!HFC^k$w#q5LxHzw*&Z}xEtZpf-X|Akm{Kxu1 z{(<7!!usaq*8bSe$=v?Q_R&wS6;lDnAjQ`IvW{z8XNl?nM9fD`I?%#nwi=BXKqCU3T_Rh8Kq?<1?5#G z6;*$GE84FbE`Ju(eiYn(wG{;D9iCranO)l&-#qBpIv?9Tnch2DI5^!rIz2r7)))L| zTL69(1MYhrzsEJ;%Y7~2e)1n+3cwBc&D}S{MH=jD*Iy~PT^cUnnLL1(YZWn0;g@5# zn5?!kl6!3PRqLp+Qi`J3JMh#_8~kx79s*R5+W`#52)|?F|HQ_j{!RX|>9M>td`WA}^umn!g$?s_CnhR)CJJw6$`B697#@lQL8?S? zx;QE3i1)l9Z^is2KX|`UcK)Dar)*@cZDyryZmMacrSAAq(OXb9^rd1Vfl5A>YRTiz zW#oF5G-kC7cFioVo$Q`HoWA|s{zE)L!@?oMZ^DPABZlQ;#y%%a>SxRwXU?h_Q@YXw6&Mj2aDq7z- z(bO=_&M?DXE7M*h(^@gt@_mt&M5&c%rL|D4jXm-{_auBMB-K z={j>c25Ut|TP4QZrKa2E=37;E+cnPHb?!S2o|}!{2W>vboq=b)VaEgU8~xeS164gk zosFZ@#p7F9<45shH<2SZQDdN(aZvIMD02~%w|ZB!aa+1|SH5*ywRKms1*+S+ZQ8!> z*uEUuIi24*THo2<+S%Rxwwwa!UI!{wzyW%efb*@5{r&-xo`ciVo%8dxtE+{(yBQE@ z3Iv)2fu=#Ah40rrFia0fG+;RK-Vp>W2H-RL&1Lx4KX-S43j$310~3_MhzxKpZoe%I zI=Q<8Lek#%{|g9Az&{8~_5T<&`#y|Q~eFJ@5|Lh3KRclxta<;$&ck~-?s<_cRuk1maE~tD*kD?8n8vEQw3PA z7W=B?`*Jm4i;(H0a0HJl0={S|uti9~7T6+Gn)NP0q5S55t^xh8|sdmk*1ynwg_$Gi&hjU#adh-5QtSCHZ^!XQ>{X zq&IG2RDztX*U~U-rZk|=aptnV?;-!gbt<=bk=1ZdMQ6_}VIte>vD0{2uz9xxhrLxz zCGp#q9ed8;2r_t0!vlC2J7Tms>TjFethx zQojng$P^1!bgH0Wcn|}Hb1XVz)^lzOIpJt?4!BTXkWst}bi}7w)vd_q7OZQw9)&Do zwmAfr+3D^Mnw^$y;Vg?e_2!uEG=aVVm}?^DAP`)u>T zZ{ubM$BTB$7p#Ix@(dYJq_=|?j<$266><3l8@lr{a`GFVc5LN9)pu;!v^3(rvpXU1 zOS5AZWZ!cb*TBOn=jSWV%QUrkM2qPmB1&&a(%y)lwwbJFPzQ1LPPay=I}_a3z~p0k zU0+g6vIG6Xv5~2j%v-bYov7DFw$od7C)5woS=GdNnf*1q$s~~8xnr$+Zg}A7JTHGw zjFP(3k{+bCf0V0{N8eZJo+q71_jy>6 zM&Bq-dixP!3k?C1@i_Xx%u5g4x9sN|Qs9@Q2n$JlrAbEXjg+Q-iH#tZ0 z!wea0$`DB(>0V$AfaURX9bm)qQnFqxTswV;AfA?33hqQ_J5%+MzmZ=G-iC;i!wOa%b4qotOK`!i)M_V6J0{L zEGfWn=H$f~<^)AH*n~UX=<#^A5k?PmsX^jq-S4n3_<)tR33r&*i*XSQ8i&#uZ*dXk zF-sV-o)-UO^rZoxWkC#^#wK2PHZRTPMW~lv&dB3DZ@okrky8pYMW@hFBvY4Qw3PV? zVCcL)Evv*+Yw_Y*X%911sytZK@^W%x3}LG@OcUYsVnL_#Vu}Svb%uj_F=ph7RmlU5 zXw`(IB?-waG796hn8D{Ehn~`oNWR|5j}apJ>OGN5`bqBwu0aq4R^=izeI&1>X@pK>+nMPrfcskj~ zC0$U&R5A@3ozVK%0w23=q0=LPnu#R9Ac&*F2`Lk$bd}hvsb`%aWi#7?0)oWR7@KuC z<(`xA(!pgFC&5^UJ0r?9LOf<6f}pZ;M%3YPWnWxEMuBeQod)+Lq9wubMMHz5afZXl z#U!i}cPB_4g+-Ah#xQ|{c;fLI^>HCwy>w7Pn4THb8>D2YKx}k4f(Jg#aL!nVR<7uY zDYL@#mZ(-*uE+{#kSM~BVCWWekc6JYau|K6g<%zdr=UXv7jLpKl4<6?1>+b#bAIb_ znIJX8LxnpLXvQR3=E#3|#IcMcBU@nY4yieXCg*xt z+2-a>=Zoi+Li+k?mH8qV2nL;lEaObe<`{R-s4K0mmF6lqTXJ3Dow5rIoKyFE7&9ai zFy}s)b0SuaqS@wLe5^BGxROkafFV0KPCufzfdQpcIuSK3Ya5SezEcLjP^gwk?FQPJ!f=@2+0*x?SeJz!w$}k^T?sh0-1xZGU zhPUItX4ieRKyh&zxYAJZcsSw7U+KeS|>9r?&6zr0x z-{vjEp(@o!3nEWxo_-@Nz8D-hu0BJOB=$;QVrY611PPp6oi8$!gPYkQRme_=o^ii@_JxGB>X@w&_C=qk3w9%idjQ|{H3eRGmt57IjOxdrDxekXH7Lv zCz%&|D@>ojm`PMU%^0|yDG}evcu}ADK!dZy4||oprII#cVMu0i67klMabv#p{^G=( zw(KFt;sj6W!@ES;t>N=UixRSuO>2-%BFboEUL4n|6{fJzr$ zWoT{}4k=2%#t!=iVXEPG>|+n9Ce(appSbl?Vsy6A3rBM8n37SF23lrzRT9m*0F%2pN1F%`;n70QDX#>W~aAR8uR9VQYLCR!CHHWemu6()%j z{+2adS~fhz^I>c1tJu|7iDaTrvoO-kL={*OQVy*W(O&m=Vnj&4PEJHHxcXv*gOJc@ znH_-{R*H})iC|O}VJM4`NF-jNi509aW+xkIcomWBi4{nOlBgURkcE)Q6Y&wA0Gjt< z18qK)&R2sELa|(i%fD@XeLPO5x^Mi`AwTAm-gsQj*Z*vHDQ3$C$2(2v% zze6Ph%WK422p1m&rx@fss;wbxB0aE?41EMkHVEyT2xpzBMPi(I3!kENn#k2n@3M;V24~p^H!{ z4^^RqQJI~qH?Z$9X^@q$o#%5}n|< z8)0My;k}h%8sQ^SoK&Gz;7FZPl+*D%oge~L$IOEg5p)X5kxzL zhE5n%)P1j%ZKDitp>E^>OVkLLP76y^2)|AXE3^pzUQQ_aDuX9F&Pi0nMJLkp5HdCq zMlJ|OJ~7_*DiikT^Ev;AXWJTYMzR#ImE%RxEF{&TRk9(RVS_X@R?E2C*Xih$(+|Uy z@1{~FwI4P|$9Q5OWWh&tiN?OCh4WL6JonN1%7B#31IMYFS4K)oB$?uq2xpjR|8*se zj_(6x5v-$#dNX+j@Opq^1og;jt;voQX|jUW?Fr$wa+57%yE`BMCjT78cI%mQf7S9P9 z(KaQkI=hOT^qf4K)G6U{3~8xOjwuh76&h4bBH|&!m#3`{y-H&YwGlKM;dGQ^4X$8i zo!}l-M|4J^eZ@)SHG&8e_j538~~6qce9oX;p5qznm$UF`6*ctX3_Uq08#Of=XRmIuTGZF>dF1_oWk z8skxv<*`~@2VUoq8WpG=IlPU%C@->nQyak=-J~NTZCh{48WC7j?>1Ub{yO?dwBAD? z^7Q6Q!l6azt76id+Lr7FH@AqGtH?mnMrgbSSdJ#R=S?$Py0KmH=@|{^dQC&m>fBB< z)nvcKlVxUgG^KAfA=rudSA+*WLFsxG15?{@s~ZQ>4JS5hsWXi_y>4Pb;%D1M(yODq zNZM8yZ7UUyL=G)r5>}?rckgY7r(b756M|16f|3|oS|M~ISO?V76DuS5zNIImSKRdP zV0o2koRb-ICLP5gAzURpBWoWuG+Hhc!Uf*ic`lO+pfk>}(8jKl6Jq44{E{YW%RbhJ^$cv1gTpA)wi#Zx`3A7?!cPJHn(dXwhr>Ioa&3O95Q} zk{@nw6QrRR%&DFWWN2Tz80nsv*9ojn_z2z>_CO?Y;J_=2?A!qn3#dDVXIt-j_R$F; z#Rp%6xnpn&SlSIS2~bpL3=!N75#bM$a1N8rS%+;k(Hwyi8Dk$k$r~2-4sTK+pqxXe z*&8NhY(*$0V)_(Di`>At%g&CB9vRi#GL7~+c9VgU2QG$CZ&s0(@h5J`pVj zPaNBfp6HB%dM2pr#*cK{n7hVEawn{22FgnB3R>(HF+N1g47%;s8O$WBG}P4aR~ zvE@z0>qoIIjWEYedB%;V&rN>W3z3;>%0R~ZNFCi5^O&D{GJh^Zd9KojbEbH1x-xD? z4>>ePd^C=8)}U@U(SG`M-0U;_37NRb&vm1*b2Hqax>>fVh6GGTkR*lermzsTEx1YLI*8Y+Ao%h&#_juCe6*T;Lq%d zkJTT|qZt&lAB_y=%!9lzO0TJh^T z_3L``>jt28qxuG8MGSS6sR{dywzxP`u5l2r!$>*KyhHs4uk+%Q`pKHO6_5C(3+hd( z2f3c0%?|N`*tk*l+8OrVO$wE*yic3d_FJ%Gs}B^5BjdMF2$rb(x6-aw9vW<$b8TbV zZ6D{2#M5khD{epE-)6NZ2+v!>h}l-+B3byQzK~JAR`@0zD73 z>o>G9%!SRMus0dMH(kFsJHIy%+FK;pU*_6hRoq{9*x!ub->%=^o!{RF?H>{x9CIC< zDju9W99$~y@+3{YSJ@J2T3zDZ(??rj5Zw1qwY& z!%}Gc+%5iAwf`=4;L>xHnG^lx>8(wXg6N8iXfRh`}NqEo>enN|{_!!35 z)A+ibw+m-vgu877TS|mS?fVCxxX*3%=N$VE7#DVBzitZ*Y#An;%R6oT# zE6%Uk6l|gv97rpjf92fyT(IMlaO!2sIW^VhLoH=apsb{m}XqwcB{ES2oFBotgG zzSzwxxbDC|gMU-M_jsqg|GEM6=D6U+trg*=gu?`@;h|2#QMlukM#8DC|1RpmO&ra5 z@4$i*_ia?*N~a_LkmIf!H^@5S(yrmsf_uk2@N%T#;(DNEpYXO(;w#vZ;UteU6g-HZ z1;|U?5gu@HU>7Cvx??<{ar2@hZTG=@ffXx*wkqO@%4>l!C6)5(3-zaZH=K9tV$m=4 z=^3+*)w=vqq~gOU(J5P81zuq7Z564C#tVevrcDk%5siBtYSVl5j$ASa>mv+i_WNDw zEa@5_WLqrl=^%N-diTd4_Z6zmji=k5RcI^L8(*A5+nMSsH@hPf3iX;8E!X?vJhr&S zJ{Ii?r&juchf|{57Xy@6P8BLmwT9Eg6NKXA&UF6w3pL~9FAV1E?7zYgC|nvXxA_w$ zut$@99=82DFNnhVtT($CN8XQ1zN&BUv3q>H&ZnZwo`DQVi`miJp0n8oi-7}))R!DqSj&ECA-*)#C`@J~v&vruv# zZ;`>(RqJHt_PfvuDP`RObkB#*td$>tU-}MXg zhS5rro2D{Q(;nzyw6Z=%Lg#;QWR@?=`Qqh}qzH5GNcU^QGGqSp#^KW5l|r)+DKa|y z<8f*4)6&i}t3I<=!hMitQiypaQi3dL&*(oq(0nf`B_DoFqwuNDytM0;8pL?Lnfd#P zeziXGQXVZucj@RY7-gwobps!UKi$$%SmXThqlT*;nrkhu>Uaecu0K=|V)Im|BS27?p z^D;Im-*4|0NrK&AY_?xk=gMc^{9{c^c#UDrCP?q#?r{CBVKVdu`w?l;>gj9Zx-erw zpSkFAfpp&V*;P^2{K?ghsQ7W|cbErJV%&WYC-1DeBV^vosRZ;6+e5m~$zruhpUL~Y z3;bf1imCBI+1hhezE80TAMtavji7P0#f$n+lNsn-*3C?s=XK2Ovi_y7CBv!XCoP`! zn&#@Ge&&+jQ0gd?RpXVgQs3dN;jo>H)T6gLV8@b{9eJ6Lm(bXe=l@FBs*CSk5{L+z z+kOp^4WTvu&fp>SzPFC!3fovj;%ZTE8j9i^DSBh)##69)2`T*5m{JHB*5+4*teC#i zF_p}0z1|0kSkIN<2F#K-KJUH@G?nb35qR$Aoo{d6oPZdvh1*CyFOpZ7f3cUxxfN1=MiIDutNJhx`rQ)bQ3=gxSW20xVnA2+k^n zxz2|I9ih~Tpjk!uu!e&?1=LAUKN3SAk@&N3!3#togiKR`BP`%##S$5~%f^^<)Btr;^Z% z8rCVq(y%`&#y-oDSLuGwz^=)rFudc^AeKCyn9&3U5gImjx?b0wMsCI18wJDo2>PpV zgJzQZXVTcEZJmgI{PQizB|D8)qD=8l=m%a?I+)D_R&1pEU3M5GN_5mh)Mrwt7F1!e zrPFF}w&5is>-A!Lyr%k2gY|SvV+pozH_}d!rDaBX)8zU|TZprFRThE?vS=b%VOSZ` z2-P;S*~-NrXhQANSLL{KI)<&vN@ImvGdMnKQakl;@`M`JRxte zG(n6uR8_evW@5E4K6QL%zR6bS`Of|dF?{JEC92?L^?8+H!kwwY^Ew<5m+gnwHe7xi zwgQ_kqXSHnLPK?Bf^`Pv+-Zu?@Z)nrgu7F>jZA69p36ep4j&Y~aBYT~;C*dg*y@cg zTx>l3)KqPnzxZ6gh%QLS`2Vo?)p1$n+t&sN28xO;wt|X?io^p*cMDP?peWs4N_U5} zgmiaEcXxMps7Tkt`^7VJ?sGBj{oOk=@66oie9m>ynSbUpcb&cWT6?cG+{Msz@>w#M zgL3V)r_4)j8TpthYL-;uLnqra%X6fBl7@zR8x%90QDmc&M(G3|8@ zV_6+xohGD#zE+U>4gP{WLG_{pBoywIiS^7JQuI-|&)WoG%B#_6pRCKf!gFc2&wI#n%du4_h?krHl+1Ga3^AIuN3-`*q zb1HS^mT||#1~NuG&zzBCzEPta$A!25Wroi(y7n!c?$GGrN@wW?N{ z{-e~gi1yAp-7?L9#T?m3%boSc`?P{EY2+AAbv0PCXuUs?E5}0K)#z-c6?&aUo!H#eKyjolhq{MZ_c!q4%a zbDrf^5b2wbQ&oJ9OQ4?;#60Hah|_XM-kZsxIh8fnE@8aV$@A>P=a%hj$%Dt> zFDxv#>9vZg7uOSFcSav&V`Ma6DK4>;RGinOdQ6Ar*vTPRwdK6CES(-Fm?YTn4}Riq zHw@atOq6udO4-a@EiVWsGxtb$_89ZI$mR=NMfG-h$H#ONR^I87P@Vm9=&66po^ie1 z5&o4gg%eWxrSFZOrVY4wUu^?kNxH5xjRuUAIiH|K0^G;*C*ze>38i&weP z*u#ANI^DkcK&;mj%(MngUdX4f~e+ zmh-XRe72-D8ama#QqKD3%iDaTG4lS^dh0g}VYIKOg!|Xp%ik=e<-h)@+rQqAWxP^K z`{s*R|He40@mg#Co288Y%}>_G8>6(wYwi8W<#J=>V!knQxqoX5t6&#i!R~7Xdq@lR zG8JG57GS;6Q4@!IFYQEd@9u1&0?3j$jnx;?WQ7*+t>|kl}VA zIiirBlb&3Ro?fw#%%G6Yo}SE?o-T&oQ_7mO!os*>?`<1f>WSUAPg@WrTGH<-n!0a$ zB^9$xC7*DHszwgCOpK*)KSDqWP`6| zVM@sOxTomac?-^k5}IqwtVS4?6?<7%tnp`YmFp zrXmYWeEwyoL8XctC43&3fi5M_EB3ODu-s2&k=n3Ut}%Pcge}Wtqt?Q}U&F*H&TzYd z;c6`FqaGH0@p9H!MltHrL8KUyI|as7qA~%DatR_vy9R3-i!x&qhQ~~$rm2>sL1pfA z#k?3rBs278bd1(U7|+jRvoElTwlI_Gv6xd}T=KUj)hn}1wPeI)=EY-tOwE4nTB(Q! zn^OzRUAj_w8#ex&O3fM!oAdi@U)reFm>X}GXK_s6=o!4i^LL5;_0 zrpA7ov`U=1NCJ=R{fNzdYKuF##f(zbb{ovaOhpME%=b#LNe{6Xm6Vkll|8y9oL>q{V@}gjbowRIQy_+OEY$%f;S;QA5nd)PI1@;!@djJx+^It`9xM z9S*fGVoRiZ==Ec5a%Wi7Fj&kI8N9gIEictRy~h5Oq{bq#h`It}cB8a+fvsX@x0yIL zheIU~5lbQwvq~tBB}v(xjq-Zx3QIM1_X-w%!E)`F)kCC3ty-0Bcy(JNOv2RVG_l1} zBZYb`OoLV2d&5}XTU7T8+N{P_&tu?M`eWOsa*bW9nxw8Y6{-JBS0!JWNM?eOG)=gJT(|?{_|;O_&r>vgvGb+aPV_gL~N9Zv{-WuJQnKYUp>S_ zeV&nFlszhk=?1Col{Cw%mfV9xg8Q^9h+~_Ah=|jAiiqV{-=sb+!ec11V7&9B$=#ux zrnTtu`Tb97_!RtYZsOS}X_XEy>}DopKlREc(SysBq|Do*M)q1MQ3aE^LydGvqgZH- zGHHeIraSX&<8_NR*3qJMk23iMdSU;1!FR0f*My_E8XnK?W}7KAnkgEnqVH^IXeX&9 zvbWb`PSv$^T=fv9y%O49Z36;gw4OU@ zOSx!Ey6H%I>xsWJ5DPRC4Kfl7di^xO=$Wt4a}Prq_t(mVcTj5+2`xfV=&7ET5h42KsEBouXhC~YgLY-*?~?W)chs7xNMik+$oo34xg*pl?Q z>%+&c+?n3;iQbygzQ*DH*1>_!{=wefp@HtowCGHPf5b+b^xj-yTHA7(bhLVOa$zNfn+&hPvqycY~2RQ`nQtJ zUz6p!y^%u_G$J@2sUKA5r+TY1KDB3ZSu-D;%19h6wmF`kGwzW%RPJ(>)6+q<15xh& zK(VjJCnnEu1z~@IJ4=hZCR`u}B+G%Futbn7$DN%HlI1j~`#`eXC-5)y?228PUL=Ko8BAXa6$7LZLw7?UR8?-zv z6FF#gUT0#^`jQplkj*tuxglG^@W>%MqV$O&dy+E3VF%JSxnW0&vB+U3>ZOTcXS#hi zM_iar%8$6R-G~}-<06|Japz;XIqD%OBtQCAL?&v~Q(R|q)Jw|h=9u?OPx&z)x$vkl zU#0ZPF+a7ko8$gkZSv#q^v0sb1B{j?#{*6F-I@rpIH@oZY;z-e;=Kde)I^92%dN>! z4L;c+AJFne^$8*`Ld9f67^CQ~Z>>G8XeGZ)0itQ~oY2qR#~wr<6VyViUxEE;>X$ z^SKz8m1wR6PgrTL^t5d3T-kZunYr>y)Mz^4W!EKGr*nErP)HEaf@x@y0eSz zQr35tI$nAyFLlaA#4U9xWy~&htCinb?$K&jUhdT!k6T9e87GVH=iygK3`tg<@lEgQc&=CAv473^>kuT6w{sjN*#M#Qg8#b$h5n@%hz zUY|*AS6QFU9FJfBn6vzG{S(mpH$In~Qr(!VNO9o2#WL)+G2g&?cXOddSaox;LpEV^ zsYmzI=JJ5`UF6D$mnw2~A|e5~Hk0uQx&FEQ?$*XayXw~F%6P&Sa%1@u_L)=pM;KMb>16gd=bVGyI=QiHIEdNYTiE+jGSOdcqB%2j($!>2`LUWw{ zg5wWNE*IJp4WH8}WZRFWaR`IM9_UNAK(^X9_XT`7G39Z1@pV{q$&lI$8Si?c6!}d%EG7{@v-JJ7@m(#Mab*bcd`b`9;+OWR32gdoP8%vs zty;l`mPcR(}%GUGtol%rtI82B&T1|AQg#*@7XXrq_`+EPtmGz zRGhCH_RfvHedkOEtM4%ko6A}<_l>LDWs#RpJK|h9Y?$@*Hp_C7mGbmUOwOm>zQ=9K zTa`GoPaoAS(v0qpRd_I++G=`D>rBB47G3_)D!e?h^cWgqshPsVpRcq=?n#Pzp`LlL z*gz{2f5ej7gtJQ;ch2A75`4=kk|6Qnq)%R;i|F7|m85NnGtp5G|6 zV_hgDcw|>_se}K>mekM_HzL;kd+*yl#H&DzbJXBiCl-s7mI^#B&1pVCal8O8jzq>i zi}?%7%QGst!>;c9Ru9(L12<|aT)jdn!gSg$f56*wC`^xG{iE%f=h|A#cGMScl?|M@ z6DoB$xv?OoWH0VLI;rDY{9ULGCL?Gt5ADK1M;HHh(Zvc13W|z~N=iz~%E~G#Dypig z&~f-5pMd7$;{&@U|H!~REG#S{A|f&}GU{u{Of-u9P+VMGe0+RDLPBC&8V3+DbyHs?0O#R}0 zaEMLs-JQxAjlIq4S}?3K&pT^U0|#Xq6z`K0@4aWt}ftMK)NT01_1U$f2?yX z6>v2FQysGY8A{#%6?S2fv7x{_EGGGVY})(S^!ITYA@P}E37L_J88J!e3CU@2sr&y0 zI{-Kkd;_2cJY#|3GK4nB1O;FYj<$i)Z6JShxYPkGLU05H54Glj%J(Y}w}1GROW7z_ z1^0D(=5u4LKL^s9Z#11bXWbCUY~CXi93wY3m~Yf;qD{_V?c zZrAIj3*Gi^zB_&+1|Oj{S=2f&N7Db{X}HO%?}=D^eskm(`T4TAZiE$%{jnOrrL=#& zuj5RQ?M#vTg-gj$8?JiCnGxT+eP0K-l!X3#lf5ABH}fl(a$5r2*MUp)tDFH`AHaQ` z_coWZeP0*ExXq<(-`D+=OX=t2nYok{Z*^O;PJBfmp+1{s96_VFXw`mn>3BAcl5S#u zKAzPwB2Q62emo_-oS2NNa_Msls*4LfD9;Dc zkdTnjuMZeQAsbCD=RC( zJPK@D0N{XuJKXmI*ntO3pF19aMd<14>)TPDVVprJbf^(@0BR80K%Wer9R(YL9bBzp z89SQ#@`4{&-vSzh6iO$&jW!%W`}|B* zM0diHl9EzVQqP}1fAQjlw6yfUW5@ZMlRgd(4vvnFAV9&{d1rt(obH2a3h3wO2LKlk z5b!PFP)Q#EH3)40a1iET*zMqb;7%CW0p_3>PD4=JQRK?X$^hvD5C(W3sJ4NSEC4mA zyg?R#AR7zD9Do{xEl}qmq6e;RpsIbhuz{8sB7NY(25<)81tAQz8UD5n1~~h*6W;#o zHrm9t(FO)kTJybFc~5meo=Ml=f5h$T$(YBtB;$+bhL?{>Qt+pxt`1u}`NXI$B1<(( zi6j_wE28OZP9Azz;xtFbP>ne^R-oC0yEY@jJ5g(fX?=hxT1&nea!~pjPPYxW!@FwG zgXdqQp@iY~heekBq`0Ai4r(h=3mQNisA(|hs;jGE+`*J9M7E+DZ~~eYR5O4$05@pT z1f>i@){aw&@as0*X1?-0prJHJ)|sAT{rE25Y~QN# zy7r_b0eeI$&9%tdlPOwTE3WP`iswr7QX)&KD!9BUO(!khnNzrkN2?s!tPG)S2u$;$ zJaTvhOFg6^1c>4vvlZadc+>CA`h-u;z%!rZmBiwGio52EYsANT<TM@ zQ&3Y=Q!_I&b8~ZxuaBjrrInSHwY9a4jSVp2wYRtbNy+`s9C%@!1(aN<%%av<0DYjX zfCp4s@Bs5P@W9@?JJ1iH4>hu=mG)cELnRj=9yGW=3QYmMEEp=GK@xlepnzp)cm!Vp z@IYSzNL~TO7OJ0)b{4hLLJjV(^%k$fdAr_Xc4@L6?n+T!I(Ffj@N|2e zl(|D3XNPKUvgYQ1sbVQ-0R8K=nMp>yh7-4RxA@+BWICOqeDmP?fgDW7Fdp3!gQ@eG zADhVnj}4m&kdt06LaDcCO;bQXK=ALCssd@6sNoQ(^CUD$?quC7p0(T;Ko z!wN>$4`^LfsQu&TZMaE*db_|%5(qR+?6qpv!{ zk6+-*i1nbiz%IXuz&bWs$lWKFwV-=5oYQpVw57W(34Zd^5f!JWZ3nv9EyiRDllL`_ zQmc;RqH?BCg+uc6b@>UgC@!ywCNw*;{K%UL6asbN&z?_Sc38f zjgtU-5ZL~Kr+?$8ZOBP&Pn0Y5fwX4WIJcN6_y!rQF!33bR@B}X8Xm`76DU7C%%q!` z{=u+3{wjl3PG;{@EUr$3*|cY;!g75t`LpVVUPIx-9dTM%Te*y~2Tz4_$0@v)?ojE@ z(3r?hdrR0~Ndr0|)JeL?5-kguPYC0mlIrYxcwk2Nadd0U?>$%k^K!Usoc!Ai!Tz(R!gv=n zGSp*BPTVlo-8Xz|N{2{TM+$?`AT@qX9q{wIrkkcjf5?*UYJ;V;1s zy%KJBv%fyj2LM)3pw9p-mO#W37%)M{3sJeyX!&h+Ab>u!ya$LSs11h8EL3TsN%Kc7 zF&Hzy9WX&Z4EMk=jReh-(62j6@~<85`HCa`1*R)~`i3X#g6NEqnWby3iat5!6J#`u zSk4#o%}ZWTQm;7U6DeQ2=;k+aH>^M=Y2w31dF`nzpRE@(=Htf#$ptDV=q>cr&Xemi zKD|;>emAPgoDmbXSef$*AJY18$~L|2^=N&{9}I)QZ3Oe>Ysncgeg>5KmlRYkY0&Op+ft6sC5oixP%c0 z!R^~sb%@h}>l_R{fIC2>!pZNT%n!DkyS0>Kw%W03?Ds2a!IIlJYHu`Y*YjZNz<5Ex*o~dygawjMs|g znD1Q_wSOBea9u2~tn>JUYES%&L9+Lp`?#Lw8-F&ruIS~`d;i%CQoh>q@bi3~$(ha+ z8O5tb#%maLnpktP^ybWtR~~YZOxB~YsA$#l@5iE|Vhxqjfwyu%PYJb^sGx&Z1>i9g znl4e>N>sSPEGpbn{s*chw3~z4Q$lhDOxl3q5p{lqi`|Ys5=@cMAPL|GJ)q2?KHJMV zzdqmAJ^;pTxJ`a7aNAqzdp1k6%i{bg&9OI?k1s_(ju42C#$OP=Ze+3-N_k%YIy{Y*ky%wxI*%_b8e0t%8C$Lvi#%G|L2h`0s3L}bVJ=%-f2|2S$#rFBc zEf3_z<&E-qFG{Bem}A-39beVymKuzmulOiH9{7MY{@hu9)P+2>V)@6TO3@wiL|=oseU~+bQ1_$5XRvnuXJ~J~rBC506Phof#aM_+1)VQUrNSgCTCqf*VE&m; zFwu%7XfokG6W-f_3f^{|Lo1f(Bg?<=j^1}`FDkpVqXMH9OQ;S0LC1?$EdTl)FIurg zE0$=*l81+fmzS51kB^_9|MBC;e-&B>tyu1$QqhVf+TiE^yO-Th41UmxB@i;uiX~dH z{Qp{Pe{)|_3PJf+_*tN zKtM=Hc=P7XTeoiAzI~gBi0ICpJH*7qcmFQM7p+*L6-%^Y`4=s6XvGq(SfV3I{z8-v zTCqecmgpPH|KICDXvGp7pMVF78$sV#VqjomV(#0w4+{$m8yg!PdhllmJ@_tv0~|!Y zrEt(UmVfFS%SXT?iwm8k^?Mmq>S$>Egu+2J$TBf8L0!oKXU(S8_OESR^=&6OIfbh^N2obRs<^~xxJGHaM(Vjm7`lg>c!XNMeQ)m>=;rN@dgK9Fh=d0D zM~C<(gn6e%cz%fV$c=U@jBzcEbFPectVyu1Pqb@Hv}sAQZcDamPqyq#vFJ)M?@lrA zNj2;J`u3-q4y2j%r%8|>=3)!2(!f*;rrre1R^*BNtuPN z$&nE7`P_VZi#kh9hA;Re*2z0lS_7P6!f%sHs?w%~;tnfw(6GIoY>yXBdqLx;71iy; zXX{3jxhUJ6F4Vdto}I4J5iG4PRBPCNXRwHE@#AYkp@9|)^W*uit96oJRZHIXqdBBY zP+u?qaGv@0*&7`Zkr!3SdMVQs&0Hm`4|lfz5~}$%+ThWy_q#ZEPyDNF6Og3|A~ZpG z=IPU?@$vBi%?hYhz^DQ)6O+xup$tg2m~8~niavo zf?#Jv@X{fKsS%RYh?mp|d1{0zHA0gbp-YW0qDGifBP^*AHq;1vYJ?*-!s+YlOpVxn zX~0Y6^oYudmdc5a%8`M}k%`KIi^^7z%IX=Fr7V@X3YCQ>mAM|3u`!jN1(mifm8Jug zh69y~BbBTp)pJKG2`4I1Cn{mb?N`i!`l&sQgw3Pp7IZRZjPk~;a&I{0jd|rv1mw(w z1gWaNS5*yFQ;Seji&9ey(a>?xvN6~8 zG}I2z)Cp72jd`J;C~A-<@;Xz{G?(AHgwM8|&%T=9u};vrQNX2%&!vgOrJ2>GnbD=0 z-lc`kwS~^DmCn75@ohV+R|ki07mt58e?ae(;6Bli0g3P->8KI8xG{zJaplAb)#OQy zlqsF`8N=*PrUhRtix+LnmmR8B9c$K{YS&%r*4(O>-*Z1&ddvs&kqeR41QM}__p+&b%n2CmA7h**Q@%sqV=xa^-j$74s^A4 zG}SiLRo2uswlocnkD6WST0Iy$eK`7p9uG%|kHtz)B`eORtAEPY{Ze4KQ2b`G)MUBb ze5KNIt;S}(&Tg~O5!vjF^12{fT#&7<$PQ0rw;!@U7&#n)9F0LvBp@e~kW(qh=~U!w z2J%xj@=HE)u>`qXfn2LaZZsk{TacTrNM!pavTGgLw}u>AMUJl`rx%f*=8$urkn_{X z#c|~FAabn_x!#T3=m7upCbDq@S+|a?UPV?cBa7ydxpT;@kI2lA$c$NJ`piGxZHOax zwQrtdO9Y{s*vD`E3ULm9wxsu^_NN~x^i(8;0Ejc%oo7!Dt#l_8h!(F*4y*Pek*@M* zPYJK}qtKk{sZ5Ee52Q0cfX|WoTe<{wn>{_|d@Y`h`l8|nX2m74tD9#z#`ILU$ILod zQdj)F2ZqY7l6UvSu3dR$8HZC=*5R{I&`D@aFEOFyMCaqhuSq?tw>;IGNs!0my&B0aV=yTZg_6CR*!lQTLe`CY2m81D z-vp&pjm|Ffnyj1&z4*r7=RO10+oP!xMsw6MlBU7hmn7*o$oHpWPbskdOJ5HK9SfEk2=Y%S&fXyA;Vk3gO$RNeMT&VCZA}yt$a1 zX`$Cg+1#s@@lKb|-dDV>%9>*gE7(Kmm|Qnw_23mreH_Gt-dCF&lj8b$Z&?XnXH4!NIOg+=)x~e1;3k1l^X7{X z=ek*$sF#@oUXdY|ZTH{#(kz*W8zb{ZMWo!CgB2$3ri4ca$fig84y$zF+2XoU3dux< zg){T}cvMTQ_y$+Tf8dp4I2&{8osLlWyWlSR)DGE**NS|~g_OtlOOM?cxncFb&ebU) zgBvT-FIsdeAU@UZT(nX}T6UdA369{$4|Ac};%dg}Sa)-?ak9jNFk5dBr!JR0oe6tO zvvJ{NA<{m=k5Pv@R((y#I@aCCc3ru$jGoIyhv?KuxXx1D#2sm#vXD>a>#c1Zw6uE- z*a%nxJb7cGIZrU+v*Z+cp8V5FIhbWAX0dF-=#Uz4Gl8kebg z&s$Ag;qXs5ga@46uRcKMT>t|NBBxEqy8>_-$# zZ`uhm+|ZX*_R+@;7L?1Svm+GNIM1E2OP=X?9GhL;ZO12x1eF|R79yTCBODA5n7IwU zxCb2yBV=W-dhGkfBa$oZmT+a2P}Y~Xi4I{zvh3AjU0*yiYr=?iE2|~ezIYWJ3Ma8< zuX%BH-n)V;{JvLZjSOPmr@T&jZgRc326=Y4sqvgu_H*52OyKo}uus9mb&MpLDb4N0qs%o%8 zECk~^Mlum_G}?(RygywV$wFS$=wz@EatSAjjg_Ox&37S`kUNS)xT?uBYaxupF^Wr; zquIA>A)KN%ibuDqIbdxef(|E|&zhs<{n^DxHty)hUR5pOh{Y&A$7sO_j@D?g#b}Y* zXrYX%)_8-(7%7|>k#dfVVo_Pn*l z1QVQCDJ;&8qO(hhHr%l$Xach(s!r3B%`$+2>F zHTf>3MgmuU;p(ootfjO>$Hh1$Sh8X^rHlfccr|Ozo}shLnHAje z8eY{sV~FJs4UX|z5uCkKV#`?_wedO`)x94Lma_+N67sroRsZDsZT-}dcTh8BgIMD=)Yhcg0l>%&@M6**h1N*2}3UQqhEeN;< z4?JBdI$f7&MP4&_*zk1fOvTjIWCiOZek&z}JV|!KHA5$}S4v5ok{o2YhR=4dlu@XB zrcBO~j$K-brcGCHi9x)KKB*tg>Z#xslJzo@Y&D8kN5R7n@hV(MKT23g!P7nKRjAHt zq$E;B+%%AIuE3IpvwbM9w_o)5e_)z0Gk|Cj~u9T{FlE{ zQBl!@|NZm<$?M>O!q@5O=;-O`85tRwnVDHxS=rdwz`6|Bl>r(exOaT=_=)IaQSry( z68sWUd{QrXU%cdbDZ?oz&#t7xqNc{Asm7?I!l=Oh)Kgf}=ZUmGzg#evS~RW=@|n>sg;KHZl!)>qKiSJBy5+tk}!+0#|r)1TEflGr{O*7DJ( zVg7CXf@|%9Q}u#<)q-usf_3?VRoQ|?>4Hh&m)H4ohPj^&ay}d6eg;2)-EjiRIJJ&C}H?R43tiJDAiyB;uAKgfv*i4(+%$(iKn?n}QBg>bN4XYcS>+1s> zYvY?MGn)&bXZ(VkTR_e(BPW)TlTZ%`!avv&2lC%gx114|OYA?TcL=LZ0dKnp#CXns z&AY~t#_IUJld-P|1KCUuUk(60;Po<(lZ;vZXVgV1jqz!TJ=g`V)dZYS_QgQV%Q6Kp z86GH|JUUVqdcu+6dS;8%{R=D(gx73HZc}?F5?J5j}xqQpD(~U{T7@dHAC3 zP94Jy#a9ory@K+EagRnXVjuMHOT~Y^cwLVyt{}!~D@psdrbrt(g8#+CV=IG&wYXGS zUkpS>dm2>mGB$NZrYDVaFC8wXZnzj5hecCdBnaaQc_OTS@3=+lc z%FjZZ87&`}GAi>j@mU&In_}=%kTH0X!ohkS$@i|}P_AE1t|{~B;ygn;{-i4AZTm8| zMCOd!+{2a@y0+1MuG-j-mjs{R+!VBbHlpky@T75cen47p^ctT@4*=2~zkw(A41K+! z&rOaV!ycr+z3Yo$1VtjfcAAYs=fqS@TYFq%X%?l-{qA^P zv0u`%abrEz_sZ>+cc`LTo1$b9 z2+B94gZ^Ujggy-SkI7&1*mp)Yly3hG_8n0Uw4g5@~rPti{9vtsT&-vj&W&u&BlKxHJ98)N*rgon@+!ql{l+ihYIig z%9$ja5V59*a_@`UlCht@qZhm@>!9p0B`ezbM3uBjIqKNcLiLf(tU7sH+3aJp(72pHF#~iFQ@A#ObG66sOp3@=_3MH>1-(pE z^z>9LkEqzGs5q#o9)JB~2KY0-G!(_YD|$jitp zN-HY8P*Rps))Z6KeWGUYSj~`E<29f98$OLU{2FfrG)+X*%_P+<d&V`}Yg{j7st;&tR=B-$*->aHH<!~SPSS{3+i42pVQFZweY^x$br@9 z!Iik-mBf*iw276h$)yhy3m?Yjvd2Evlof%`ucVvksU~68xq;F%t&89j+W?CS18N|WAD$rTnTJT z+FvMxX^}O-XdI@b`l>=pp{T>|)nTh1(ExRu0!!Xl<-{4DVJ=apso;#`tfsg8S1=kLRXX@f~xP{ydy0&+~{^d;!DMqf+ihkLEx9J1VLPy(AvaaK_^(*9HW;UBt zG^{k3VVhkW^`z3k7Gj8^X*nY=XQ6|Co_a}ZShDIeRv?37RmBb6qQx;`M!a4t0{Z$! z&mJxpl6EieGuj;&oT8qOOBo8_Tb#1Ev`1m$nUQ{Ju#n;t$_XhWpA3S)=V5|g5|m-N z9r91~F)W3pE*)j@aWFc=91qjojZ5o!UeFf3TRZ+W*FK~1^qDT{rlvkq=<(PsmaM7k&)4p zkui~xv6GSUl94?oBNHYke@ad+MNa;TfZ@-+fsia?kn5Ecl8 zB^4F)T2N7$Q&E{vQ@^IB)}^LXr(sg2VU?rdkbcA?`H27NBLR^|LQiN#`Dvf>(mvy& zljNX#&PFHALjQ`1UWSogmVrTzfkBaxQJIlZm5E86nOTFGS&M~5o0V0UjZL4O-H?;h zh?mz)K)^;w$Wc_(?b$O=NlD)qF9Ke^41OsaCan-9trYW8IsTPuqMUM~ic-9$T#Wv! z2$L6~W>UdcqVH@U``Gh%I&ykAvAH?3y1KHtx^Xza<#zJscL)%+egDiRRKhx3$~y9e zRrD*XSUJlCMav`=i&PDB_)XI=Pt!01Z?dLIlIH6qO`{ZTtq%rr1t!l+EG5dUpH_m= z$w9EjS+L4oq})rY++VgLP^s*_W>Kh7Zn$+ugllqSKzvkGY;a9d9yhX) zIKG)Wv5_&cmOZ|bKfY8vHeWINxn^Xxd3d60aHMZwuzz6S>)YQy0N%d-f!=|E9+VgS zws&x_cYL^YcC_}(c-hKS!TNO0#`K5H=?vs_I&vlhIg^Q;%|d?4-JC1jTrA&Mt=rgW z-q>i}*z8!{>{;3vnBN$k-<+J?{5ZL}FtNEhwz)pCxjD4CIk36ezqyIh8}Hyp@#HF> z6mx&L0rR65N(do-G~im)SAO(Jmtp9PWX^>WrM@}Yo5MGRJ$Xc;R`2#Y99I-kL0nD^ z5A$ET^vXYKMyA;tWOQ9;yWbn)FhR7mkwH2h{&0P$H%cB)>7+5Uu2tG9+mlAJ!@!@jKG7)lOQgd329mu-Rt7OFDS|T&yn$liUyjAVP!dQ~?V-h7Lx=6-y(wiT{2s~tu z^Q5sqxg>D1kf7h}5ZT0lIW7y~paq_g+@R%YnaDw_^EwlQ)|adZhitBS$_?2PhDQ$B z5v5NI*^`tJ4m*&x$qhSFj71JRQ7=slJJapEIpV@}Qhvns=-~0g6s@F_Bkp`GH?LC+ z4w#RaudqdpdWwtbhj9u$!{nzB_mr1;IB4|YD0K~~V9y&l`jSvjUyOz3Se7GHP_cfa~VouxnhH&DVmh6z0v}wYKb!z7|=b zR&$I%|W@c^QtXLs}k! z2WS?WxX5Q0n)z7oEVc*=D=)T+$i^+UiR;cTwo6&xS?VC@ZxqC7g&Lx#Gn!pcOaI_GDz_l_o>@^8efdLwHt9(!TX%C{!eblvqr zs+n}IL&+!N_0ycoOT!1E6IHce+Pc4F!oJk|I+223v>3Bf_U%w(v^nYOC2Z;UzGuFK zNs;v&FyY~gio?YC2UWzd>%?xHUE2RjE1k4<9*#zF|h+F#i(c z1H}q}pgQn?0H5DAvJ&_$gP4)Y$w`nb0HybU>?}9~9d(~|M^N3*P0zQ>;ly^VK!$36 zt||8ZrU%P2ffPFXH&@*=X8K7)qbp{Q6E^lgGWgQrb6khxUA{3s@8Jb3MPDkXTSx7R zF;u0COxGpu+3UOaCaRLDA|DWN`tzACd*_nWgOPlK`mnBG0et790;AaBhN2gT&ZjpI^o?B|vX!aeJ z>(O7I|2|O&Mn05P31@g!R#w96Kv0YqyzC10e?Vv#i0cADT>#ZkW)KJq0gwjiAW$yI zw}~JylE1Ur^B?`uHu!;o!R92_Lk!DfK zi(j2zsrMsRI7(yIou(AZs%VQaSXiF&AvYb!)Svg9ZHraDI;!n{f=f8zaW^q?S|{$z zL#6vP;nb&5$UOR8CwCwIgT$Ht!5hlI1nA%_pFeXlI~;NVhkU^YUZ~X ze}u?w(7oE;!DDNI`q@Sv&Mqx>0JyWUf8WWICon!>P+Zn9p*As_H8Fq*S@_ zD8eU)@JR0!`~AXIj1L`$>GUbMtuz;7{fqqX7cX**;!JQ@j+MNto;-TF&W0d_;~huZ z?-tL#_J!Y7fH#G!R%|LSD&bjiz@2QJmX3_4tWR)Ub-8-?|8qVqy1o7DMH+mIdQVSJ zFE1|$_1|v02L=X$_7?S+Gdw&Tz#Kf0k&yuDP;ZMG!VV?Vrlh2#rKN$qJUB8B%7sSF zVF$A-%RvGj$wE)8gBO^i zv~CIn{BwalvHQ>;s#E_@*@OI6tu1uU1q!UQvomTSG*oH7jfLKUIRLnCD=L5*+|q!xl5KpT`z3kB1{I0FO{#34a|+YwU`%9P&f2ndD{cOsf>B%%$c)i&jK;?{Q2|XCIm>D z|AS6E>gwtMXIffX+S=MWIy$<#x_Vz9kWL96aIFj;!>B3*g_;@kRXdgYx)XLq!TMD>1j|JY=_h)c@#yw!+HQAl7KmGWy`1t2w9-l|A_MEu& z0EHe!Ya@S^w2*)QKzTWF$PX0VSqu1c{X3 z0n90Y9C+ZS65?xsLITq?uucLH2(^t~2|g$24>u^_tS(Bc=c@^^boq9{^_}){}SsE(BT>i&5ApK{v)h|i7_=b6&e@eY;`zQ9mt<>>-ufe z3T8!UT!by|8X6j)juo`45Ue3J1Zq@a_7x_B;Cc#otZ=&u6;r5&f<_hURlz_AJwQVN z4{D?OqpG@%^%nr^8xg#LUv<#E<1>L|+S@v)*UUu{(WtCRpo0bi9kj)A{neEJFFNQ! zv27hxrFcOF=%8y7ckJ~A@JSSb4!W0s(~r+|$rI?H9=#+g^r~Hk%RHz#>u3cMU1Glq zkiW1r(72e8kN{>yn56-jgC@p|j0}jPf#$}XoE&I$%+JpU(<54eL@SUiEG*C&82jJX zIQhHAJAc}~7A|*icMFY=sNF5x*FsJ0j*b@0l;DAr)*;Fitw5eUi4Mg3{Q~jO3M5*A zyviBC^&xq*+WUcGU(JV<@%kV}`wQG?1(JygTwDK*D=k`qgrpF(0(t5bu*X8nBC4vY zYHDhbGV&iA+@Z=MXay3gu4n}k5AVc@6DQHVtdbJk%c2#?A1#mX7$MOLB-$eR&$6-l zU#b#2B>u3luIeuHBCNpWc+~uF(*L@SVguSmP!YG?KTl$-v46+_Sp}$~qkQlo$c5Uq>Vgf#p0_Tq40WBnOl7nuJ z;Ui;kBL$sFeKpVc#XtkPmx3>kcN|NB!>Mh0R1m&_+#HHxOjmxFYrdJh-#jeFEkMUq%){l(!K)=$BF z=9s8vHRxmG->I1WwteI8szdxHlqlds!2=&d{RnISSu`trn}{}I{myE5R_bJPq(F=W z+KBakf~A3L?Qe3Cg%%;vA|x>}F$iD=fgvDv3B)jiJ8_aZwxGZ%yK0rshAcxUdz#-|GzWkIAP*TOdOgR*-oWFs?$ituiq&ft{-? zEG&LxUghZMi0WVUZ;M4lH(>KPaQ+Y4 zUC`(Pf)uc$z-9wlWrZx^z?L`|B!PhrFwFsWIemS7@Z<=2O5bQ^Ll+dNK3LO-qXUd*NLvACz?M*A?EQnaVM z?ur$C!4D;vdHcw4>0{WiZem-^>-|_NoMCsv7*z8Fe=kAKaSsh&Ud8AyZ6h+B{sE@iq5T9l7oh zknH}AF(lf^>dy~!K-m7MutFZJfUQL(Y@s#sA34@RcE_Nf1@5bm0V^o7sCD*RQyr+J zLN=_ZoGoOhvx7$hiU=$|!uSRjR#2J;$aKI$_lDi-41&8ho*I6+dzj*kFoNe>V7unZ$e}W~kOm3o=Rodp@DK_69Rv3`AdvuN1a!7AJ^O9_guEbu8!KEnf3#xrlPZep zAqV5`msa*y%VT=;^)5%o2;#mxvwfem*R>}DBiJI6X|6@aoqV9X^)bp`$iDlL>6e%6 z?z%3WBszO~aTKxCgAh*!F0AU@@M92pve*z zBq6{-XoH+IfD{SUv>!Q&qgJ->UPt}X!VYgwjpMxi1;FVzcRjtfGe-xze=|ERy5km4 zbITdLjymB78q*7}?XTbRr!`w@Yo(f~_m0)W*sNq?Q)wmlAvlT@kag&0dABt+YPTd1 zkt;uHccn$R{z5|-@9)#X{%W2B6q4v&k>LSZVhYod34vw%5Km>5Ei#UbUC4YY^~pHj zJmx~3Z{~C)YN`Mu7+nvc1GD}{16gwL+B@ zLO*QHx}&E44EK`TxEJ2W{nke7ZGzczg{H_WWrpFmy<^mn7%U4By!}*Kjnwa&PtOhH zh?e$UrtZLL%X*7@^IbJ|N?(ix$yV@utK$s@-A3^!amu@$H`N!V%KjgFUmaHEn)a(; zAZ05C1{NXMh-=Z(Eg^`2ba#VDcMC{&cXxMpm(tyx>*c)g&a7F3?mct9GyBZ!`FO79 zS{LB{bN|+TKld;08K%ZN9A8%a0W6ePBvfm0kJ{S*)V9{v*7i_m`#+e_9>N^bl8lNx z=q>p>m_xoI4H$

*)~;z7WFlG6?{z| z4R8MQhc|!plop!YAou1RdQd`?2$BqeG$I)_Rf^s|(k}LOglSA zPl&VxWw4O?6**Fc$|Hot{c?A(>7yIm^kKYG89<`1?w|6ZZ1LJ^)|^+W?(V~Nsfzl* z60t6APx)LsEWk>Xvm4E~y~+^7(|lsjWY+NtFLkTkOqO5SJ#!hBe1lA7*Lof# zP67*!*;p@#Vy68;n<3ZP1Y$c{Z@=TFY{-qBHcMj9w7&LvO!-@e)&TjOuk_#5*nKAS zNPO_$S7V{KS+J-(RM^fLPhjY9X+BWkMfWIh55&ahBilZ z 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