1
0

adding kirby3-janitor

This commit is contained in:
Philip Wagner
2024-10-14 14:22:24 +02:00
parent b0db09492d
commit 94fbb996f0
204 changed files with 27855 additions and 4 deletions

View File

@@ -26,7 +26,8 @@
"getkirby/cms": "^3.6",
"sylvainjule/embed": "^1.0",
"jg/kirby-fields-block": "^1.1",
"sylvainjule/color-palette": "^1.0"
"sylvainjule/color-palette": "^1.0",
"bnomei/kirby3-janitor": "^2.16"
},
"config": {
"allow-plugins": {

414
composer.lock generated
View File

@@ -4,8 +4,90 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "74776b9954f7c7164160efc4281c70dc",
"content-hash": "12d6b33d05835517f785cab96892d755",
"packages": [
{
"name": "bnomei/kirby3-janitor",
"version": "2.16.0",
"source": {
"type": "git",
"url": "https://github.com/bnomei/kirby3-janitor.git",
"reference": "12a9132cf221f3e248d9f22bddb7cbd7d303ae3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bnomei/kirby3-janitor/zipball/12a9132cf221f3e248d9f22bddb7cbd7d303ae3a",
"reference": "12a9132cf221f3e248d9f22bddb7cbd7d303ae3a",
"shasum": ""
},
"require": {
"getkirby/composer-installer": "^1.2",
"league/climate": "^3.7",
"php": ">=7.4.0",
"symfony/deprecation-contracts": "2.5",
"symfony/finder": "^5.4"
},
"require-dev": {
"getkirby/cms": "^3.5",
"php-coveralls/php-coveralls": "^2.4",
"phpunit/phpunit": "^9.5"
},
"type": "kirby-plugin",
"extra": {
"kirby-cms-path": "tests/kirby"
},
"autoload": {
"psr-4": {
"Bnomei\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bruno Meilick",
"email": "b@bnomei.com"
}
],
"description": "Kirby 3 Plugin for running jobs like cleaning the cache from within the Panel, PHP code or a cronjob",
"keywords": [
"ajax",
"button",
"cache",
"clean",
"cronjob",
"janitor",
"job-runner",
"kirby3",
"kirby3-cms",
"kirby3-plugin"
],
"support": {
"issues": "https://github.com/bnomei/kirby3-janitor/issues",
"source": "https://github.com/bnomei/kirby3-janitor/tree/v2.16.0"
},
"funding": [
{
"url": "https://buymeacoff.ee/bnomei",
"type": "custom"
},
{
"url": "https://paypal.me/bnomei",
"type": "custom"
},
{
"url": "https://github.com/bnomei",
"type": "github"
},
{
"url": "https://www.patreon.com/bnomei",
"type": "patreon"
}
],
"time": "2022-04-14T18:24:35+00:00"
},
{
"name": "claviska/simpleimage",
"version": "3.7.0",
@@ -650,6 +732,71 @@
],
"time": "2022-03-08T20:15:36+00:00"
},
{
"name": "league/climate",
"version": "3.8.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/climate.git",
"reference": "a785a3ac8f584eed4abd45e4e16fe64c46659a28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/climate/zipball/a785a3ac8f584eed4abd45e4e16fe64c46659a28",
"reference": "a785a3ac8f584eed4abd45e4e16fe64c46659a28",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"seld/cli-prompt": "^1.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.6.10",
"mockery/mockery": "^1.4.2",
"phpunit/phpunit": "^9.5.10"
},
"suggest": {
"ext-mbstring": "If ext-mbstring is not available you MUST install symfony/polyfill-mbstring"
},
"type": "library",
"autoload": {
"psr-4": {
"League\\CLImate\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joe Tannenbaum",
"email": "hey@joe.codes",
"homepage": "http://joe.codes/",
"role": "Developer"
},
{
"name": "Craig Duncan",
"email": "git@duncanc.co.uk",
"homepage": "https://github.com/duncan3dc",
"role": "Developer"
}
],
"description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.",
"keywords": [
"cli",
"colors",
"command",
"php",
"terminal"
],
"support": {
"issues": "https://github.com/thephpleague/climate/issues",
"source": "https://github.com/thephpleague/climate/tree/3.8.2"
},
"time": "2022-06-18T14:42:08+00:00"
},
{
"name": "league/color-extractor",
"version": "0.3.2",
@@ -1251,6 +1398,61 @@
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "seld/cli-prompt",
"version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/cli-prompt.git",
"reference": "b8dfcf02094b8c03b40322c229493bb2884423c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/b8dfcf02094b8c03b40322c229493bb2884423c5",
"reference": "b8dfcf02094b8c03b40322c229493bb2884423c5",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpstan/phpstan": "^0.12.63"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\CliPrompt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
"keywords": [
"cli",
"console",
"hidden",
"input",
"prompt"
],
"support": {
"issues": "https://github.com/Seldaek/cli-prompt/issues",
"source": "https://github.com/Seldaek/cli-prompt/tree/1.0.4"
},
"time": "2020-12-15T21:32:01+00:00"
},
{
"name": "sylvainjule/color-palette",
"version": "1.0.4",
@@ -1329,6 +1531,136 @@
},
"time": "2024-03-08T14:51:01+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-07-12T14:48:14+00:00"
},
{
"name": "symfony/finder",
"version": "v5.4.43",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ae25a9145a900764158d439653d5630191155ca0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ae25a9145a900764158d439653d5630191155ca0",
"reference": "ae25a9145a900764158d439653d5630191155ca0",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-php80": "^1.16"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v5.4.43"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-08-13T14:03:51+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.26.0",
@@ -1579,6 +1911,86 @@
}
],
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
}
],
"packages-dev": [],

View File

@@ -10,6 +10,13 @@ columns:
fields:
type: fields
fields:
janitor:
type: janitor
label: Copy from de to here
progress: Working...
job: copyFromDe
data: 'layout'
confirm: "This will replace everything under here"
layout:
label: Layout
type: layout

View File

@@ -32,6 +32,13 @@ tabs:
work:
label: Projekt
fields:
janitor:
type: janitor
label: Copy from de to here
progress: Working...
job: copyFromDe
data: 'layout'
confirm: "This will replace everything under here"
layout:
label: Layout
type: layout

View File

@@ -3,6 +3,18 @@
return [
'languages' => true,
'debug' => true,
'bnomei.janitor.jobs' => [
'copyFromDe' => function (Kirby\Cms\Page $page = null, string $data) {
$content = $page->content('de')->toArray();
$page->update([$data => $content[$data]], kirby()->languageCode());
return [
'status' => 200,
'label' => 'Done',
'reload' => true
];
},
],
'thumbs' => [
'srcsets' => [
'full' => [

View File

@@ -0,0 +1,25 @@
[*.{css,scss,less,js,json,ts,sass,html,hbs,mustache,phtml,html.twig,md,yml}]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
insert_final_newline = true
[*.md, *.txt]
indent_size = 4
trim_trailing_whitespace = false
[site/templates/**.php]
indent_size = 2
[site/snippets/**.php]
indent_size = 2
[package.json,.{babelrc,editorconfig,eslintrc,lintstagedrc,stylelintrc}]
indent_style = space
indent_size = 2
[composer.json]
indent_size = 4

View File

@@ -0,0 +1,18 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:vue/recommended",
"prettier"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"vue/require-default-prop": "off"
}
}

View File

@@ -0,0 +1,19 @@
<?php
$finder = PhpCsFixer\Finder::create()
->exclude('content')
->exclude('kirby')
->exclude('node_modules')
//->exclude('site/plugins')
->exclude('src')
->exclude('vendor')
->in(__DIR__)
;
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
])
->setFinder($finder)
;

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Bruno Meilick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,67 @@
# Kirby 3 Janitor
![Release](https://flat.badgen.net/packagist/v/bnomei/kirby3-janitor?color=ae81ff)
![Downloads](https://flat.badgen.net/packagist/dt/bnomei/kirby3-janitor?color=272822)
[![Build Status](https://flat.badgen.net/travis/bnomei/kirby3-janitor)](https://travis-ci.com/bnomei/kirby3-janitor)
[![Coverage Status](https://flat.badgen.net/coveralls/c/github/bnomei/kirby3-janitor)](https://coveralls.io/github/bnomei/kirby3-janitor)
[![Maintainability](https://flat.badgen.net/codeclimate/maintainability/bnomei/kirby3-janitor)](https://codeclimate.com/github/bnomei/kirby3-janitor)
[![Twitter](https://flat.badgen.net/badge/twitter/bnomei?color=66d9ef)](https://twitter.com/bnomei)
Kirby 3 Plugin for running jobs.
- It is a Panel Button!
- It has jobs build-in for cleaning the cache, sessions, create zip-backup, pre-generate thumbs, open URLs, refresh the current Panel page and more.
- You can define your own jobs (call API hooks, play a game, hack a server, ...)
- It can be triggered in your frontend code and with CRON.
- It can also be used as a CLI with fancy output.
- It can also create logs of what it did.
## Install
Using composer:
```bash
composer require bnomei/kirby3-janitor
```
Using git submodules:
```bash
git submodule add https://github.com/bnomei/kirby3-janitor.git site/plugins/kirby3-janitor
```
Using download & copy: download [the latest release](https://github.com/bnomei/kirby3-janitor/releases) and copy to `site/plugins`
## Commerical Usage
> <br>
><b>Support open source!</b><br><br>
> This plugin is free but if you use it in a commercial project please consider to sponsor me or make a donation.<br>
> If my work helped you to make some cash it seems fair to me that I might get a little reward as well, right?<br><br>
> Be kind. Share a little. Thanks.<br><br>
> &dash; Bruno<br>
> &nbsp;
| M | O | N | E | Y |
|---|----|---|---|---|
| [Github sponsor](https://github.com/sponsors/bnomei) | [Patreon](https://patreon.com/bnomei) | [Buy Me a Coffee](https://buymeacoff.ee/bnomei) | [Paypal dontation](https://www.paypal.me/bnomei/15) | [Hire me](mailto:b@bnomei.com?subject=Kirby) |
## Wiki
Continue to the [Janitor Wiki](https://github.com/bnomei/kirby3-janitor/wiki) to read more on how to install, setup and use this plugin.
## Dependencies
- [Symfony Finder](https://symfony.com/doc/current/components/finder.html)
- [CLIMate](https://github.com/thephpleague/climate)
## Disclaimer
This plugin is provided "as is" with no guarantee. Use it at your own risk and always test it yourself before using it in a production environment. If you find any issues, please [create a new issue](https://github.com/bnomei/kirby3-janitor/issues/new).
## License
[MIT](https://opensource.org/licenses/MIT)
It is discouraged to use this plugin in any project that promotes racism, sexism, homophobia, animal abuse, violence or any other form of hate speech.

View File

@@ -0,0 +1,165 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Cms\Page;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Dir;
use Kirby\Toolkit\F;
use Symfony\Component\Finder\Finder;
use ZipArchive;
final class BackupZipJob extends JanitorJob
{
/** @var array */
private $options;
public function __construct(?Page $page = null, ?string $data = null)
{
parent::__construct($page, $data);
$this->options = [
'ulimit' => option('bnomei.janitor.backupzip.ulimit', 512), // 1024 seems to be unix default
'date' => option('bnomei.janitor.backupzip.date', null), // null to disable, 'since 1 day ago'
'roots' => option('bnomei.janitor.backupzip.roots', function () {
return [
kirby()->roots()->accounts(),
kirby()->roots()->content(),
];
}),
'target' => option('bnomei.janitor.backupzip.target', function () {
$dir = realpath(kirby()->roots()->accounts() . '/../') . '/backups';
Dir::make($dir);
$prefix = option('bnomei.janitor.backupzip.prefix', '');
return $dir . '/' . $prefix . time() . '.zip'; // date('Y-m-d')
}),
];
foreach ($this->options as $key => $value) {
if (!is_string($value) && is_callable($value)) {
$this->options[$key] = $value();
}
}
}
/**
* @param string|null $key
* @return array
*/
public function option(?string $key = null)
{
if ($key) {
return A::get($this->options, $key);
}
return $this->options;
}
public static function directory(): string
{
return \dirname((string) (new self())->option('target'));
}
/**
* @return array
*/
public function job(): array
{
$time = time();
$climate = \Bnomei\Janitor::climate();
$zipPath = (string) $this->option('target');
$zip = new ZipArchive();
if ($zip->open($zipPath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true) {
if ($climate) {
$climate->red('Failed to create: ' . $zipPath);
}
return [
'status' => 500,
];
}
$roots = $this->option('roots');
$finder = new Finder();
$finder->files()->in($roots);
if ($date = $this->option('date')) {
$finder->date($date);
}
$count = iterator_count($finder); // closing of zip
$ulimit = $this->option('ulimit');
$zipped = 0;
if ($climate) {
$climate->out('Files: ' . $count);
}
$progress = null;
if ($count && $climate) {
$progress = $climate->progress()->total($count);
}
foreach ($finder as $file) {
$filePath = $file->getPath() . DIRECTORY_SEPARATOR . $file->getFilename();
$localFilePath = $filePath;
foreach ($roots as $root) {
$localFilePath = str_replace(dirname($root), '', $localFilePath);
}
if ($zip->addFile($filePath, $localFilePath)) {
$mime = F::mime($filePath);
if (in_array($mime, [
'application/json', 'text/json',
'application/yaml', 'text/yaml',
'text/html',
'text/plain',
'text/xml',
'application/x-javascript',
'text/css',
'text/csv', 'text/x-comma-separated-values',
'text/comma-separated-values', 'application/octet-stream',
])) {
$zip->setCompressionName($filePath, ZipArchive::CM_DEFLATE);
} else {
$zip->setCompressionName($filePath, ZipArchive::CM_STORE);
}
$zipped++;
if ($progress && $climate) {
$progress->current($zipped);
}
if ($zipped % $ulimit === 0) {
$zip->close();
if ($zip->open($zipPath) === false) {
@unlink($zipPath);
if ($climate) {
$climate->red('Hit ulimit but failed to reopen zip: ' . $zipPath);
}
return [
'status' => 500,
'error' => 'Hit ulimit but failed to reopen zip: ' . $zipPath,
];
}
}
}
}
if ($climate) {
$climate->out('Closing zip...');
}
$zip->close();
if ($climate) {
$climate->out($zipPath);
}
return [
'status' => $zipped > 0 ? 200 : 204,
'duration' => time() - $time,
'filename' => \basename($zipPath, '.zip'),
'files' => $zipped,
'nicesize' => \Kirby\Toolkit\F::niceSize($zipPath),
'modified' => date('d/m/Y, H:i:s', \Kirby\Toolkit\F::modified($zipPath)),
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Toolkit\F;
use Symfony\Component\Finder\Finder;
final class CleanCacheFilesJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$dir = kirby()->roots()->cache();
$removed = 0;
$finder = new Finder();
$finder->files()->name('*.cache')->in($dir);
$count = iterator_count($finder);
$climate = \Bnomei\Janitor::climate();
$progress = null;
if ($count && $climate) {
$progress = $climate->progress()->total($count);
}
foreach ($finder as $cacheFile) {
if (F::remove($cacheFile->getRealPath())) {
$removed++;
if ($progress && $climate) {
$progress->current($removed);
}
}
}
return [
'status' => $removed > 0 ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Toolkit\F;
final class CleanContentJob extends JanitorJob
{
private $progress;
private $climate;
/**
* based on cookbook by @texnixe
* https://getkirby.com/docs/cookbook/extensions/content-file-cleanup
*
* @return array
*/
public function job(): array
{
$kirby = kirby();
// Authenticate as almighty
$kirby->impersonate('kirby');
// Define your collection
// Don't use `$site->index()` for thousands of pages
$collection = $kirby->site()->index();
$time = microtime(true);
$count = $collection->count();
$updated = 0;
$this->climate = \Bnomei\Janitor::climate();
// set the fields to be ignored
$ignore = option('bnomei.jabitor.cleancontentjob.ignore', ['title', 'slug', 'template', 'sort']);
// call the script for all languages if multilang
if ($kirby->multilang() === true) {
$languages = $kirby->languages();
foreach ($languages as $language) {
$updated += $this->cleanUp($collection, $ignore, $language->code());
}
} else {
$updated += $this->cleanUp($collection, $ignore);
}
if ($this->climate) {
$this->climate->blue('duration: ' . round((microtime(true) - $time) * 1000) . 'ms');
$this->climate->blue('count: ' . $count);
$this->climate->blue('updated: ' . $updated);
}
return [
'status' => $updated > 0 ? 200 : 204,
];
}
/**
* based on cookbook by @texnixe
* https://getkirby.com/docs/cookbook/extensions/content-file-cleanup
*/
protected function cleanUp($collection, $ignore = null, string $lang = null): int
{
$updated = 0;
foreach ($collection as $item) {
// get all fields in the content file
$contentFields = $item->content($lang)->fields();
// unset all fields in the `$ignore` array
foreach ($ignore as $field) {
if (array_key_exists($field, $contentFields) === true) {
unset($contentFields[$field]);
}
}
// get the keys
$contentFields = array_keys($contentFields);
// get all field keys from blueprint
$blueprintFields = array_keys($item->blueprint()->fields());
// get all field keys that are in $contentFields but not in $blueprintFields
$fieldsToBeDeleted = array_diff($contentFields, $blueprintFields);
// update page only if there are any fields to be deleted
if (count($fieldsToBeDeleted) > 0) {
// flip keys and values and set new values to null
$data = array_map(function ($value) {
return null;
}, array_flip($fieldsToBeDeleted));
// try to update the page with the data
try {
$item->update($data, $lang);
$updated++;
if ($this->climate) {
$this->climate->green('+++ ' . $item->id());
}
} catch (\Exception $e) {
if ($this->climate) {
$this->climate->red('ERR ' . $item->id() . ': ' .$e->getMessage());
}
}
} else {
if ($this->climate) {
$this->climate->white('=== ' . $item->id());
}
}
}
return $updated;
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class CleanSessionsJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$success = kirby()->app()->session()->store()->collectGarbage();
return [
'status' => $success ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class ContextJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
return [
'status' => 200,
'label' => $this->page()->title()->value() . ' ' . $this->data(),
];
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class FlushLapseJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$success = false;
if (class_exists('\Bnomei\Lapse')) {
$success = \Bnomei\Lapse::singleton()->flush();
}
return [
'status' => $success ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class FlushPagesCacheJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
return [
'status' => kirby()->cache('pages')->flush() ? 200 : 404,
];
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class FlushRedisDBJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$success = false;
if (class_exists('\Bnomei\Redis')) {
$redis = new \Bnomei\Redis();
if ($redis->redisClient()->dbsize() > 1) {
// DANGER: $this->connection->flushdb()
$redis->flush();
$success = $redis->redisClient()->dbsize() === 0;
}
}
return [
'status' => $success ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Toolkit\F;
use Symfony\Component\Finder\Finder;
final class FlushSessionFilesJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$dir = kirby()->root('sessions');
$removed = 0;
$finder = new Finder();
$finder->files()->name('*.sess')->in($dir);
$count = iterator_count($finder);
$climate = \Bnomei\Janitor::climate();
$progress = null;
if ($count && $climate) {
$progress = $climate->progress()->total($count);
}
foreach ($finder as $cacheFile) {
if (F::remove($cacheFile->getRealPath())) {
$removed++;
if ($progress && $climate) {
$progress->current($removed);
}
}
}
return [
'status' => $removed > 0 ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,274 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Cms\File;
use Kirby\Cms\Page;
use Kirby\Cms\User;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
use League\CLImate\CLImate;
final class Janitor
{
/**
* @var array
*/
private $options;
/**
* Janitor constructor.
* @param array $options
*/
public function __construct(array $options = [])
{
$defaults = [
'debug' => option('debug'),
'log' => option('bnomei.janitor.log.fn'),
'jobs' => option('bnomei.janitor.jobs'),
'jobs-defaults' => ['bnomei.janitor.jobs-defaults'],
'jobs-extends' => option('bnomei.janitor.jobs-extends'),
'secret' => option('bnomei.janitor.secret'),
];
$this->options = array_merge($defaults, $options);
$extends = array_merge($this->options['jobs-defaults'], $this->options['jobs-extends']);
foreach ($extends as $extend) {
// NOTE: it is intended that jobs override merged not other way around
$this->options['jobs'] = array_change_key_case(
array_merge(option($extend, []), $this->options['jobs'])
);
}
foreach ($this->options as $key => $call) {
if (is_callable($call) && in_array($key, ['secret'])) {
$this->options[$key] = $call();
}
}
}
/**
* @param string|null $key
* @return array
*/
public function option(?string $key = null)
{
if ($key) {
return A::get($this->options, $key);
}
return $this->options;
}
/**
* @param string $secret
* @param string $name
* @param array $data
* @return array
*/
public function jobWithSecret(string $secret, string $name, array $data = []): array
{
if ($secret === $this->option('secret')) {
return $this->job($name, $data);
}
return [
'status' => 401,
];
}
/**
* @param string $name
* @param array $data
* @return array
*/
public function job(string $name, array $data = []): array
{
$job = $this->findJob($name);
if (!is_string($job) && is_callable($job)) {
return $this->jobFromCallable($job, $data);
} elseif (class_exists($job)) {
return $this->jobFromClass($job, $data);
}
return [
'status' => 404,
];
}
/**
* @return mixed
*/
public function listJobs()
{
// find in jobs config
return array_keys($this->option('jobs'));
}
/**
* @param string $name
* @return mixed|string
*/
public function findJob(string $name)
{
// find in jobs config
$jobInConfig = A::get($this->option('jobs'), strtolower($name));
if ($jobInConfig) {
return $jobInConfig;
}
// could be a class
return $name;
}
/**
* @param $job
* @param array $data
* @return array
*/
public function jobFromCallable($job, array $data): array
{
$return = false;
try {
set_time_limit(0);
} catch (\Exception $ex) {
// ignore
}
try {
$return = $job(
page(str_replace('+', '/', urldecode(A::get($data, 'contextPage', '')))),
str_replace('+S_L_A_S_H+', '/', urldecode(A::get($data, 'contextData', '')))
);
} catch (\BadMethodCallException $ex) {
$return = $job();
}
if (is_array($return)) {
return $return;
}
return [
'status' => $return ? 200 : 404,
];
}
/**
* @param string $job
* @param array $data
* @return array
*/
public function jobFromClass(string $job, array $data): array
{
$object = new $job(
page(str_replace('+', '/', urldecode(A::get($data, 'contextPage', '')))),
str_replace('+S_L_A_S_H+', '/', urldecode(A::get($data, 'contextData', '')))
);
if (method_exists($object, 'job')) {
try {
set_time_limit(0);
} catch (\Exception $ex) {
// ignore
}
return $object->job();
}
return [
'status' => 400,
];
}
/**
* @param string $msg
* @param string $level
* @param array $context
* @return bool
*/
public function log(string $msg = '', string $level = 'info', array $context = []): bool
{
$log = $this->option('log');
if ($log && is_callable($log)) {
if (!$this->option('debug') && $level == 'debug') {
// skip but...
return true;
} else {
return $log($msg, $level, $context);
}
}
return false;
}
/*
* @var Janitor
*/
private static $singleton;
/**
* @param array $options
* @return Janitor
*/
public static function singleton(array $options = []): Janitor
{
if (self::$singleton) {
return self::$singleton;
}
self::$singleton = new Janitor($options);
return self::$singleton;
}
/**
* @param string|null $template
* @param mixed|null $model
* @return string
*/
public static function query(string $template = null, $model = null): string
{
$page = null;
$file = null;
$user = kirby()->user();
if ($model && $model instanceof Page) {
$page = $model;
} elseif ($model && $model instanceof File) {
$file = $model;
} elseif ($model && $model instanceof User) {
$user = $model;
}
return Str::template($template, [
'kirby' => kirby(),
'site' => kirby()->site(),
'page' => $page,
'file' => $file,
'user' => $user,
'model' => $model ? get_class($model) : null,
]);
}
/**
* @param $val
* @param bool $return_null
* @return bool
*/
public static function isTrue($val, $return_null = false): bool
{
$boolval = (is_string($val) ? filter_var($val, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : (bool) $val);
$boolval = ($boolval === null && !$return_null ? false : $boolval);
return $boolval;
}
/**
* @var \League\CLImate\CLImate
*/
private static $climate;
/**
* @param CLImate|null $climate
* @return CLImate|null
*/
public static function climate(?CLImate $climate = null): ?CLImate
{
if ($climate && !self::$climate) {
self::$climate = $climate;
}
return self::$climate;
}
}

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Cms\Page;
abstract class JanitorJob implements Job
{
/*
* @var Page
*/
private $page;
/*
* @var string
*/
private $data;
public function __construct(?Page $page = null, ?string $data = null)
{
$this->page = $page;
$this->data = $data;
}
/**
* @return string|null
*/
public function data(): ?string
{
return $this->data;
}
/**
* @return Page|null
*/
public function page(): ?Page
{
return $this->page;
}
/**
* @return array
*/
abstract public function job(): array;
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Cms\Page;
interface Job
{
public function __construct(?Page $page = null, ?string $data = null);
public function data(): ?string;
public function page(): ?Page;
public function job(): array;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Bnomei;
use League\CLImate\Util\Writer\WriterInterface;
class QuietWriter implements WriterInterface
{
public function write($content)
{
// be quiet here
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class ReindexAutoIDJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$success = false;
if (class_exists('\Bnomei\AutoID')) {
$success = \Bnomei\AutoID::index(true) > 0;
}
return [
'status' => $success ? 200 : 204,
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class ReindexSearchForKirbyJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
if (class_exists('\Kirby\Search\Index')) {
try {
(new \Kirby\Search\Index())->build();
} catch (\Exception $e) {
return [
'status' => 500,
'error' => $e->getMessage(),
];
}
return [
'status' => 200,
];
}
return [
'status' => 204,
];
}
}

View File

@@ -0,0 +1,187 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Exception;
use Kirby\Cms\Media;
use Kirby\Cms\Page;
use Kirby\Cms\Pages;
use Kirby\Filesystem\Dir;
use Kirby\Http\Remote;
use Kirby\Toolkit\Query;
use Kirby\Toolkit\Str;
use Symfony\Component\Finder\Finder;
final class RenderJob extends JanitorJob
{
/**
* @var int|void
*/
private $countPages;
/**
* @var bool
*/
private $verbose;
/**
* @var array
*/
private $failed;
/**
* @var array
*/
private $found;
private $countLanguages;
private $renderSiteUrl;
/**
* @var mixed
*/
private $renderTemplate;
/**
* @return array
*/
public function job(): array
{
$kirby = kirby();
$climate = Janitor::climate();
$progress = null;
$this->verbose = $climate ? $climate->arguments->defined('verbose') : false;
$time = time();
// make sure the thumbs are triggered
$kirby->cache('pages')->flush();
if (class_exists('\Bnomei\Lapse')) {
Lapse::singleton()->flush();
}
// visit all pages to generate media/*.job files
$allPages = $this->getAllPagesIDs();
$this->countPages = count($allPages);
$this->countLanguages = $kirby->languages()->count() > 0 ? $kirby->languages()->count() : 1;
$visited = 0;
if ($climate) {
$climate->out('Languages: ' . $this->countLanguages);
$climate->out('Pages: ' . $this->countPages);
$climate->blue('Rendering Pages...');
}
if ($this->countPages && $climate) {
$progress = $climate->progress()->total($this->countPages);
}
$this->failed = [];
$this->found = [];
$this->renderSiteUrl = rtrim((string)\option('bnomei.janitor.renderSiteUrl')(), '/');
foreach ($allPages as $pageId) {
try {
$content = '';
if (strlen($this->renderSiteUrl) > 0) {
$content = $this->remoteGetPage($pageId);
} else {
$content = $this->renderPage($pageId);
}
if ($this->verbose && strlen($content) > 0) {
$this->verboseCheckContent($content);
}
} catch (Exception $ex) {
$this->failed[] = $pageId . ': ' . $ex->getMessage();
}
$visited++;
if ($progress && $climate) {
$progress->current($visited);
}
}
$this->found = array_unique($this->found);
if ($climate && count($this->found)) {
$climate->out('Found images with media/pages/* : ' . count($this->found));
}
if (count($this->failed)) {
$climate->out('Rendering failed for Pages: ' . count($this->failed));
foreach ($this->failed as $fail) {
$climate->red($fail);
}
}
$duration = time() - $time;
return [
'status' => $visited > 0 ? 200 : 204,
'duration' => $duration,
];
}
private function getAllPagesIDs(): array
{
$ids = [];
$allPages = null;
if ($this->data()) {
$allPages = (new Query(
$this->data(),
[
'kirby' => kirby(),
'site' => site(),
'page' => $this->page(),
]
))->result();
if (is_a($allPages, Page::class)) {
$allPages = new Pages([$allPages]);
}
foreach ($allPages as $page) {
$ids[] = $page->id(); // this should not fully load the page yet
}
}
if (!$allPages) {
$finder = new Finder();
$finder->directories()
->in(kirby()->roots()->content());
foreach ($finder as $folder) {
$id = $folder->getRelativePathname();
if (strpos($id, '_drafts') === false) {
$ids[] = ltrim(preg_replace('/\/*\d+_/', '/', $id), '/');
}
}
}
return $ids;
}
private function remoteGetPage(string $pageId): string
{
$content = Remote::get($this->renderSiteUrl . '/' . $pageId)->content();
foreach (kirby()->languages() as $lang) {
$content .= Remote::get($this->renderSiteUrl . '/' . $lang->code() . '/' . $pageId)->content();
}
return $content;
}
private function verboseCheckContent(string $content)
{
preg_match_all('~/media/pages/([a-zA-Z0-9-_./]+.(?:png|jpg|jpeg|webp|avif|gif))~', $content, $matches);
if ($matches && count($matches) > 1) {
$this->found = array_merge($this->found, $matches[1]);
}
}
private function renderPage(string $pageId)
{
$page = page($pageId);
$content = '';
if ($this->countLanguages > 1) {
$content = $page->render();
foreach (kirby()->languages() as $lang) {
site()->visit($page, $lang->code());
$content .= $page->render();
}
} else {
site()->visit($page);
$content = $page->render();
}
return $content;
}
}

View File

@@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
namespace Bnomei;
use Kirby\Cms\Media;
use Kirby\Cms\Page;
use Kirby\Cms\Pages;
use Kirby\Data\Data;
use Kirby\Filesystem\Dir;
use Kirby\Filesystem\F;
use Kirby\Http\Remote;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Query;
use Kirby\Toolkit\Str;
use Symfony\Component\Finder\Finder;
final class ThumbsJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
$climate = Janitor::climate();
$progress = null;
$verbose = $climate ? $climate->arguments->defined('verbose') : false;
$time = time();
$root = realpath(kirby()->roots()->index() . '/media/') . '/pages';
if ($this->page() && $this->data()) {
$root = $this->page()->mediaRoot();
}
Dir::make($root);
if ($verbose) {
$finder = new Finder();
$finder->files()
->in($root)
->name('/\.(?:avif|png|jpg|jpeg|webp|gif)$/');
if ($climate) {
$climate->out('Thumbs found: ' . iterator_count($finder));
}
}
$finder = new Finder();
$finder->files()
->in($root)
->ignoreDotFiles(false)
->name('/\.json$/');
$countJobs = iterator_count($finder);
$jobs = 0;
$created = 0;
$jobsSkipped = [];
if ($climate) {
$climate->out('Jobs found: ' . $countJobs);
}
if ($countJobs && $climate) {
$climate->blue('Generating Thumbs...');
$progress = $climate->progress()->total($countJobs);
}
foreach ($finder as $file) {
$jobs++;
$parentID = null;
$page = null;
$page = null;
if (preg_match('/.*\/media\/pages\/(.*)\/.*-[\d]*\/\.jobs/', $file->getPath(), $matches)) {
$page = page($matches[1]);
}
if (!$page) {
$jobsSkipped[] = 'Page not found: ' . $parentID;
continue;
}
$path = $file->getPath() . '/' . $file->getFilename();
$options = Data::read($path);
$jobFilename = $file->getFilenameWithoutExtension();
$filename = A::get($options, 'filename');
$pageFile = $page->file($filename);
if (!$pageFile) {
$jobsSkipped[] = 'File not found: ' . $parentID . '/' . $filename;
continue;
}
$hash = basename(str_replace('/.jobs', '', $file->getPath()));
if (Media::link($page, $hash, $jobFilename) !== false) {
$created++;
}
if ($progress && $climate) {
$progress->current($jobs);
}
}
$duration = time() - $time;
if ($climate) {
$climate->out('Thumbs created: ' . $created);
if ($jobsSkipped) {
$climate->out('Jobs executed: ' . $jobs);
$climate->out('Jobs skipped: ' . count($jobsSkipped));
foreach ($jobsSkipped as $skip) {
$climate->red($skip);
}
}
$climate->out('Duration in seconds: ' . strval($duration));
}
return [
'status' => $created > 0 ? 200 : 204,
'duration' => $duration,
'thumbs' => [
'jobs' => $countJobs,
'created' => $created,
],
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Bnomei;
final class WhistleJob extends JanitorJob
{
/**
* @return array
*/
public function job(): array
{
return [
'status' => 200,
'label' => '♫',
];
}
}

View File

@@ -0,0 +1,75 @@
{
"name": "bnomei/kirby3-janitor",
"type": "kirby-plugin",
"version": "2.16.0",
"license": "MIT",
"description": "Kirby 3 Plugin for running jobs like cleaning the cache from within the Panel, PHP code or a cronjob",
"authors": [
{
"name": "Bruno Meilick",
"email": "b@bnomei.com"
}
],
"keywords": [
"kirby3",
"kirby3-cms",
"kirby3-plugin",
"cache",
"clean",
"janitor",
"job-runner",
"cronjob",
"ajax",
"button"
],
"autoload": {
"psr-4": {
"Bnomei\\": "classes/"
}
},
"config": {
"optimize-autoloader": true,
"sort-packages": true,
"allow-plugins": {
"getkirby/composer-installer": true
}
},
"require": {
"php": ">=7.4.0",
"getkirby/composer-installer": "^1.2",
"league/climate": "^3.7",
"symfony/deprecation-contracts": "2.5",
"symfony/finder": "^5.4"
},
"require-dev": {
"getkirby/cms": "^3.5",
"php-coveralls/php-coveralls": "^2.4",
"phpunit/phpunit": "^9.5"
},
"scripts": {
"build": [
"yarn",
"yarn run build"
],
"analyze": "phpstan analyse classes",
"fix": "php-cs-fixer fix",
"test": [
"mkdir -p tests/logs",
"@putenv XDEBUG_MODE=coverage",
"phpunit --configuration ./phpunit.xml"
],
"dist": [
"composer install --no-dev --optimize-autoloader",
"git rm -rf --cached .; git add .;"
],
"kirby": [
"composer install",
"composer update",
"composer install --working-dir=tests/kirby --no-dev --optimize-autoloader",
"composer update --working-dir=tests/kirby"
]
},
"extra": {
"kirby-cms-path": "tests/kirby"
}
}

4619
site/plugins/kirby3-janitor/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
version: '3.8'
services:
webserver:
image: webdevops/php-apache:7.4
ports:
- 8000:80
environment:
WEB_DOCUMENT_ROOT: /app/tests/
WEB_ALIAS_DOMAIN: janitor.test
volumes:
- .:/app:rw

View File

@@ -0,0 +1 @@
.janitor{background-color:var(--color-text);color:#fff;border-radius:3px;padding:.5rem 1rem;line-height:1.25rem;text-align:left}.janitor:hover{background-color:#222}.janitor .k-button-text{opacity:1}.janitor.is-running{background-color:var(--color-border)}.janitor.is-running .k-button-text{color:var(--color-text)}.janitor.has-response{background-color:var(--color-text)}.janitor.is-success{background-color:var(--color-positive)}.janitor.has-error{background-color:var(--color-negative-light)}.visually-hidden{position:absolute;width:1px;height:1px;border:0;padding:0;margin:0;clip-path:inset(50%);overflow:hidden;white-space:nowrap}

View File

@@ -0,0 +1 @@
(()=>{(function(){"use strict";var p=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"janitor-wrapper"},[i("k-button",{class:["janitor",t.button.state],attrs:{id:t.id,icon:t.currentIcon,job:t.job,disabled:!t.isUnsaved&&t.hasChanges},on:{click:t.runJanitor}},[t._v(" "+t._s(t.button.label||t.label)+" ")]),i("a",{directives:[{name:"show",rawName:"v-show",value:t.downloadRequest,expression:"downloadRequest"}],ref:"downloadAnchor",staticClass:"visually-hidden",attrs:{href:t.downloadRequest,download:""}}),i("a",{directives:[{name:"show",rawName:"v-show",value:t.urlRequest,expression:"urlRequest"}],ref:"tabAnchor",staticClass:"visually-hidden",attrs:{href:t.urlRequest,target:"_blank"}})],1)},v=[],q="";function g(t,e,i,c,o,r,l,h){var s=typeof t=="function"?t.options:t;e&&(s.render=e,s.staticRenderFns=i,s._compiled=!0),c&&(s.functional=!0),r&&(s._scopeId="data-v-"+r);var a;if(l?(a=function(n){n=n||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,!n&&typeof __VUE_SSR_CONTEXT__!="undefined"&&(n=__VUE_SSR_CONTEXT__),o&&o.call(this,n),n&&n._registeredComponents&&n._registeredComponents.add(l)},s._ssrRegister=a):o&&(a=h?function(){o.call(this,(s.functional?this.parent:this).$root.$options.shadowRoot)}:o),a)if(s.functional){s._injectStyles=a;var R=s.render;s.render=function(k,b){return a.call(b),R(k,b)}}else{var f=s.beforeCreate;s.beforeCreate=f?[].concat(f,a):[a]}return{exports:t,options:s}}const u="janitor.runAfterAutosave",m={props:{label:String,progress:String,job:String,cooldown:Number,status:String,data:String,pageURI:String,clipboard:Boolean,unsaved:Boolean,autosave:Boolean,intab:Boolean,confirm:String,icon:{type:[Boolean,String],default:!1}},data(){return{button:{label:null,state:null},downloadRequest:null,clipboardRequest:null,urlRequest:null,isUnsaved:!1,icons:{"is-running":"janitorLoader","is-success":"check","has-error":"alert"}}},computed:{id(){var t;return"janitor-"+this.hashCode(this.job+((t=this.button.label)!=null?t:"")+this.pageURI)},hasChanges(){return this.$store.getters["content/hasChanges"]()},currentIcon(){var t;return(t=this.icons[this.status])!=null?t:this.icon}},created(){this.$events.$on("model.update",()=>sessionStorage.getItem(u)&&location.reload()),sessionStorage.getItem(u)===this.id&&(sessionStorage.removeItem(u),this.runJanitor())},methods:{hashCode(t){let e=0;if(t.length===0)return e;for(const i of t)e=(e<<5)-e+t.charCodeAt(i),e=e&e;return e},async runJanitor(){if(this.confirm&&!window.confirm(this.confirm))return;if(this.autosave&&this.hasChanges){const e=document.querySelector(".k-panel .k-form-buttons .k-view").lastChild;if(e){this.isUnsaved=!1,sessionStorage.setItem(u,this.id),this.simulateClick(e);return}}if(this.clipboard){this.clipboardRequest=this.data,this.button.label=this.progress,this.button.state="is-success",setTimeout(this.resetButton,this.cooldown),this.$nextTick(()=>{this.copyToClipboard(this.data)});return}if(this.clipboardRequest){await this.copyToClipboard(this.clipboardRequest),this.resetButton(),this.clipboardRequest=null;return}if(this.status)return;let t=this.job+"/"+encodeURIComponent(this.pageURI);this.data&&(t=t+"/"+encodeURIComponent(this.data)),this.getRequest(t)},async getRequest(t){var h;this.button.label=(h=this.progress)!=null?h:`${this.label} \u2026`,this.button.state="is-running";const{label:e,status:i,reload:c,href:o,download:r,clipboard:l}=await this.$api.get(t);e&&(this.button.label=e),i?this.button.state=i===200?"is-success":"has-error":this.button.state="has-response",c&&location.reload(),o&&(this.intab?(this.urlRequest=o,this.$nextTick(()=>{this.simulateClick(this.$refs.tabAnchor)})):location.href=o),r&&(this.downloadRequest=r,this.$nextTick(()=>{this.simulateClick(this.$refs.downloadAnchor)})),l?this.clipboardRequest=l:setTimeout(this.resetButton,this.cooldown)},resetButton(){this.button.label=null,this.button.state=null},simulateClick(t){const e=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window});t.dispatchEvent(e)},async copyToClipboard(t){try{await navigator.clipboard.writeText(t)}catch{console.error("navigator.clipboard is not available")}}}},d={};var _=g(m,p,v,!1,w,null,null,null);function w(t){for(let e in d)this[e]=d[e]}var C=function(){return _.exports}();window.panel.plugin("bnomei/janitor",{fields:{janitor:C},icons:{janitorLoader:'<g fill="none" fill-rule="evenodd"><g transform="translate(1 1)" stroke-width="1.75"><circle cx="7" cy="7" r="7.2" stroke="#000" stroke-opacity=".2"/><path d="M14.2,7c0-4-3.2-7.2-7.2-7.2" stroke="#000"><animateTransform attributeName="transform" type="rotate" from="0 7 7" to="360 7 7" dur="1s" repeatCount="indefinite"/></path></g></g>'}})})();})();

View File

@@ -0,0 +1,210 @@
<?php
@include_once __DIR__ . '/vendor/autoload.php';
/*
janitor [noun]
one who keeps the premises of a building (such as an apartment or
office) clean, tends the heating system, and makes minor repairs
*/
Kirby::plugin('bnomei/janitor', [
'options' => [
'jobs' => [],
'jobs-defaults' => [
'clean' => 'Bnomei\\CleanCacheFilesJob', // legacy
'cleanCache' => 'Bnomei\\CleanCacheFilesJob',
'flush' => 'Bnomei\\FlushPagesCacheJob', // legacy
'flushPages' => 'Bnomei\\FlushPagesCacheJob',
'cleanSessions' => 'Bnomei\\CleanSessionsJob',
'cleanContent' => 'Bnomei\\CleanContentJob',
'flushSessions' => 'Bnomei\\FlushSessionFilesJob',
'flushLapse' => 'Bnomei\\FlushLapseJob',
'flushRedisDB' => 'Bnomei\\FlushRedisDBJob',
'reindexAutoID' => 'Bnomei\\ReindexAutoIDJob',
'reindexSearch' => 'Bnomei\\ReindexSearchForKirbyJob',
'backupZip' => 'Bnomei\\BackupZipJob',
'render' => 'Bnomei\\RenderJob',
'thumbs' => 'Bnomei\\ThumbsJob',
],
'jobs-extends' => [
'bnomei.lapse.jobs', // https://github.com/bnomei/kirby3-lapse/blob/master/index.php#L10
],
'label.cooldown' => 2000, // ms
'secret' => null,
'thumbsOnUpload' => false,
'renderSiteUrl' => function () {
$url = site()->url();
// $url = 'https://www.example.com/';
return php_sapi_name() === 'cli' ? $url : '';
},
'log.enabled' => false,
'log.fn' => function (string $msg, string $level = 'info', array $context = []): bool {
if (option('bnomei.janitor.log.enabled')) {
if (function_exists('monolog')) {
monolog()->{$level}($msg, $context);
} elseif (function_exists('kirbyLog')) {
kirbyLog('bnomei.janitor.log')->log($msg, $level, $context);
}
return true;
}
return false;
},
'icon' => false,
],
'snippets' => [
'maintenance' => __DIR__ . '/snippets/maintenance.php',
],
'fields' => [
'janitor' => [
'props' => [
'label' => function ($label = null) {
return \Kirby\Toolkit\I18n::translate($label, $label);
},
'progress' => function ($progress = null) {
return \Kirby\Toolkit\I18n::translate($progress, $progress);
},
'job' => function (?string $job = null) {
return 'plugin-janitor/' . $job;
},
'cooldown' => function (int $cooldownMilliseconds = 2000) {
return intval(option('bnomei.janitor.label.cooldown', $cooldownMilliseconds));
},
'data' => function (?string $data = null) {
$data = \Bnomei\Janitor::query($data, $this->model());
return str_replace(
'/',
'+S_L_A_S_H+',
\Kirby\Toolkit\I18n::translate($data, $data)
);
},
'clipboard' => function ($clipboard = null) {
return \Bnomei\Janitor::isTrue($clipboard);
},
'unsaved' => function ($allowUnsaved = true) {
return \Bnomei\Janitor::isTrue($allowUnsaved);
},
'autosave' => function ($doAutosave = false) {
return \Bnomei\Janitor::isTrue($doAutosave);
},
'intab' => function ($intab = false) {
return \Bnomei\Janitor::isTrue($intab);
},
'confirm' => function ($confirm = '') {
return $confirm;
},
'pageURI' => function () {
$uri = kirby()->site()->homePageId();
if (is_a($this->model(), \Kirby\Cms\Page::class)) {
$uri = $this->model()->uri();
}
if (is_a($this->model(), \Kirby\Cms\File::class)) {
$uri = $this->model()->parent()->uri();
}
if (is_a($this->model(), \Kirby\Cms\User::class)) {
$uri = $this->model()->panelPath();
}
if (is_a($this->model(), \Kirby\Cms\Site::class)) {
$uri = '$'; // any not empty string so route /$/DATA is used
}
return str_replace('/', '+', $uri);
},
'icon' => function ($icon = false) {
return $icon ?? option('bnomei.janitor.icon');
},
],
],
],
'routes' => [
[
'pattern' => 'plugin-janitor/(:any)/(:any)',
'action' => function (string $job, string $secret) {
$janitor = new \Bnomei\Janitor();
$janitor->log('janitor-api-secret', 'debug');
$response = $janitor->jobWithSecret($secret, $job);
return Kirby\Http\Response::json($response, A::get($response, 'status', 400));
},
],
],
'hooks' => [
'file.create:after' => function ($file) {
if (option('bnomei.janitor.thumbsOnUpload') && $file->isResizable()) {
janitor('render', $file->page(), 'page');
janitor('thumbs', $file->page(), 'page');
}
},
'route:before' => function () {
$isPanel = strpos(
kirby()->request()->url()->toString(),
kirby()->urls()->panel()
) !== false;
$isApi = strpos(
kirby()->request()->url()->toString(),
kirby()->urls()->api()
) !== false;
if (!$isPanel && !$isApi) {
if (F::exists(kirby()->roots()->index() . '/down')) {
snippet('maintenance');
die;
}
}
},
],
'api' => [
'routes' => [
[
'pattern' => 'plugin-janitor/(:any)/(:any)/(:any)',
'action' => function (string $job, string $page, string $data) {
$janitor = \Bnomei\Janitor::singleton();
$janitor->log('janitor-api-auth', 'debug');
return $janitor->job($job, [
'contextPage' => $page,
'contextData' => $data,
]);
},
],
[
'pattern' => 'plugin-janitor/(:any)/(:any)',
'action' => function (string $job, string $page) {
$janitor = \Bnomei\Janitor::singleton();
$janitor->log('janitor-api-auth', 'debug');
return $janitor->job($job, [
'contextPage' => $page,
]);
},
],
[
'pattern' => 'plugin-janitor/(:any)',
'action' => function (string $job) {
$janitor = \Bnomei\Janitor::singleton();
$janitor->log('janitor-api-auth', 'debug');
return $janitor->job($job);
}
],
],
],
]);
if (!class_exists('Bnomei\Janitor')) {
require_once __DIR__ . '/classes/Janitor.php';
}
if (!function_exists('janitor')) {
function janitor(string $job, ?\Kirby\Cms\Page $contextPage = null, ?string $contextData = null, bool $dump = false)
{
$janitor = \Bnomei\Janitor::singleton();
$janitor->log('janitor()', 'debug');
$response = $janitor->job($job, [
'contextPage' => $contextPage ? urlencode(str_replace('/', '+', $contextPage->uri())) : '',
'contextData' => $contextData ? urlencode($contextData) : '',
]);
if ($dump) {
return $response;
}
return intval(A::get($response, 'status')) === 200;
}
}

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
foreach([// janitor from zip with vendor
__DIR__ . '/vendor/autoload.php',
// janitor from composer in site/plugins/kirby3-janitor
realpath(__DIR__ . '/../../../') . '/vendor/autoload.php',
] as $file) {
if (file_exists($file)) {
require $file;
break;
}
}
ini_set('display_errors', '1');
$climate = new \League\CLImate\CLImate();
$climate->arguments->add([
'help' => [
'prefix' => 'h',
'longPrefix' => 'help',
'description' => 'Display the help',
'noValue' => true,
],
'list' => [
'prefix' => 'l',
'longPrefix' => 'list',
'description' => 'List all registered jobs',
'noValue' => true,
],
'format' => [
'prefix' => 'f',
'longPrefix' => 'format',
'description' => 'Format the output as "label", "table" or "json"',
'defaultValue' => 'label',
],
'kirby' => [
'prefix' => 'k',
'longPrefix' => 'kirby',
'description' => 'Relative path to Kirbys public folder',
'defaultValue' => '/',
],
'verbose' => [
'prefix' => 'v',
'longPrefix' => 'verbose',
'description' => 'Show debug info',
'noValue' => true,
],
'job' => [
'description' => 'Run a job',
],
'quiet' => [
'prefix' => 'q',
'longPrefix' => 'quiet',
'description' => 'Run jobs silently',
'noValue' => true,
],
'tinker' => [
'prefix' => 't',
'longPrefix' => 'tinker',
'description' => 'Run a REPL session',
'noValue' => true,
],
'down' => [
'prefix' => 'd',
'longPrefix' => 'down',
'description' => 'Start maintenance mode',
'noValue' => true,
],
'up' => [
'prefix' => 'u',
'longPrefix' => 'up',
'description' => 'Stop maintenance mode',
'noValue' => true,
],
]);
$climate->arguments->parse();
$verbose = $climate->arguments->defined('verbose');
// COMMAND: kirby
$kirbyPublicFolder = null;
foreach([ // site/plugins/kirby3-janitor => /index.php
realpath(__DIR__ . '/../../../'),
// site/plugins/kirby3-janitor => /public/index.php
realpath(__DIR__ . '/../../../public'),
] as $dir) {
if ($dir !== false && file_exists($dir . '/index.php')) {
$kirbyPublicFolder = $dir;
break;
}
}
if ($climate->arguments->defined('kirby')) {
$kirbyPublicFolder = realpath(__DIR__ . DIRECTORY_SEPARATOR . ltrim($climate->arguments->get('kirby'), DIRECTORY_SEPARATOR));
}
if ($kirbyPublicFolder) {
$kirbyLoader = $kirbyPublicFolder . DIRECTORY_SEPARATOR . 'janitor-' . sha1(__DIR__) . '.php';
if (! file_exists($kirbyLoader)) {
file_put_contents(
$kirbyLoader,
str_replace('echo ', '// echo ',
file_get_contents($kirbyPublicFolder . DIRECTORY_SEPARATOR . 'index.php')
)
);
if ($verbose) {
$climate->backgroundYellow()->out('ATTENTION! Janitor created this file to load the Kirby instance: ' . $kirbyLoader);
}
}
include $kirbyLoader;
if ($verbose) {
$climate->backgroundCyan()->out('Using Kirby instance from: ' . $kirbyLoader);
}
}
\Bnomei\Janitor::climate($climate);
$janitor = new \Bnomei\Janitor();
// COMMAND: help
$command = $climate->arguments->defined('help');
if ($command) {
$climate->usage();
}
// COMMAND: list
$command = $climate->arguments->defined('list');
if ($command) {
foreach ($janitor->listJobs() as $key) {
$climate->out($key);
}
}
// COMMAND: quiet
$command = $climate->arguments->get('quiet');
if ($command) {
$climate->output->add('quiet', new \Bnomei\QuietWriter());
$climate->output->defaultTo('quiet');
}
// COMMAND: tinker
$command = $climate->arguments->get('tinker');
if ($command) {
while (true) eval($climate->input('>>> ')->prompt());
}
// COMMAND: down
$command = $climate->arguments->get('down');
if ($command) {
file_put_contents(kirby()->roots()->index() . '/down', date('c'));
}
// COMMAND: up
$command = $climate->arguments->get('up');
if ($command) {
$down = kirby()->roots()->index() . '/down';
if (file_exists($down)) {
unlink($down);
}
}
// COMMAND: job
$job = $climate->arguments->get('job');
if ($job) {
$format = $climate->arguments->get('format');
if ($format === 'class') {
$janitor->job($job, [], $climate);
} elseif ($format === 'json') {
$climate->json($janitor->job($job));
} elseif ($format === 'table') {
$table = [];
foreach ($janitor->job($job) as $key => $value) {
$table[] = [$key, $value];
}
$climate->table($table);
} else {
$data = $janitor->job($job);
$status = $data['status'];
$label = array_key_exists('label', $data) ? $data['label'] : $status;
if ($status === 200) {
$climate->lightGreen($label);
} elseif ($status === 204) {
$climate->lightRed($label);
} elseif ($status === 404) {
$climate->backgroundRed($label);
} else {
$climate->out($label);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
{
"private": true,
"scripts": {
"dev": "kirbyup src/index.js --watch",
"build": "kirbyup src/index.js",
"lint": "eslint \"src/**/*.{js,vue}\"",
"lint:fix": "npm run lint -- --fix",
"format": "prettier --write \"src/**/*.{js,vue}\""
},
"devDependencies": {
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-vue": "^7.19.1",
"kirbyup": "^0.18.0"
}
}

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Maintenance</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
padding: 10%;
text-align: center;
line-height: 1.5em;
}
a {
color: inherit;
}
a:hover,
a:focus {
color: #000;
}
p {
max-width: 30em;
margin: 0 auto;
}
.notice {
font-weight: bold;
}
.admin-advice {
font-size: .8em;
font-style: italic;
color: #999;
padding-top: 3rem;
}
</style>
</head>
<body>
<p class="notice">
This page is currently in maintenance.
</p>
</body>
</html>

View File

@@ -0,0 +1,296 @@
<template>
<div class="janitor-wrapper">
<k-button
:id="id"
:class="['janitor', button.state]"
:icon="currentIcon"
:job="job"
:disabled="!isUnsaved && hasChanges"
@click="runJanitor"
>
{{ button.label || label }}
</k-button>
<a
v-show="downloadRequest"
ref="downloadAnchor"
class="visually-hidden"
:href="downloadRequest"
download
/>
<a
v-show="urlRequest"
ref="tabAnchor"
class="visually-hidden"
:href="urlRequest"
target="_blank"
/>
</div>
</template>
<script>
const STORAGE_ID = "janitor.runAfterAutosave";
export default {
props: {
label: String,
progress: String,
job: String,
cooldown: Number,
status: String,
data: String,
pageURI: String,
clipboard: Boolean,
unsaved: Boolean,
autosave: Boolean,
intab: Boolean,
confirm: String,
icon: {
type: [Boolean, String],
default: false,
},
},
data() {
return {
button: {
label: null,
state: null,
},
downloadRequest: null,
clipboardRequest: null,
urlRequest: null,
isUnsaved: false,
icons: {
"is-running": "janitorLoader",
"is-success": "check",
"has-error": "alert",
},
};
},
computed: {
id() {
return (
"janitor-" +
this.hashCode(this.job + (this.button.label ?? "") + this.pageURI)
);
},
hasChanges() {
return this.$store.getters["content/hasChanges"]();
},
currentIcon() {
return this.icons[this.status] ?? this.icon;
},
},
created() {
this.$events.$on(
"model.update",
() => sessionStorage.getItem(STORAGE_ID) && location.reload()
);
if (sessionStorage.getItem(STORAGE_ID) === this.id) {
sessionStorage.removeItem(STORAGE_ID);
this.runJanitor();
}
},
methods: {
/**
* Source: https://stackoverflow.com/a/8831937
*/
hashCode(str) {
let hash = 0;
if (str.length === 0) {
return hash;
}
for (const i of str) {
hash = (hash << 5) - hash + str.charCodeAt(i);
// convert to 32bit integer
hash = hash & hash;
}
return hash;
},
async runJanitor() {
if (this.confirm && !window.confirm(this.confirm)) {
return;
}
if (this.autosave && this.hasChanges) {
// lock janitor button, press save and listen to `model.update` event
const saveButton = document.querySelector(
".k-panel .k-form-buttons .k-view"
).lastChild;
// revert & save
if (saveButton) {
this.isUnsaved = false;
sessionStorage.setItem(STORAGE_ID, this.id);
this.simulateClick(saveButton);
return;
}
}
if (this.clipboard) {
this.clipboardRequest = this.data;
this.button.label = this.progress;
this.button.state = "is-success";
setTimeout(this.resetButton, this.cooldown);
this.$nextTick(() => {
this.copyToClipboard(this.data);
});
return;
}
if (this.clipboardRequest) {
await this.copyToClipboard(this.clipboardRequest);
this.resetButton();
this.clipboardRequest = null;
return;
}
if (this.status) {
return;
}
let url = this.job + "/" + encodeURIComponent(this.pageURI);
if (this.data) {
url = url + "/" + encodeURIComponent(this.data);
}
this.getRequest(url);
},
async getRequest(url) {
this.button.label = this.progress ?? `${this.label}`;
this.button.state = "is-running";
const { label, status, reload, href, download, clipboard } =
await this.$api.get(url);
if (label) {
this.button.label = label;
}
if (status) {
this.button.state = status === 200 ? "is-success" : "has-error";
} else {
this.button.state = "has-response";
}
if (reload) {
location.reload();
}
if (href) {
if (this.intab) {
this.urlRequest = href;
this.$nextTick(() => {
this.simulateClick(this.$refs.tabAnchor);
});
} else {
location.href = href;
}
}
if (download) {
this.downloadRequest = download;
this.$nextTick(() => {
this.simulateClick(this.$refs.downloadAnchor);
});
}
if (clipboard) {
this.clipboardRequest = clipboard;
} else {
setTimeout(this.resetButton, this.cooldown);
}
},
resetButton() {
this.button.label = null;
this.button.state = null;
},
simulateClick(element) {
const evt = new MouseEvent("click", {
bubbles: true,
cancelable: true,
view: window,
});
element.dispatchEvent(evt);
},
async copyToClipboard(content) {
try {
await navigator.clipboard.writeText(content);
} catch (err) {
console.error("navigator.clipboard is not available");
}
},
},
};
</script>
<style>
.janitor {
background-color: var(--color-text);
color: white;
border-radius: 3px;
padding: 0.5rem 1rem;
line-height: 1.25rem;
text-align: left;
}
.janitor:hover {
background-color: #222;
}
.janitor .k-button-text {
opacity: 1;
}
.janitor.is-running {
background-color: var(--color-border);
}
.janitor.is-running .k-button-text {
color: var(--color-text);
}
.janitor.has-response {
background-color: var(--color-text);
}
.janitor.is-success {
background-color: var(--color-positive);
}
.janitor.has-error {
background-color: var(--color-negative-light);
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
border: 0;
padding: 0;
margin: 0;
clip-path: inset(50%);
overflow: hidden;
white-space: nowrap;
}
</style>

View File

@@ -0,0 +1,11 @@
import Janitor from "./components/fields/Janitor.vue";
window.panel.plugin("bnomei/janitor", {
fields: {
janitor: Janitor,
},
icons: {
janitorLoader:
'<g fill="none" fill-rule="evenodd"><g transform="translate(1 1)" stroke-width="1.75"><circle cx="7" cy="7" r="7.2" stroke="#000" stroke-opacity=".2"/><path d="M14.2,7c0-4-3.2-7.2-7.2-7.2" stroke="#000"><animateTransform attributeName="transform" type="rotate" from="0 7 7" to="360 7 7" dur="1s" repeatCount="indefinite"/></path></g></g>',
},
});

View File

@@ -6,6 +6,25 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Bnomei\\BackupZipJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/BackupZipJob.php',
'Bnomei\\CleanCacheFilesJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/CleanCacheFilesJob.php',
'Bnomei\\CleanContentJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/CleanContentJob.php',
'Bnomei\\CleanSessionsJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/CleanSessionsJob.php',
'Bnomei\\ContextJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/ContextJob.php',
'Bnomei\\FlushLapseJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/FlushLapseJob.php',
'Bnomei\\FlushPagesCacheJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/FlushPagesCacheJob.php',
'Bnomei\\FlushRedisDBJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/FlushRedisDBJob.php',
'Bnomei\\FlushSessionFilesJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/FlushSessionFilesJob.php',
'Bnomei\\Janitor' => $baseDir . '/site/plugins/kirby3-janitor/classes/Janitor.php',
'Bnomei\\JanitorJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/JanitorJob.php',
'Bnomei\\Job' => $baseDir . '/site/plugins/kirby3-janitor/classes/Job.php',
'Bnomei\\QuietWriter' => $baseDir . '/site/plugins/kirby3-janitor/classes/QuietWriter.php',
'Bnomei\\ReindexAutoIDJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/ReindexAutoIDJob.php',
'Bnomei\\ReindexSearchForKirbyJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/ReindexSearchForKirbyJob.php',
'Bnomei\\RenderJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/RenderJob.php',
'Bnomei\\ThumbsJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/ThumbsJob.php',
'Bnomei\\WhistleJob' => $baseDir . '/site/plugins/kirby3-janitor/classes/WhistleJob.php',
'Composer\\CaBundle\\CaBundle' => $vendorDir . '/composer/ca-bundle/src/CaBundle.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'Embed\\Adapters\\Archive\\Api' => $vendorDir . '/embed/embed/src/Adapters/Archive/Api.php',
@@ -400,6 +419,93 @@ return array(
'Laminas\\Escaper\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-escaper/src/Exception/ExceptionInterface.php',
'Laminas\\Escaper\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-escaper/src/Exception/InvalidArgumentException.php',
'Laminas\\Escaper\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-escaper/src/Exception/RuntimeException.php',
'League\\CLImate\\Argument\\Argument' => $vendorDir . '/league/climate/src/Argument/Argument.php',
'League\\CLImate\\Argument\\Filter' => $vendorDir . '/league/climate/src/Argument/Filter.php',
'League\\CLImate\\Argument\\Manager' => $vendorDir . '/league/climate/src/Argument/Manager.php',
'League\\CLImate\\Argument\\Parser' => $vendorDir . '/league/climate/src/Argument/Parser.php',
'League\\CLImate\\Argument\\Summary' => $vendorDir . '/league/climate/src/Argument/Summary.php',
'League\\CLImate\\CLImate' => $vendorDir . '/league/climate/src/CLImate.php',
'League\\CLImate\\Decorator\\Component\\BackgroundColor' => $vendorDir . '/league/climate/src/Decorator/Component/BackgroundColor.php',
'League\\CLImate\\Decorator\\Component\\BaseDecorator' => $vendorDir . '/league/climate/src/Decorator/Component/BaseDecorator.php',
'League\\CLImate\\Decorator\\Component\\Color' => $vendorDir . '/league/climate/src/Decorator/Component/Color.php',
'League\\CLImate\\Decorator\\Component\\Command' => $vendorDir . '/league/climate/src/Decorator/Component/Command.php',
'League\\CLImate\\Decorator\\Component\\DecoratorInterface' => $vendorDir . '/league/climate/src/Decorator/Component/DecoratorInterface.php',
'League\\CLImate\\Decorator\\Component\\Format' => $vendorDir . '/league/climate/src/Decorator/Component/Format.php',
'League\\CLImate\\Decorator\\Parser\\Ansi' => $vendorDir . '/league/climate/src/Decorator/Parser/Ansi.php',
'League\\CLImate\\Decorator\\Parser\\NonAnsi' => $vendorDir . '/league/climate/src/Decorator/Parser/NonAnsi.php',
'League\\CLImate\\Decorator\\Parser\\Parser' => $vendorDir . '/league/climate/src/Decorator/Parser/Parser.php',
'League\\CLImate\\Decorator\\Parser\\ParserFactory' => $vendorDir . '/league/climate/src/Decorator/Parser/ParserFactory.php',
'League\\CLImate\\Decorator\\Parser\\ParserImporter' => $vendorDir . '/league/climate/src/Decorator/Parser/ParserImporter.php',
'League\\CLImate\\Decorator\\Style' => $vendorDir . '/league/climate/src/Decorator/Style.php',
'League\\CLImate\\Decorator\\Tags' => $vendorDir . '/league/climate/src/Decorator/Tags.php',
'League\\CLImate\\Exceptions\\Exception' => $vendorDir . '/league/climate/src/Exceptions/Exception.php',
'League\\CLImate\\Exceptions\\InvalidArgumentException' => $vendorDir . '/league/climate/src/Exceptions/InvalidArgumentException.php',
'League\\CLImate\\Exceptions\\RuntimeException' => $vendorDir . '/league/climate/src/Exceptions/RuntimeException.php',
'League\\CLImate\\Exceptions\\UnexpectedValueException' => $vendorDir . '/league/climate/src/Exceptions/UnexpectedValueException.php',
'League\\CLImate\\Logger' => $vendorDir . '/league/climate/src/Logger.php',
'League\\CLImate\\Settings\\Art' => $vendorDir . '/league/climate/src/Settings/Art.php',
'League\\CLImate\\Settings\\Manager' => $vendorDir . '/league/climate/src/Settings/Manager.php',
'League\\CLImate\\Settings\\SettingsImporter' => $vendorDir . '/league/climate/src/Settings/SettingsImporter.php',
'League\\CLImate\\Settings\\SettingsInterface' => $vendorDir . '/league/climate/src/Settings/SettingsInterface.php',
'League\\CLImate\\TerminalObject\\Basic\\BasicTerminalObject' => $vendorDir . '/league/climate/src/TerminalObject/Basic/BasicTerminalObject.php',
'League\\CLImate\\TerminalObject\\Basic\\BasicTerminalObjectInterface' => $vendorDir . '/league/climate/src/TerminalObject/Basic/BasicTerminalObjectInterface.php',
'League\\CLImate\\TerminalObject\\Basic\\Border' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Border.php',
'League\\CLImate\\TerminalObject\\Basic\\Br' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Br.php',
'League\\CLImate\\TerminalObject\\Basic\\Clear' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Clear.php',
'League\\CLImate\\TerminalObject\\Basic\\ClearLine' => $vendorDir . '/league/climate/src/TerminalObject/Basic/ClearLine.php',
'League\\CLImate\\TerminalObject\\Basic\\Columns' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Columns.php',
'League\\CLImate\\TerminalObject\\Basic\\Draw' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Draw.php',
'League\\CLImate\\TerminalObject\\Basic\\Dump' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Dump.php',
'League\\CLImate\\TerminalObject\\Basic\\Flank' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Flank.php',
'League\\CLImate\\TerminalObject\\Basic\\Inline' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Inline.php',
'League\\CLImate\\TerminalObject\\Basic\\Json' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Json.php',
'League\\CLImate\\TerminalObject\\Basic\\Out' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Out.php',
'League\\CLImate\\TerminalObject\\Basic\\Repeatable' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Repeatable.php',
'League\\CLImate\\TerminalObject\\Basic\\Tab' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Tab.php',
'League\\CLImate\\TerminalObject\\Basic\\Table' => $vendorDir . '/league/climate/src/TerminalObject/Basic/Table.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Animation' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Animation.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Animation\\Keyframe' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Animation/Keyframe.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\Checkbox' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Checkbox/Checkbox.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\CheckboxGroup' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Checkbox/CheckboxGroup.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\RadioGroup' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Checkbox/RadioGroup.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkboxes' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Checkboxes.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Confirm' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Confirm.php',
'League\\CLImate\\TerminalObject\\Dynamic\\DynamicTerminalObject' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/DynamicTerminalObject.php',
'League\\CLImate\\TerminalObject\\Dynamic\\DynamicTerminalObjectInterface' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/DynamicTerminalObjectInterface.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Input' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Input.php',
'League\\CLImate\\TerminalObject\\Dynamic\\InputAbstract' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/InputAbstract.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Padding' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Padding.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Password' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Password.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Progress' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Progress.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Radio' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Radio.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Spinner' => $vendorDir . '/league/climate/src/TerminalObject/Dynamic/Spinner.php',
'League\\CLImate\\TerminalObject\\Helper\\Art' => $vendorDir . '/league/climate/src/TerminalObject/Helper/Art.php',
'League\\CLImate\\TerminalObject\\Helper\\Sleeper' => $vendorDir . '/league/climate/src/TerminalObject/Helper/Sleeper.php',
'League\\CLImate\\TerminalObject\\Helper\\SleeperInterface' => $vendorDir . '/league/climate/src/TerminalObject/Helper/SleeperInterface.php',
'League\\CLImate\\TerminalObject\\Helper\\StringLength' => $vendorDir . '/league/climate/src/TerminalObject/Helper/StringLength.php',
'League\\CLImate\\TerminalObject\\Router\\BaseRouter' => $vendorDir . '/league/climate/src/TerminalObject/Router/BaseRouter.php',
'League\\CLImate\\TerminalObject\\Router\\BasicRouter' => $vendorDir . '/league/climate/src/TerminalObject/Router/BasicRouter.php',
'League\\CLImate\\TerminalObject\\Router\\DynamicRouter' => $vendorDir . '/league/climate/src/TerminalObject/Router/DynamicRouter.php',
'League\\CLImate\\TerminalObject\\Router\\ExtensionCollection' => $vendorDir . '/league/climate/src/TerminalObject/Router/ExtensionCollection.php',
'League\\CLImate\\TerminalObject\\Router\\Router' => $vendorDir . '/league/climate/src/TerminalObject/Router/Router.php',
'League\\CLImate\\TerminalObject\\Router\\RouterInterface' => $vendorDir . '/league/climate/src/TerminalObject/Router/RouterInterface.php',
'League\\CLImate\\Util\\Cursor' => $vendorDir . '/league/climate/src/Util/Cursor.php',
'League\\CLImate\\Util\\Helper' => $vendorDir . '/league/climate/src/Util/Helper.php',
'League\\CLImate\\Util\\Output' => $vendorDir . '/league/climate/src/Util/Output.php',
'League\\CLImate\\Util\\OutputImporter' => $vendorDir . '/league/climate/src/Util/OutputImporter.php',
'League\\CLImate\\Util\\Reader\\ReaderInterface' => $vendorDir . '/league/climate/src/Util/Reader/ReaderInterface.php',
'League\\CLImate\\Util\\Reader\\Stdin' => $vendorDir . '/league/climate/src/Util/Reader/Stdin.php',
'League\\CLImate\\Util\\System\\Linux' => $vendorDir . '/league/climate/src/Util/System/Linux.php',
'League\\CLImate\\Util\\System\\System' => $vendorDir . '/league/climate/src/Util/System/System.php',
'League\\CLImate\\Util\\System\\SystemFactory' => $vendorDir . '/league/climate/src/Util/System/SystemFactory.php',
'League\\CLImate\\Util\\System\\Windows' => $vendorDir . '/league/climate/src/Util/System/Windows.php',
'League\\CLImate\\Util\\UtilFactory' => $vendorDir . '/league/climate/src/Util/UtilFactory.php',
'League\\CLImate\\Util\\UtilImporter' => $vendorDir . '/league/climate/src/Util/UtilImporter.php',
'League\\CLImate\\Util\\Writer\\Buffer' => $vendorDir . '/league/climate/src/Util/Writer/Buffer.php',
'League\\CLImate\\Util\\Writer\\File' => $vendorDir . '/league/climate/src/Util/Writer/File.php',
'League\\CLImate\\Util\\Writer\\StdErr' => $vendorDir . '/league/climate/src/Util/Writer/StdErr.php',
'League\\CLImate\\Util\\Writer\\StdOut' => $vendorDir . '/league/climate/src/Util/Writer/StdOut.php',
'League\\CLImate\\Util\\Writer\\WriterInterface' => $vendorDir . '/league/climate/src/Util/Writer/WriterInterface.php',
'League\\ColorExtractor\\Color' => $vendorDir . '/league/color-extractor/src/League/ColorExtractor/Color.php',
'League\\ColorExtractor\\ColorExtractor' => $vendorDir . '/league/color-extractor/src/League/ColorExtractor/ColorExtractor.php',
'League\\ColorExtractor\\Palette' => $vendorDir . '/league/color-extractor/src/League/ColorExtractor/Palette.php',
@@ -450,6 +556,7 @@ return array(
'PHPMailer\\PHPMailer\\SMTP' => $vendorDir . '/phpmailer/phpmailer/src/SMTP.php',
'Parsedown' => $baseDir . '/kirby/dependencies/parsedown/Parsedown.php',
'ParsedownExtra' => $baseDir . '/kirby/dependencies/parsedown-extra/ParsedownExtra.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php',
'Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php',
'Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php',
@@ -478,13 +585,42 @@ return array(
'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php',
'Seld\\CliPrompt\\CliPrompt' => $vendorDir . '/seld/cli-prompt/src/CliPrompt.php',
'Spyc' => $baseDir . '/kirby/dependencies/spyc/Spyc.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php',
'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php',
'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php',
'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php',
'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php',
'Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php',
'Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php',
'Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php',
'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php',
'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php',
'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php',
'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php',
'Symfony\\Polyfill\\Intl\\Idn\\Info' => $vendorDir . '/symfony/polyfill-intl-idn/Info.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php',
'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php',
'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php',
'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Whoops\\Exception\\ErrorException' => $vendorDir . '/filp/whoops/src/Whoops/Exception/ErrorException.php',
'Whoops\\Exception\\Formatter' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Formatter.php',
'Whoops\\Exception\\Frame' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Frame.php',

View File

@@ -6,8 +6,10 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'09fc349b549513bf7f4291502426f919' => $vendorDir . '/embed/embed/src/functions.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',

View File

@@ -7,19 +7,24 @@ $baseDir = dirname($vendorDir);
return array(
'Whoops\\' => array($vendorDir . '/filp/whoops/src/Whoops'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'ML\\JsonLD\\' => array($vendorDir . '/ml/json-ld'),
'League\\CLImate\\' => array($vendorDir . '/league/climate/src'),
'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'),
'Kirby\\' => array($baseDir . '/kirby/src', $vendorDir . '/getkirby/composer-installer/src'),
'HtmlParser\\' => array($vendorDir . '/oscarotero/html-parser/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'Embed\\' => array($vendorDir . '/embed/embed/src'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Bnomei\\' => array($baseDir . '/site/plugins/kirby3-janitor/classes'),
'' => array($vendorDir . '/league/color-extractor/src'),
);

View File

@@ -7,8 +7,10 @@ namespace Composer\Autoload;
class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
{
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'09fc349b549513bf7f4291502426f919' => __DIR__ . '/..' . '/embed/embed/src/functions.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -23,9 +25,12 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
),
'S' =>
array (
'Symfony\\Polyfill\\Php80\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'Symfony\\Component\\Finder\\' => 25,
'Seld\\CliPrompt\\' => 15,
),
'P' =>
array (
@@ -40,6 +45,7 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
),
'L' =>
array (
'League\\CLImate\\' => 15,
'Laminas\\Escaper\\' => 16,
),
'K' =>
@@ -62,6 +68,10 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
array (
'Composer\\CaBundle\\' => 18,
),
'B' =>
array (
'Bnomei\\' => 7,
),
);
public static $prefixDirsPsr4 = array (
@@ -69,6 +79,10 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
array (
0 => __DIR__ . '/..' . '/filp/whoops/src/Whoops',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
@@ -81,6 +95,14 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
),
'Symfony\\Component\\Finder\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/finder',
),
'Seld\\CliPrompt\\' =>
array (
0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
),
'Psr\\Log\\' =>
array (
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
@@ -102,6 +124,10 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
array (
0 => __DIR__ . '/..' . '/ml/json-ld',
),
'League\\CLImate\\' =>
array (
0 => __DIR__ . '/..' . '/league/climate/src',
),
'Laminas\\Escaper\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-escaper/src',
@@ -127,6 +153,10 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
array (
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
),
'Bnomei\\' =>
array (
0 => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes',
),
);
public static $fallbackDirsPsr4 = array (
@@ -155,6 +185,25 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
);
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Bnomei\\BackupZipJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/BackupZipJob.php',
'Bnomei\\CleanCacheFilesJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/CleanCacheFilesJob.php',
'Bnomei\\CleanContentJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/CleanContentJob.php',
'Bnomei\\CleanSessionsJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/CleanSessionsJob.php',
'Bnomei\\ContextJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/ContextJob.php',
'Bnomei\\FlushLapseJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/FlushLapseJob.php',
'Bnomei\\FlushPagesCacheJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/FlushPagesCacheJob.php',
'Bnomei\\FlushRedisDBJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/FlushRedisDBJob.php',
'Bnomei\\FlushSessionFilesJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/FlushSessionFilesJob.php',
'Bnomei\\Janitor' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/Janitor.php',
'Bnomei\\JanitorJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/JanitorJob.php',
'Bnomei\\Job' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/Job.php',
'Bnomei\\QuietWriter' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/QuietWriter.php',
'Bnomei\\ReindexAutoIDJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/ReindexAutoIDJob.php',
'Bnomei\\ReindexSearchForKirbyJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/ReindexSearchForKirbyJob.php',
'Bnomei\\RenderJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/RenderJob.php',
'Bnomei\\ThumbsJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/ThumbsJob.php',
'Bnomei\\WhistleJob' => __DIR__ . '/../..' . '/site/plugins/kirby3-janitor/classes/WhistleJob.php',
'Composer\\CaBundle\\CaBundle' => __DIR__ . '/..' . '/composer/ca-bundle/src/CaBundle.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'Embed\\Adapters\\Archive\\Api' => __DIR__ . '/..' . '/embed/embed/src/Adapters/Archive/Api.php',
@@ -549,6 +598,93 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
'Laminas\\Escaper\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/ExceptionInterface.php',
'Laminas\\Escaper\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/InvalidArgumentException.php',
'Laminas\\Escaper\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/RuntimeException.php',
'League\\CLImate\\Argument\\Argument' => __DIR__ . '/..' . '/league/climate/src/Argument/Argument.php',
'League\\CLImate\\Argument\\Filter' => __DIR__ . '/..' . '/league/climate/src/Argument/Filter.php',
'League\\CLImate\\Argument\\Manager' => __DIR__ . '/..' . '/league/climate/src/Argument/Manager.php',
'League\\CLImate\\Argument\\Parser' => __DIR__ . '/..' . '/league/climate/src/Argument/Parser.php',
'League\\CLImate\\Argument\\Summary' => __DIR__ . '/..' . '/league/climate/src/Argument/Summary.php',
'League\\CLImate\\CLImate' => __DIR__ . '/..' . '/league/climate/src/CLImate.php',
'League\\CLImate\\Decorator\\Component\\BackgroundColor' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/BackgroundColor.php',
'League\\CLImate\\Decorator\\Component\\BaseDecorator' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/BaseDecorator.php',
'League\\CLImate\\Decorator\\Component\\Color' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/Color.php',
'League\\CLImate\\Decorator\\Component\\Command' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/Command.php',
'League\\CLImate\\Decorator\\Component\\DecoratorInterface' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/DecoratorInterface.php',
'League\\CLImate\\Decorator\\Component\\Format' => __DIR__ . '/..' . '/league/climate/src/Decorator/Component/Format.php',
'League\\CLImate\\Decorator\\Parser\\Ansi' => __DIR__ . '/..' . '/league/climate/src/Decorator/Parser/Ansi.php',
'League\\CLImate\\Decorator\\Parser\\NonAnsi' => __DIR__ . '/..' . '/league/climate/src/Decorator/Parser/NonAnsi.php',
'League\\CLImate\\Decorator\\Parser\\Parser' => __DIR__ . '/..' . '/league/climate/src/Decorator/Parser/Parser.php',
'League\\CLImate\\Decorator\\Parser\\ParserFactory' => __DIR__ . '/..' . '/league/climate/src/Decorator/Parser/ParserFactory.php',
'League\\CLImate\\Decorator\\Parser\\ParserImporter' => __DIR__ . '/..' . '/league/climate/src/Decorator/Parser/ParserImporter.php',
'League\\CLImate\\Decorator\\Style' => __DIR__ . '/..' . '/league/climate/src/Decorator/Style.php',
'League\\CLImate\\Decorator\\Tags' => __DIR__ . '/..' . '/league/climate/src/Decorator/Tags.php',
'League\\CLImate\\Exceptions\\Exception' => __DIR__ . '/..' . '/league/climate/src/Exceptions/Exception.php',
'League\\CLImate\\Exceptions\\InvalidArgumentException' => __DIR__ . '/..' . '/league/climate/src/Exceptions/InvalidArgumentException.php',
'League\\CLImate\\Exceptions\\RuntimeException' => __DIR__ . '/..' . '/league/climate/src/Exceptions/RuntimeException.php',
'League\\CLImate\\Exceptions\\UnexpectedValueException' => __DIR__ . '/..' . '/league/climate/src/Exceptions/UnexpectedValueException.php',
'League\\CLImate\\Logger' => __DIR__ . '/..' . '/league/climate/src/Logger.php',
'League\\CLImate\\Settings\\Art' => __DIR__ . '/..' . '/league/climate/src/Settings/Art.php',
'League\\CLImate\\Settings\\Manager' => __DIR__ . '/..' . '/league/climate/src/Settings/Manager.php',
'League\\CLImate\\Settings\\SettingsImporter' => __DIR__ . '/..' . '/league/climate/src/Settings/SettingsImporter.php',
'League\\CLImate\\Settings\\SettingsInterface' => __DIR__ . '/..' . '/league/climate/src/Settings/SettingsInterface.php',
'League\\CLImate\\TerminalObject\\Basic\\BasicTerminalObject' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/BasicTerminalObject.php',
'League\\CLImate\\TerminalObject\\Basic\\BasicTerminalObjectInterface' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/BasicTerminalObjectInterface.php',
'League\\CLImate\\TerminalObject\\Basic\\Border' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Border.php',
'League\\CLImate\\TerminalObject\\Basic\\Br' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Br.php',
'League\\CLImate\\TerminalObject\\Basic\\Clear' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Clear.php',
'League\\CLImate\\TerminalObject\\Basic\\ClearLine' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/ClearLine.php',
'League\\CLImate\\TerminalObject\\Basic\\Columns' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Columns.php',
'League\\CLImate\\TerminalObject\\Basic\\Draw' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Draw.php',
'League\\CLImate\\TerminalObject\\Basic\\Dump' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Dump.php',
'League\\CLImate\\TerminalObject\\Basic\\Flank' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Flank.php',
'League\\CLImate\\TerminalObject\\Basic\\Inline' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Inline.php',
'League\\CLImate\\TerminalObject\\Basic\\Json' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Json.php',
'League\\CLImate\\TerminalObject\\Basic\\Out' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Out.php',
'League\\CLImate\\TerminalObject\\Basic\\Repeatable' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Repeatable.php',
'League\\CLImate\\TerminalObject\\Basic\\Tab' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Tab.php',
'League\\CLImate\\TerminalObject\\Basic\\Table' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Basic/Table.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Animation' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Animation.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Animation\\Keyframe' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Animation/Keyframe.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\Checkbox' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Checkbox/Checkbox.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\CheckboxGroup' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Checkbox/CheckboxGroup.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkbox\\RadioGroup' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Checkbox/RadioGroup.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Checkboxes' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Checkboxes.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Confirm' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Confirm.php',
'League\\CLImate\\TerminalObject\\Dynamic\\DynamicTerminalObject' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/DynamicTerminalObject.php',
'League\\CLImate\\TerminalObject\\Dynamic\\DynamicTerminalObjectInterface' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/DynamicTerminalObjectInterface.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Input' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Input.php',
'League\\CLImate\\TerminalObject\\Dynamic\\InputAbstract' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/InputAbstract.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Padding' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Padding.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Password' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Password.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Progress' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Progress.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Radio' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Radio.php',
'League\\CLImate\\TerminalObject\\Dynamic\\Spinner' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Dynamic/Spinner.php',
'League\\CLImate\\TerminalObject\\Helper\\Art' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Helper/Art.php',
'League\\CLImate\\TerminalObject\\Helper\\Sleeper' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Helper/Sleeper.php',
'League\\CLImate\\TerminalObject\\Helper\\SleeperInterface' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Helper/SleeperInterface.php',
'League\\CLImate\\TerminalObject\\Helper\\StringLength' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Helper/StringLength.php',
'League\\CLImate\\TerminalObject\\Router\\BaseRouter' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/BaseRouter.php',
'League\\CLImate\\TerminalObject\\Router\\BasicRouter' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/BasicRouter.php',
'League\\CLImate\\TerminalObject\\Router\\DynamicRouter' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/DynamicRouter.php',
'League\\CLImate\\TerminalObject\\Router\\ExtensionCollection' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/ExtensionCollection.php',
'League\\CLImate\\TerminalObject\\Router\\Router' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/Router.php',
'League\\CLImate\\TerminalObject\\Router\\RouterInterface' => __DIR__ . '/..' . '/league/climate/src/TerminalObject/Router/RouterInterface.php',
'League\\CLImate\\Util\\Cursor' => __DIR__ . '/..' . '/league/climate/src/Util/Cursor.php',
'League\\CLImate\\Util\\Helper' => __DIR__ . '/..' . '/league/climate/src/Util/Helper.php',
'League\\CLImate\\Util\\Output' => __DIR__ . '/..' . '/league/climate/src/Util/Output.php',
'League\\CLImate\\Util\\OutputImporter' => __DIR__ . '/..' . '/league/climate/src/Util/OutputImporter.php',
'League\\CLImate\\Util\\Reader\\ReaderInterface' => __DIR__ . '/..' . '/league/climate/src/Util/Reader/ReaderInterface.php',
'League\\CLImate\\Util\\Reader\\Stdin' => __DIR__ . '/..' . '/league/climate/src/Util/Reader/Stdin.php',
'League\\CLImate\\Util\\System\\Linux' => __DIR__ . '/..' . '/league/climate/src/Util/System/Linux.php',
'League\\CLImate\\Util\\System\\System' => __DIR__ . '/..' . '/league/climate/src/Util/System/System.php',
'League\\CLImate\\Util\\System\\SystemFactory' => __DIR__ . '/..' . '/league/climate/src/Util/System/SystemFactory.php',
'League\\CLImate\\Util\\System\\Windows' => __DIR__ . '/..' . '/league/climate/src/Util/System/Windows.php',
'League\\CLImate\\Util\\UtilFactory' => __DIR__ . '/..' . '/league/climate/src/Util/UtilFactory.php',
'League\\CLImate\\Util\\UtilImporter' => __DIR__ . '/..' . '/league/climate/src/Util/UtilImporter.php',
'League\\CLImate\\Util\\Writer\\Buffer' => __DIR__ . '/..' . '/league/climate/src/Util/Writer/Buffer.php',
'League\\CLImate\\Util\\Writer\\File' => __DIR__ . '/..' . '/league/climate/src/Util/Writer/File.php',
'League\\CLImate\\Util\\Writer\\StdErr' => __DIR__ . '/..' . '/league/climate/src/Util/Writer/StdErr.php',
'League\\CLImate\\Util\\Writer\\StdOut' => __DIR__ . '/..' . '/league/climate/src/Util/Writer/StdOut.php',
'League\\CLImate\\Util\\Writer\\WriterInterface' => __DIR__ . '/..' . '/league/climate/src/Util/Writer/WriterInterface.php',
'League\\ColorExtractor\\Color' => __DIR__ . '/..' . '/league/color-extractor/src/League/ColorExtractor/Color.php',
'League\\ColorExtractor\\ColorExtractor' => __DIR__ . '/..' . '/league/color-extractor/src/League/ColorExtractor/ColorExtractor.php',
'League\\ColorExtractor\\Palette' => __DIR__ . '/..' . '/league/color-extractor/src/League/ColorExtractor/Palette.php',
@@ -599,6 +735,7 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
'PHPMailer\\PHPMailer\\SMTP' => __DIR__ . '/..' . '/phpmailer/phpmailer/src/SMTP.php',
'Parsedown' => __DIR__ . '/../..' . '/kirby/dependencies/parsedown/Parsedown.php',
'ParsedownExtra' => __DIR__ . '/../..' . '/kirby/dependencies/parsedown-extra/ParsedownExtra.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php',
'Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php',
'Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php',
@@ -627,13 +764,42 @@ class ComposerStaticInit34ad0fcfd7efff0ce7004033b941cfcf
'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php',
'Seld\\CliPrompt\\CliPrompt' => __DIR__ . '/..' . '/seld/cli-prompt/src/CliPrompt.php',
'Spyc' => __DIR__ . '/../..' . '/kirby/dependencies/spyc/Spyc.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php',
'Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php',
'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php',
'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php',
'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php',
'Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php',
'Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php',
'Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php',
'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php',
'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php',
'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
'Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php',
'Symfony\\Polyfill\\Intl\\Idn\\Idn' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Idn.php',
'Symfony\\Polyfill\\Intl\\Idn\\Info' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Info.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php',
'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php',
'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php',
'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Whoops\\Exception\\ErrorException' => __DIR__ . '/..' . '/filp/whoops/src/Whoops/Exception/ErrorException.php',
'Whoops\\Exception\\Formatter' => __DIR__ . '/..' . '/filp/whoops/src/Whoops/Exception/Formatter.php',
'Whoops\\Exception\\Frame' => __DIR__ . '/..' . '/filp/whoops/src/Whoops/Exception/Frame.php',

View File

@@ -1,5 +1,90 @@
{
"packages": [
{
"name": "bnomei/kirby3-janitor",
"version": "2.16.0",
"version_normalized": "2.16.0.0",
"source": {
"type": "git",
"url": "https://github.com/bnomei/kirby3-janitor.git",
"reference": "12a9132cf221f3e248d9f22bddb7cbd7d303ae3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bnomei/kirby3-janitor/zipball/12a9132cf221f3e248d9f22bddb7cbd7d303ae3a",
"reference": "12a9132cf221f3e248d9f22bddb7cbd7d303ae3a",
"shasum": ""
},
"require": {
"getkirby/composer-installer": "^1.2",
"league/climate": "^3.7",
"php": ">=7.4.0",
"symfony/deprecation-contracts": "2.5",
"symfony/finder": "^5.4"
},
"require-dev": {
"getkirby/cms": "^3.5",
"php-coveralls/php-coveralls": "^2.4",
"phpunit/phpunit": "^9.5"
},
"time": "2022-04-14T18:24:35+00:00",
"type": "kirby-plugin",
"extra": {
"kirby-cms-path": "tests/kirby"
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Bnomei\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bruno Meilick",
"email": "b@bnomei.com"
}
],
"description": "Kirby 3 Plugin for running jobs like cleaning the cache from within the Panel, PHP code or a cronjob",
"keywords": [
"ajax",
"button",
"cache",
"clean",
"cronjob",
"janitor",
"job-runner",
"kirby3",
"kirby3-cms",
"kirby3-plugin"
],
"support": {
"issues": "https://github.com/bnomei/kirby3-janitor/issues",
"source": "https://github.com/bnomei/kirby3-janitor/tree/v2.16.0"
},
"funding": [
{
"url": "https://buymeacoff.ee/bnomei",
"type": "custom"
},
{
"url": "https://paypal.me/bnomei",
"type": "custom"
},
{
"url": "https://github.com/bnomei",
"type": "github"
},
{
"url": "https://www.patreon.com/bnomei",
"type": "patreon"
}
],
"install-path": "../../site/plugins/kirby3-janitor"
},
{
"name": "claviska/simpleimage",
"version": "3.7.0",
@@ -671,6 +756,74 @@
],
"install-path": "../laminas/laminas-escaper"
},
{
"name": "league/climate",
"version": "3.8.2",
"version_normalized": "3.8.2.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/climate.git",
"reference": "a785a3ac8f584eed4abd45e4e16fe64c46659a28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/climate/zipball/a785a3ac8f584eed4abd45e4e16fe64c46659a28",
"reference": "a785a3ac8f584eed4abd45e4e16fe64c46659a28",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"seld/cli-prompt": "^1.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.6.10",
"mockery/mockery": "^1.4.2",
"phpunit/phpunit": "^9.5.10"
},
"suggest": {
"ext-mbstring": "If ext-mbstring is not available you MUST install symfony/polyfill-mbstring"
},
"time": "2022-06-18T14:42:08+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"League\\CLImate\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joe Tannenbaum",
"email": "hey@joe.codes",
"homepage": "http://joe.codes/",
"role": "Developer"
},
{
"name": "Craig Duncan",
"email": "git@duncanc.co.uk",
"homepage": "https://github.com/duncan3dc",
"role": "Developer"
}
],
"description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.",
"keywords": [
"cli",
"colors",
"command",
"php",
"terminal"
],
"support": {
"issues": "https://github.com/thephpleague/climate/issues",
"source": "https://github.com/thephpleague/climate/tree/3.8.2"
},
"install-path": "../league/climate"
},
{
"name": "league/color-extractor",
"version": "0.3.2",
@@ -1305,6 +1458,64 @@
},
"install-path": "../ralouphie/getallheaders"
},
{
"name": "seld/cli-prompt",
"version": "1.0.4",
"version_normalized": "1.0.4.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/cli-prompt.git",
"reference": "b8dfcf02094b8c03b40322c229493bb2884423c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/b8dfcf02094b8c03b40322c229493bb2884423c5",
"reference": "b8dfcf02094b8c03b40322c229493bb2884423c5",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpstan/phpstan": "^0.12.63"
},
"time": "2020-12-15T21:32:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Seld\\CliPrompt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
"keywords": [
"cli",
"console",
"hidden",
"input",
"prompt"
],
"support": {
"issues": "https://github.com/Seldaek/cli-prompt/issues",
"source": "https://github.com/Seldaek/cli-prompt/tree/1.0.4"
},
"install-path": "../seld/cli-prompt"
},
{
"name": "sylvainjule/color-palette",
"version": "1.0.4",
@@ -1389,6 +1600,142 @@
},
"install-path": "../../site/plugins/embed"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.0",
"version_normalized": "2.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-07-12T14:48:14+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/deprecation-contracts"
},
{
"name": "symfony/finder",
"version": "v5.4.43",
"version_normalized": "5.4.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ae25a9145a900764158d439653d5630191155ca0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ae25a9145a900764158d439653d5630191155ca0",
"reference": "ae25a9145a900764158d439653d5630191155ca0",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-php80": "^1.16"
},
"time": "2024-08-13T14:03:51+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v5.4.43"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/finder"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.26.0",
@@ -1648,6 +1995,89 @@
}
],
"install-path": "../symfony/polyfill-mbstring"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"time": "2024-09-09T11:45:10+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/polyfill-php80"
}
],
"dev": true,

View File

@@ -3,13 +3,22 @@
'name' => 'getkirby/plainkit',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => 'a4b2aece7b44b516ca8349830f01c2eccae22ff0',
'reference' => 'b0db09492d378d45eb0ecd0234e85a57db00d2f8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'bnomei/kirby3-janitor' => array(
'pretty_version' => '2.16.0',
'version' => '2.16.0.0',
'reference' => '12a9132cf221f3e248d9f22bddb7cbd7d303ae3a',
'type' => 'kirby-plugin',
'install_path' => __DIR__ . '/../../site/plugins/kirby3-janitor',
'aliases' => array(),
'dev_requirement' => false,
),
'claviska/simpleimage' => array(
'pretty_version' => '3.7.0',
'version' => '3.7.0.0',
@@ -67,7 +76,7 @@
'getkirby/plainkit' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => 'a4b2aece7b44b516ca8349830f01c2eccae22ff0',
'reference' => 'b0db09492d378d45eb0ecd0234e85a57db00d2f8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -100,6 +109,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'league/climate' => array(
'pretty_version' => '3.8.2',
'version' => '3.8.2.0',
'reference' => 'a785a3ac8f584eed4abd45e4e16fe64c46659a28',
'type' => 'library',
'install_path' => __DIR__ . '/../league/climate',
'aliases' => array(),
'dev_requirement' => false,
),
'league/color-extractor' => array(
'pretty_version' => '0.3.2',
'version' => '0.3.2.0',
@@ -217,6 +235,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'seld/cli-prompt' => array(
'pretty_version' => '1.0.4',
'version' => '1.0.4.0',
'reference' => 'b8dfcf02094b8c03b40322c229493bb2884423c5',
'type' => 'library',
'install_path' => __DIR__ . '/../seld/cli-prompt',
'aliases' => array(),
'dev_requirement' => false,
),
'sylvainjule/color-palette' => array(
'pretty_version' => '1.0.4',
'version' => '1.0.4.0',
@@ -235,6 +262,24 @@
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'reference' => '6f981ee24cf69ee7ce9736146d1c57c2780598a8',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/finder' => array(
'pretty_version' => 'v5.4.43',
'version' => '5.4.43.0',
'reference' => 'ae25a9145a900764158d439653d5630191155ca0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/finder',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-idn' => array(
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
@@ -268,5 +313,14 @@
0 => '*',
),
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

246
vendor/league/climate/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,246 @@
Changelog
=========
--------
## 3.8.2 - 2022-01-23
### Fixed
* Avoid passing null to strlen(). [#186](https://github.com/thephpleague/climate/issues/186)
* [Support] Added compatibility for psr/log 2 & 3. [#191](https://github.com/thephpleague/climate/issues/191)
--------
## 3.8.1 - 2022-01-23
### Fixed
* [Linux] Avoid type issue when checking if \STDOUT is defined. [#185](https://github.com/thephpleague/climate/issues/185)
--------
## 3.8.0 - 2022-01-22
### Changed
* [Support] Added support for PHP 8.1.
### Fixed
* [Linux] Added a workaround for executed some parts of the code in a non-cli context. [#175](https://github.com/thephpleague/climate/pull/175)
--------
## 3.7.0 - 2021-01-10
### Changed
* [Support] Added support for PHP 8.0.
* [Support] Dropped support for PHP 7.2.
--------
## 3.6.0 - 2020-10-04
### Added
* [Arguments] Add a method to access trailing args as array. [#158](https://github.com/thephpleague/climate/pull/158)
### Fixed
* [Table] Add support for newlines in table data. [#160](https://github.com/thephpleague/climate/pull/160)
* [Checkbox] Don't try to add padding if the there's no spare space. [#161](https://github.com/thephpleague/climate/issues/161)
### Changed
* [Support] Dropped support for PHP 7.1.
--------
## 3.5.2 - 2019-12-01
### Fixed
* [Checkbox] Ensure we can output when the terminal width is unknown. [#156](https://github.com/thephpleague/climate/pull/156)
--------
## 3.5.1 - 2019-11-24
### Fixed
* [Art] Be stricter about matching filenames when looking for art. [#155](https://github.com/thephpleague/climate/issues/155)
* [Support] Provide better support for Windows using GitHub actions.
--------
## 3.5.0 - 2019-02-10
### Added
* [Arguments] Multiple arguments (eg `cli -d foo=bar -d baz=qux`) available via `$climate->arguments->getArray("d")`. [#111](https://github.com/thephpleague/climate/pull/111)
* [Arguments] A new method (`Argument::values()`) replaces the deprecated `valueArray()` method.
* [Spinner] Add an indeterminate progress spinner.
* [Exceptions] All exception now implement `League\CLImate\Exceptions\Exception`.
* [Basic] Allow single lines to be cleared using `$climate->clearLine()`. [#145](https://github.com/thephpleague/climate/issues/145).
### Fixed
* [Arguments] Mixing arguments with/without option values. [#122](https://github.com/thephpleague/climate/issues/122).
* [Output] Prevent `tput` output from being sent to the terminal.
* [Confirm] Accept more reasonable options for yes/no. [#126](https://github.com/thephpleague/climate/issues/126).
* [Radio] Allow ENTER to be used to choose an option. [#140](https://github.com/thephpleague/climate/issues/140).
* [Output] Improve the checks for ANSI color checks. [#128](https://github.com/thephpleague/climate/issues/128) / [#129](https://github.com/thephpleague/climate/issues/129).
* [Art] Only match filenames when looking for art. [#130](https://github.com/thephpleague/climate/issues/130)
### Changed
* [Support] Dropped support for PHP 5.6 and PHP 7.0
--------
## 3.4.1 - 2018-04-29
### Fixed
* [Json] Don't escape slashes when outputting JSON. [#121](https://github.com/thephpleague/climate/pull/121)
--------
## 3.4.0 - 2018-04-28
### Added
* [Logger] Added a Logger class to use CLImate as a PSR-3 logger.
--------
## 3.3.0 - 2018-04-20
### Fixed
* Ensure multibyte strings are supported everywhere.
* Improved support for IDE assistance when using method chaining. [#102](https://github.com/thephpleague/climate/pull/102)
* [Art] Improve handling of missing files. [#114](https://github.com/thephpleague/climate/issues/114)
* [Input] Correct the usage of `defaultTo()` with `accept()`. [#104](https://github.com/thephpleague/climate/pull/104)
* [Windows] Fixed the terminal width detection. [#64](https://github.com/thephpleague/climate/pull/64)
### Added
* [Table] Add support for a prefix argument for each row. [#51](https://github.com/thephpleague/climate/issues/51)
* [Progress] Added an `each()` method. [#112](https://github.com/thephpleague/climate/pull/112)
### Changed
* [Support] Add support for PHP 7.2
* [Support] Drop support for PHP 5.4
* [Support] Drop support for PHP 5.5
* [Support] Drop support for HHVM.
* Suggest the symfony polyfill library is `ext-mbstring` is not available. [#110](https://github.com/thephpleague/climate/pull/110)
--------
## 3.2.4 - 2016-10-30
### Fixed
* [Progres] Allow labels to be shown/hidden on each iteration. [#98](https://github.com/thephpleague/climate/pull/98)
--------
## 3.2.3 - 2016-10-17
### Added
* [Support] Added support for PHP 7.1
--------
## 3.2.2 - 2016-07-18
### Fixed
* [Art] Allow code to be used in a phar. [#86](https://github.com/thephpleague/climate/pull/86)
--------
## 3.2.1 - 2016-04-05
### Added
* [Arguments] Add a `trailing()` method to get any trailing arguments.
* [Progress] Added a `forceRedraw()` method. [#72](https://github.com/thephpleague/climate/issues/72)
### Fixed
* [Checkbox] Don't cancel out the formatting for the first checkbox. [#77](https://github.com/thephpleague/climate/issues/77)
* [Padding] Ensure formatting is handled. [#78](https://github.com/thephpleague/climate/issues/78)
* [Columns] Prevent error when less items than columns are passed. [#75](https://github.com/thephpleague/climate/pull/75)
--------
## 3.2.0 - 2015-08-13
### Added
- Multi-line support for `input` method [https://github.com/thephpleague/climate/pull/67](https://github.com/thephpleague/climate/pull/67)
- `extend` method for _much_ easier extending of CLImate
### Fixed
- Unnecessary progress bar re-drawing when the output hadn't changed [https://github.com/thephpleague/climate/pull/69](https://github.com/thephpleague/climate/pull/69)
- Progress label no longer removed once progress reaches 100%
- Non-prefixed paramaters for `arguments` method now show in usage description [https://github.com/thephpleague/climate/issues/65](https://github.com/thephpleague/climate/issues/65)
## 3.1.1 - 2015-05-01
### Fixed
- Windows support added for `password` thanks to @Seldaek and [seld/cli-prompt](https://packagist.org/packages/seld/cli-prompt)
## 3.1.0 - 2015-04-30
### Added
- `password` prompt
- `checkboxes` prompt
- `radio` prompt
- 'file' as output option
## 3.0.0 - 2015-03-01
### Changed
- Custom output writers are added simply via the `output` property on CLImate now, as opposed to the immense amount of scaffolding required before
### Added
- Argument parsing
- StdErr output
- Buffer output
- `animate` method for running ASCII animations in the terminal. Because it's fun.
- Input now bolds the default response if it exists
## 2.6.1 - 2015-01-18
### Fixed
- Added `forceAnsiOn` and `forceAnsiOff` methods to address systems that were not identified correctly
## 2.6.0 - 2015-01-07
### Added
- Allow for passing an array of arrays into `columns` method
- `tab` method, for indenting text
- `padding` method, for padding strings to an equal width with a character
- `League\CLImate\TerminalObject\Repeatable` for repeatable objects such as `tab` and `br`
- `League\CLImate\Decorator\Parser\Ansi` and `League\CLImate\Decorator\Parser\NonAnsi`
- Factories:
+ `League\CLImate\Decorator\Parser\ParserFactory`
+ `League\CLImate\Util\System\SystemFactory`
- Terminal Objects now are appropriately namespaced as `Basic` or `Dynamic`
- Readers and Writers are appropriately namespaced as such under `League\CLImate\Util`
### Fixed
- Labels for `advance` method
- Non-ansi terminals will now have plaintext output instead of jumbled characters
- `border` method now default to full terminal width

View File

@@ -0,0 +1,22 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)

32
vendor/league/climate/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,32 @@
# Contributing
Contributions are **welcome** and will be fully **credited**.
We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/climate).
## Pull Requests
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
- **Create feature branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
## Running Tests
``` bash
$ composer test
```
**Happy coding**!

13
vendor/league/climate/Dockerfile vendored Normal file
View File

@@ -0,0 +1,13 @@
ARG PHP_VERSION=7.3
FROM php:${PHP_VERSION}-cli
ARG COVERAGE
RUN if [ "$COVERAGE" = "pcov" ]; then pecl install pcov && docker-php-ext-enable pcov; fi
# Install composer to manage PHP dependencies
RUN apt-get update && apt-get install -y git zip
RUN curl https://getcomposer.org/download/1.9.0/composer.phar -o /usr/local/sbin/composer
RUN chmod +x /usr/local/sbin/composer
RUN composer self-update
WORKDIR /app

21
vendor/league/climate/LICENSE.md vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Joe Tannenbaum
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

44
vendor/league/climate/README.md vendored Normal file
View File

@@ -0,0 +1,44 @@
<p align="center"><img src="http://climate.thephpleague.com/img/CLImate_Blink.gif" width="300" alt="CLImate" /></p>
[![Latest Version](https://img.shields.io/github/tag/thephpleague/climate.svg?style=flat&label=release)](https://github.com/thephpleague/climate/tags)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md)
[![Build Status](https://github.com/thephpleague/climate/workflows/.github/workflows/buildcheck.yml/badge.svg?branch=master)](https://github.com/thephpleague/climate/actions?query=branch%3Amaster+workflow%3Abuildcheck)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/climate.svg?style=flat)](https://scrutinizer-ci.com/g/thephpleague/climate/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/climate.svg?style=flat)](https://scrutinizer-ci.com/g/thephpleague/climate)
[![Total Downloads](https://img.shields.io/packagist/dt/league/climate.svg?style=flat)](https://packagist.org/packages/league/climate)
Running PHP from the command line? CLImate is your new best bud.
CLImate allows you to easily output colored text, special formats, and more.
## Installation
The recommended method of installing this library is via [Composer](https://getcomposer.org/).
Run the following command from your project root:
```bash
$ composer require league/climate
```
## Usage
```php
require_once __DIR__ . "/vendor/autoload.php";
$climate = new \League\CLImate\CLImate;
$climate->red('Whoa now this text is red.');
$climate->blue('Blue? Wow!');
```
_Read more at https://climate.thephpleague.com/_
## Credits
This library was created by [Joe Tannenbaum](https://joe.codes/).
It is currently maintained and developed by [Craig Duncan](https://twitter.com/duncan3dc).
Much love to [Damian Makki](https://dribbble.com/damianmakki) for the logo.

48
vendor/league/climate/composer.json vendored Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "league/climate",
"description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.",
"keywords": ["cli","php", "terminal", "command", "colors"],
"license": "MIT",
"authors": [
{
"name": "Joe Tannenbaum",
"email": "hey@joe.codes",
"homepage": "http://joe.codes/",
"role": "Developer"
}, {
"name": "Craig Duncan",
"email": "git@duncanc.co.uk",
"homepage": "https://github.com/duncan3dc",
"role": "Developer"
}
],
"require": {
"psr/log": "^1.0 || ^2.0 || ^3.0",
"php": "^7.3 || ^8.0",
"seld/cli-prompt": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10",
"mockery/mockery": "^1.4.2",
"mikey179/vfsstream": "^1.6.10"
},
"suggest": {
"ext-mbstring": "If ext-mbstring is not available you MUST install symfony/polyfill-mbstring"
},
"autoload": {
"psr-4": {
"League\\CLImate\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"League\\CLImate\\Tests\\": "tests/"
}
},
"scripts": {
"test": [
"vendor/bin/phpunit",
"@composer validate --strict"
]
}
}

View File

@@ -0,0 +1,6 @@
_ _ ___ _ _
| || | / _ \| || |
| || |_| | | | || |_
|__ _| | | |__ _|
| | | |_| | | |
|_| \___/ |_|

View File

@@ -0,0 +1,17 @@
( )
H
H
_H_
.-'-.-'-.
/ \
| |
| .-------'._
| / / '.' '. \
| \ \ @ @ / /
| '---------'
| _______|
| .'-+-+-+|
| '.-+-+-+|
| """""" |
'-.__ __.-'
"""

View File

@@ -0,0 +1,6 @@
______ _____ _ ______ _____
| ____/\ |_ _| | | ____| __ \
| |__ / \ | | | | | |__ | | | |
| __/ /\ \ | | | | | __| | | | |
| | / ____ \ _| |_| |____| |____| |__| |
|_|/_/ \_\_____|______|______|_____/

View File

@@ -0,0 +1,17 @@
<blue> ( )</blue>
<blue> H</blue>
<blue> H</blue>
<blue> _H_</blue>
<blue> .-'-.-'-.</blue>
<blue> / \</blue>
<blue>| |</blue>
<blue>| .-------'._</blue>
<blue>| /<white>/ '.' '.</white> \</blue>
<blue>| \<white>\ <black><blink>@ @</blink></black> /</white> /</blue>
<blue>| '---------'</blue>
<blue>| _______|</blue>
<blue>| .'<black>-+-+-+</black>|</blue>
<blue>| '.<black>-+-+-+</black>|</blue>
<blue>| """""" |</blue>
<blue>'-.__ __.-'</blue>
<blue> """</blue>

View File

@@ -0,0 +1,6 @@
_____ _____ _____ ______ _____
| __ \ /\ / ____/ ____| ____| __ \
| |__) / \ | (___| (___ | |__ | | | |
| ___/ /\ \ \___ \\___ \| __| | | | |
| | / ____ \ ____) |___) | |____| |__| |
|_| /_/ \_\_____/_____/|______|_____/

6
vendor/league/climate/src/ASCII/php vendored Normal file
View File

@@ -0,0 +1,6 @@
__
____ / /_ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / /_/ /
/ .___/_/ /_/ .___/
/_/ /_/

View File

@@ -0,0 +1,102 @@
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyssoo+/:--...`````````````..--:/++ossyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso/:-.``` ```.-:/osyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso/-.`` ``.-/+syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhso/-`` ``-:osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs+:.` `.:+syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo:.` `.:oyhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+-` ```.` `:::` `....` `-+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+-` `+++///. .o+-/o- -o+://++` .:` `-+shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo:` :: `oo.``` .o+` /s- `+o` ``. +s` ./. `:oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy/. /s. :s+/++. -s/:::/s/ .s/ `/+/` -s: +s` -/-`` ./shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys:` ``-//` `o+` .s/````` -s/----o+ .s/` .+o``o+` -s: :s/:++/- `-oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo- `:++:-` -s: ``. oo//++/`.+. `/: -++++++- -s/` `o+` -so.```-. .oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo. `-` :s:`.:+` /s//++/`.-.``` ```` :+++/+s. -s/:/+/` .oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho. .oo- :oo+:. ` `-.`` ``..` .so-` `` `/+++-` .oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs- `:` `/s:` -s/`./++. ```..........``` .-/++/ -o+.`-+o/ .shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy: ` .oo-`-/o/+o. -o+/-` ``.-/+ossyyyhhyyyyyyhhyyysso+/:.`` `. `+s- `os` -yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh+` .o+` `:oo+-` `:s: ` `.:+syhhyyso+/::--........--::/+osyyhhys+/.` -y: .oo- -+- `/hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy- .os/` .+o- ` .:+shhys+/-.` `.-:+syhhso:. `/o+:-/s/` :oo:oo- -shhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhho` `+o--oo-` :o- `-+shhs+:.` ``.` ...` `... `` `.:+shhs+-` -//:.`:ooo- .o/ `+hhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhh: ` -oo-` `:oyhyo:. ``` `.--` `--.` .--.` .--.` .--. ` `:oyhho:` -o+-`-oo` -hhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhy- -o+` -oyhy+-` `.` `.--` `.--` `--.` `--.` .--.` .--. .-.` `-/yhyo-` `. ` .shhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhs` ` `:yhyo-` `.` `.--` `.--` `.--` `--.` `--.` .--.` .--.` .--. `.+yhy/. `ohhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhh+` .+yhs/` `..``.--. `.--` `.--` `.--` `---` `--.` .--.` .--.` .--. ` `:shh+. `+hhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhho .+hho- ``` .--.``.--. `.--` `.--` `.--` `.--` `--.` `--.` .--.` .--.` `.` -ohh+. +hhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhh+` `/yho- ` `--.``.--.``.--.``.--` `.--` `.--` `.--` `--.` `--.` .--.` .--.``..` -ohh/` /hhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhho -yhs: .-.` `--.` .--.``.--.``.--` `... `..````..` `.-.` `--.` .--.` .--.``..` -shy: +hhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhho` `ohy/` `.` `--.` `--.` .--.``.-.` ``...-:://++++++++++//:-..`` `--.` `--.` .--.``.-` `/yho` `ohhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhy` -shs. ` `--.` `--.` `--.``.-. `.-:/++ooooooooooooooooooooooooo+:-```--.` `-.` `.` ..` .shy: `yhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhy- /hh+` `--` `.-.` `--.` `--. `-/+oooooooooooooooooooooooooooooooooso+-``.``````.....--` `.. `/hh/` -yhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhh/ +hy: `` `.--` `.-.` `--.` ``-osoooooooooooooooooooooooooooooooooo+/:--..--::/:::---... ..```` :yho` :hhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhs `+hy- .--. `.--` `.-.` `-- `+soooooooooooooooooooooooooooooooooo/--:--:/+/-..` .` `...` `--.` .yho` shhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhh- ohy- ..``.--` `..` ``...` ``+soooooooooooooooooooooooooooooooo+:-::-:+o:.`.:+o/``.-` `--.` `--.` .yho` -yhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhh+ -/ /hh- .--. ```-/++++++/:-. /soooooooooooooooooooooooooooooooo--/:-/oo-``-+oooooo:``--` `--.` `--.` .yh+` -/ +hhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhh. -ss: :hh: ..``.` -osooooooooos+ -sooooooooooooooooooooooooooooooo/./+.:os:``-osooooooos+-`.--` `.--` `--. :hh/ -ss/` `hhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhho ..---/ooos/.```` `hh+ .--. -sooooooooooo+`.oooooooooooooooooooooooooooooooo--o:.+so- .+sooooooooooos:``.--` `.--` `-. /hh. ..---/ooos/.```` ohhhhhhhhhhhhhhh
hhhhhhhhhhhhhhh: -osssoooooosooo:` `ohy` `.` .` `ooooooooooooo` osoooooooooooooooooooooooooooos+.:s--oso` :ooooooooooooooos+` `.--` `.--` `` sho` -osssoooooosooo:` -hhhhhhhhhhhhhhh
hhhhhhhhhhhhhhy` -oooooooooo:. -hh: `--.` .sooooooooooo- +sooooooooooooooooooooooooooos/`+s-.ss+` :soooooooooooooooos+` `.--` `.--` -hh: -oooooooooo:. `shhhhhhhhhhhhhh
hhhhhhhhhhhhhh+ /sooooooo. shs` `` `-- .sooooooooos- :`.oooooooooooooooooooooooooooo:`:s-.oso` :soooooooooooooooooos+ `. `.--` `.--` `ohs /sooooooo. /hhhhhhhhhhhhhh
hhhhhhhhhhhhhd- .sooo/+oos- .hd: .--` ` `+oooooooos: -+/``+soooooooooooooooooooooooo.`:..`:/+- -soooooooooooooooooooos- --` `.--` `.-` -dh- `sooo/+oos- -dhhhhhhhhhhhhh
hhhhhhhhhhhhhh. -/-` .-+/ /dh` `---` .soooooos/ -////-`-ooooooooooooooooooooooo.`.::::---``oooooooooooooooooooooos/ `.--` `.--` `` yh+ -/-` .-+/ `hhhhhhhhhhhhhh
hhhhhhhhhhhhhy `ohs .-` `.-- ` .oooooos- ///////.`:ooooooooooooooooooso`-+:``..---`/sooooooooooooooooooooos: ` `.--. `.--` ohs` yhhhhhhhhhhhhh
hhhhhhhhhhhhhs .yh+ `.--` `-. `+sooos/ -///////:.`-+sooooooooooooos+`-//:`+so+` .soooooooooooooooooooooos` --. .--. `.-- /hy. ohhhhhhhhhhhhh
hhhhhhhhhhhhho .hh: . `.--` `. -osoos- ://///////-``/osooooooooos+`://:`+sos: `+oooooooooooooooooooooos/ .--. .--. `.` -hh- ohhhhhhhhhhhhh
hhhhhhhhhhhhho .hh- `--` `.--` -osos: -///////////-``:+ssoooos/`:///`/soso :sooooooooooooooooooooooo``-.` .--. .--. -hh- +hhhhhhhhhhhhh
hhhhhhhhhhhhho .hh- .--. `.--` .+ss+.`:////////////-``-/oss/`:///`/soos- osooooooooooooooooooooos- `--.` `--.` .--` -hh- +hhhhhhhhhhhhh
hhhhhhhhhhhhho .hh: . .--. `.--` `/os/``----://///////:-.`.`////`:soos/` :sooooooooooooooooooooos+ .-` `--.` `--.` .` -hh- ohhhhhhhhhhhhh
hhhhhhhhhhhhhs .yh+ --. .--. `.--` ` ..-:::..:`.//////////..////`:sooos```ooooooooooooooosssooooso. `.--` `--.` `--.` /hh. ohhhhhhhhhhhhh
hhhhhhhhhhhhhy `sho .--.` .--. .--` `-/+oooooos:`-`+..//////:`-////`-sooos:``.++oosssssoo+/:-..``....` `` ``.` `--.` `-- ohs` shhhhhhhhhhhhh
hhhhhhhhhhhhhh` /dh` `` .--.` .--. `.:+oooooooss/.-.`.+s/.-::/-`:////.-oooooo`-`--..``......---:::--.....`` `--.` ` yh+ `hhhhhhhhhhhhhh
hhhhhhhhhhhhhd- .hd- `-.` `--.` ```:+oooooooso+:.-..://.-oo. ` ./////..ooooos--.`..```..........-::/+++oooooo++/:.` `--. -hd- .hhhhhhhhhhhhhh
hhhhhhhhhhhhhh+ sho` `--.` `-- -ooooosso+/:-.-.-://///-.+s: -/////-.ooooos+`: ``....-:::/++oooooooooooooooooooooo+/.``` `. ohy /hhhhhhhhhhhhhh
hhhhhhhhhhhhhhy` -hh- `--.` -.:+///::--.-..-://///////:`/s/`:///..ooooooo.:.:ooooooooooooooooooooooooooooooooooooos- --` -hh: `shhhhhhhhhhhhhh
hhhhhhhhhhhhhhh- `` `ohs `` `--.``....```-`.-:///////////////`:s/`//.-oooooos-./`osooooooooooooooooooooooooooooooooooos/` `.` shs` ` -hhhhhhhhhhhhhhh
hhhhhhhhhhhhhhho `.-:/+++o` .hh/ .-` `-.`.`::::`+/`/////////////////:`/s-..:sooooos+`+`.++oossooooooooooooooooooooooooooooos+- .-. /hh. `++` -::- +hhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhh. `++:-o/``o: /hh: .-.` ``..-///-.o-./////////////////:`o+.+oooooooo.// `.....-:/++ooosoooooooooooooooooooo/.`` `.. -yh/ :o` -s:-o/ `hhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhh+ -s. -o` .+` `+hy. `.--` -`:///..s:./////////////////`:soooooooos.-o`` `.--` `.....-::/++oooooooooo++:.`` .--. .yho` -o//o- .s: /hhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhy- +/ ` `:/` `ohy. `.--``-`:///.-s:.:///////////////`:sooooooos:.s- --` `.--` `.--` `..````........` `--.``.. .shs` `-``.-. `+/ .yhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhs ``.```++-` `ohy. `.-.`:`////.-s+../////////////:`+ooooooos:`o/ `.--` `.--` `.--` `.-.` `.-.` `--.` .--. .yho` `/+` -` `` ohhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhh: `+///+s:``. `ohy: ````...:.:///.-+s+--://///////-.+soooooos/.++`.-.``.--```.--` `.--` `.-.` `--.` `--.` .` -yho` /s. :o` -o` :hhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhy- .s/:/++. `/hh/` .. ``.:.-///-./oo+:---::::--:ooooooooo:.o+```.--.``.--```.--` `.--` `.--` `--.` `--` :hh+` -/++o/..o: .yhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhy` `/o/` ` //` :yho. `.. `--.:///-./oso++////+oooooooos+--o/`.-.``.--.``.--` `.--` `.--` `.--` `--.` ` `ohy: -/` `..:/+: `shhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhho` .. `:s+` .shy/ `.. .----:/:-.:+oooooooooooooo+:-+o-```.--.``.--.``.--. `.--` `.--` `.--` `.` :yhs. `/+- .++:. ` `+hhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhh+ .-/+/-/o` `:yho- `.. `-:::---.:+oooooooooo+:-:++:``--.` .--.``.--.``.--. `.--` `.--` `.-. -ohy/` /s. ..`+s` +hhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhh/ `++/.` -:- .+hho. `.. `.:/++ooooo++///::-://:.`..` `--.` .--.``.--.``.--. `.--` `.--` ` .+hh+. `/++-.`.o/ /hhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhh+ ` ./+/+/` .+hho- `.` `....``````..----..`..` `--.` `--.` `--.` .--.``.--. `.--. `.` .+hho- `---.``.:+++- /hhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhh+` `:+o+. /s. -+hho:` `` `.--. .-.` .--` `--.` `--.` `--.` `--.` .--.``.--.``..` `-ohho- .s/::/++:` /hhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhho` :/.`++.-+o` ./yhy+. .--. `.--. `.--` `.--` `--.` `--.` `--.` `--.` .-. ./shy+. +o .o//o- +hhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhs. .o+::. ``.-. `:shhs/. ..-. `.--. `.--` `.--` `--.` `--.` `--.` `-. .:shhs:` /:` `++/o- ` .ohhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhy- :: .+++/:o/ `/shhs+-` ` .--. `.--` `.--` `---` `--.` `.` `-+shhs/` `/o- ./o+` .yhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhh+ -+oo:` .s: .:oyhhs/-` `` `...` `.-.` `..` `-/oyhyo:. :o- .so:-` `` /hhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs. .- `/o:o+` .//:` `.:oyhhyo/:.` `.:/oyhhyo/.` `-/- .+o++.`-/+. .shhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh/` -o+- `+o-.:o/. `.-/osyhhyso+/:--..````````..--:/+osyhhyso/:.` `/o:.` .+o-` `/hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy- .. -o/` .s: .` `.-/+ossyyhhyyyyyyyyyyhyyysso+/-.` .s: ` ./. -shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho. +o. `/o:``+++/-` ``..............`` -/+/-` .o+. `++ .ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+` `:++/++. .o+``.+o` `` `` o+`./o/``:o/++:` `+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+. `... -o++:.-o/``/o//:. .-///++` oo .:+oo` `..` `+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+. `o- `+o:- /s.`.:s- .:-.` `. :s:` `o/`.oo/-.`/: .+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo-` o/ :s- -s- `+o:.`+/` .` ``` `..... /- :s. +o.-/o: `o+ .oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs:` `` -s/.` -s- .s: .oo+ .s. `+++o. `o+:::o/ :o/.`o/ `+s:.` `` `:syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+-` `.://++: `++` /o`+/`:o .o/` :s- o+ `/o` `:+oo` `o/ `-+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs+.` ` -/o/` s/ `o/o/ :s:---s+ /s//+s- +o `` `./shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys/-` ``.` `+. `+o. /s----s/ :s. `/+` .: `-/syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs+-. `. .- :- `:` .` .-+shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys+-.` `-/oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys+:.` `.-+oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhso+:.`` ``.:/oshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso+:-.``` ```.-:/osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyso++::-..``````````````````..-::/+osyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyssyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

View File

@@ -0,0 +1,153 @@
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyssooo+++////////////+++ooossyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyso+//:-..```` ````..-://+osyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyo+/:-.`` ``.-:/+osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso/:.`` ``.-/+syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo+:.` `.:/oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhyo+-.` `.-+oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhyo:.` `.:oshhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo:. .:oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhys/.` .:oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+-` `-+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+- ``.. -++++- .---..`` ./yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy/. -//oosssss. `+yo:/sy: .ossoossss+- .. ./yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh+. /ys:...`` `oyo` -sy+` oy+` ``.:o: `sy/ ./yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho- `+s/ -sy- `oyo` `oy+ -sy- +yo` +s: -ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy:` :ys. oso/+osys` `sy:`.....:yo` :ys` `o+//- -yy- :ys. .:. :ydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds- `. oyo :ys/:--.` `ssssssssssso` +y+ `-:oy/ `oy+ `sy/ -ysys+:. .ohhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh/` .:oyy: .sy: .sy- `oy/`` -ys` `oyo` -sy- :ys. +yo` .sy/`-/osss- `/hdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy: .-+syo/-` /ys. +y+-:/+ooy: `oy/ -ss` `+ysso+++ss+ `sy/ -sy: -sy/ `-:` :ydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy: /ys/` ` `oy+ `.-:+s- :yoo+/:--.` `---:/+:` /ys/-.` `oy+ .ssoss/-. -sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy- .:` :ss: `-+sy: -ysosso+/:. -/oossssss. .sy/`.:+sy: -sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy: `oys- -ssoss+:` :/-.` `.--.` .sy+` ` `:++o+- -sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh:` :sy+` .ss+` `.+: ./osso:.` -syo//oso/. :ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh/` .+: .oss- .sy+`./oss+:` ``......----......``` ``-/osso` `+ys:` `-+ss/ `/hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdo. -sy+. ./os+os+` .ossso/-` `..://+ossyyyhhhhhhhhhhhhhhhhyyysso++/:-.` `-- :sy+. /ys. `+dhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy- `/:` `+ys:-oss/.``+ys:` `/:`` `.-/+osyhhhhhhhhhyyyysssoooooooosssyyyyhhhhhhhhhyso+/-.` /ys: :sy+` `` -sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh+` `/ss/` -osso-` -ss- `.:+syhhhhhhhyso+/:-..`````` ``````.-::++oyyhhhhhhyso:.` /ys. .oys- `:os/` `/hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy. `/sy+` `/ss/` `` .:+syhhhhhys+/-.`` ``.-/+oyhhhhhys+:.` `+ss+-```:ss/` `:oy+/ss/. .sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhd+` `/ss+os+. -oyo- .-+shhhhhyo+:.` `.-/oyhhhhhs+:. `:osoooso- `:oso-` `/ss/. /hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhy- `oy/` ./ss+. `/s/` `./shhhhhs+:.` ` `...` `----` .---.` ``` `.:+shhhhhs+-` .::-.` `:osoos/` `/s/ .ydyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo` `` ./ss+. ` `-+yhhhhyo:. ` .---. .----` .----` `.----` `.---.` .-+yhhhhyo-` `/sso-``/ss/` ` `+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhd/ ./ss+. `.+yhhhhs/.` `---.` `----. `----. .----` `.----` `.---.` `..`` `./shhhhy+-` .oo- .+o. :hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh- `/so. `/yhhhhs/. .--.` `.---.` `----. `----. .----` .----` `.---.` `.--..` .:shhhhy+. -hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhy. ` `-ohhhhy/. `.` `.---.` `.---.` `----. `----. `----` .----` `.---.` `.---.` .:shhhhs-` `sdyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyds` `:yhhhho- .----` `.---.` `.---.` `----. `----. `----` .----` `.---.` `.---.` .+yhhhy/` `odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo` `/yhhhy/` .--` .----` `.---.` `.---.` `----. `----. `----` .----` .----` `.---.` `` `:shhhh/` +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo `/hhhhs- .----` .----` .----` `.---.` `----. `----. `----` .----` .----` `.---.` `..` -shhhh/` +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo :hhhhs- `---. `----` .----` .----` `.---.` `----. `----. `----` .----` .----` `.---.` `--` .ohhhh/` +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydo -ydhds- ` `----. `----` .----` .----` `.---.` `.---.` `----. `----. `----` .----` .----` `--. .sdhhh: +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydo `odhhy- .--. `----. `----` .----` .----` .---. `.... `....` `--:-. `----` .----` .---.` `-:. -ydhds. +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhyds /dhhd/ `.---.` `----. `----. `----` .---. ` ```.....--....``` ```.-. `----` .----` .----` `.:.` :hhhd+ odyhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhyhy` `ydyds` .:-` `.---.` `----. `----. `--.` `.--//+ooosssssssssssssssssoo++/-.` `----` .----` .----` .:. `odhdy. sdyhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. :dhhd: .----` .---.` `----. `--:-` `.-:/+oossssoooooooooooooooooooooooooooossso+/-` `----` `--:-` .--.` .:. -hhhd/ `hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhd: +dyds` `-` .----` .----` `.---.` `` .:+ossssoooooooooooooooooooooooooooooooooooooooooosso+-` `.---` ``` .:` `odydo` -dhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhyd+ `ydhd/ `----` .----` .----` `.-:-` ./ossooooooooooooooooooooooooooooooooooooooooooooooooooosss+. ``.`..``` ``..---::/+- .-` :dhhh. /dyhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhy` .hhhh- ` `----` .----` .----` `. .+ssooooooooooooooooooooooooooooooooooooooooooooooooooosso/-`..--..`.-:++ooo++//:-----` .-` `.` -hhhh- sdyhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhh. -hhhh. .:-. `----` .----` .----` `/ssooooooooooooooooooooooooooooooooooooooooooooooooooss+-`.-/:-`.-/ooo+:-.` ``` .:--` `` `ydhd: `hhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhyd+ -dhhy. `----. `----. .----` .:-` `osooooooooooooooooooooooooooooooooooooooooooooooooosso:`.:+:.`-/oso/-` ` .-. `-:--. `----` `sdhd: :dhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhy` -hhdy` `.` `----. `...` ..---` `` `osooooooooooooooooooooooooooooooooooooooooooooooooss/.`-++-`./oyo:. `./+so- `--. `----. .----` `sdhd: sdhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhd: .` .hhhy` `-:-.` `-.` `.........`` `` `+soooooooooooooooooooooooooooooooooooooooooooooooss/.`:s/.`:oss+-` ./ossooos+. .--.` `----. `----` `sdhd- .` -dhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhds .y+ `yhhh. `.---. `:+osssssssssoo+/:-` /yooooooooooooooooooooooooooooooooooooooooooooooos+. :s+``:oss+. -+ssoooooooss/` `-:-.` `----. `----` `yhhh. .so` odhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhd: -sss/ sdhh- `-` `.-` `/ssoooooooooooooooy+ -sooooooooooooooooooooooooooooooooooooooooooooooss: .ss- -osso- -osooooooooooooss: `---.` `----. `----` .hhhy` -sss/ -hhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhy :sooos/ +dhd/ -:--` `+sooooooooooooooooso` .ssooooooooooooooooooooooooooooooooooooooooooooos+``/y/``+sos/` .+ssooooooooooooooos+` `.---.` `----. `-:-` -dhdo :ssoos/ sdhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhd/ .--::///+sooooos/-..``` -dhdo .--:. /sooooooooooooooooss. `osooooooooooooooooooooooooooooooooooooooooooooss: .oy- -ssss: :ssooooooooooooooooooss- `.---.` `----. `-- +dhd: .--::///+sooooos/-..``` -dhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhh` `/ssssssoooooooossssoooo- `sdhy` .. .-` -sooooooooooooooooss- +sooooooooooooooooooooooooooooooooooooooooooooso. :ss. :soss. `+soooooooooooooooooooooss: `.---.` `----.` .. `sdhy` `/ssssssoooooooossssoooo- `yhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhd+ .+ssooooooooooooooso:` /dhd: `:--` +soooooooooooooooos- `ssooooooooooooooooooooooooooooooooooooooooooos+``+ys. /soss. `osoooooooooooooooooooooooos/ `.---.` `.---.` -dhd+ ./ssooooooooooooooso/` /dhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhd: .+soooooooooooso-` `yhds .----` osooooooooooooooos/ /yoooooooooooooooooooooooooooooooooooooooooos/ `oss. /soss. `osoooooooooooooooooooooooooos/ `.---.` `.---. odhh. .+soooooooooooso:` -dhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhy` -soooooooooos/ /dhd: ` `--:` osoooooooooooooos/ -. `+soooooooooooooooooooooooooooooooooooooooss: .sss. :soss- `osooooooooooooooooooooooooooooy: .` `.---.` `.---.` .hhd+ -yoooooooooos/ sdhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhdo osoooossoooos+ `yhds `--. `-. /yooooooooooooos+ .++. `+soooooooooooooooooooooooooooooooooooooss. ``./- :yssy: `osoooooooooooooooooooooooooooooos. --` `.---.` `.---` odhh. +soooossoooos+ +dhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhd: -yssso+::+ssoso` -dhd/ `----. ` `ssoooooooooooso` `///+. :ssooooooooooooooooooooooooooooooooooso` -/:-.``..:+: /yooooooooooooooooooooooooooooooos+ .:--` `.---.` `.:. -dhd/ .sssso+::+ssoss` -dhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhd- +o/-.` .-+oy- odhh. `----. -sooooooooooss. `/+///+:` .+sooooooooooooooooooooooooooooooooso` `::::::::-...` -sooooooooooooooooooooooooooooooooso` .----` `.---.` `.` `yhds +o/-.` `-+oy- .hhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhh` ` `-. `yhds `-` `----. ` :sooooooooos/ :+///////. .osooooooooooooooooooooooooooooos+``:-``.-::::::/: `osooooooooooooooooooooooooooooooooso` .----` .----` +dhh` ` `-. yhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhs .hhd/ .:-.` `----` ` -ssoooooooy: :+///////+/. -ossooooooooooooooooooooooooos/ `/+/+- ````...-` /yooooooooooooooooooooooooooooooooos+ .. .----` .----` :dhd: odhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhdo /dhd: `.---.` `-:- .osoooooos+ -+/////////+/. ./ssoooooooooooooooooooooos/ `///+: .sso++: .soooooooooooooooooooooooooooooooooos. -:-` .----` .---. -dhd+ +dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd+ +dhh. `.---.` `-- :ssooooos- :+//////////+/-` `-ossooooooooooooooooooy: .+//+: `osooos. +sooooooooooooooooooooooooooooooooos/ `----. `----` .-:` `yhdo /dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd/ odhy` `-` `.---.` `. `+ssoooss. :+////////////+:. .:ossoooooooooooooos- .+//+/ `osoooy/ :yoooooooooooooooooooooooooooooooooos. `----. `----` .` sdds /dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd/ odhy `:--` .----` .+ssooss- -+/////////////+/:. `:ossoooooooooss- .+//+/ +soooso` `osoooooooooooooooooooooooooooooooooy/ .:. `----. `----` sdds :dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd/ odhy .----` .----` `/ssoos+` `:+//////////////+/:. `-/ossooooss. -+////` +sooooy: :yoooooooooooooooooooooooooooooooooso` ----. `----. `----` sdds :dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd/ odhy .----` .----` `:ssoss: `/+///////////////+//-` `-+osss. -+///+` /yoooos+ `ssoooooooooooooooooooooooooooooooooy- `----. `----. `--:` sdds :dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd/ odhy` `. .----` .----` -+ssss:` `:/::://////////////+/:.` `-` :+///+. :yooooss. ` /yooooooooooooooooooooooooooooooooos+ .-` `.---.` `----. `-` sdds :dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhd+ +dhh. --. `----` .----` `:/--` `.``-/+///////////////. `/+///+. -yoooooy/ ` `ssooooooooooooooooooooooooooooooooss. ----` `.---.` `----. `yhdo /dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhdo /dhd: .:--. `----` .----` `` `.-://++/- .+. -/+///////////+- `/////+- -ssooooso``. /yoooooooooooooooooooossssssoooooosy- .--:-` `.---.` `.---. .hhd+ +dhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhds -hhd/ `----. `----` .----` `.-/+ossssooooso``+` /. -///////////. .+////+- .ssoooooy- -``ossssssoooooooossssoo/::-..````````. ``` ``.-` `.---.` `.-:. :dhd: odhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhy` `yhdo `----. `----` .-.` .-+ossoooooooooss/``/. :ys/``-+/////+:` :+////+: .ssooooos+ .- ``.-::/++ooooo/:-.`` ``..--:::::---..` `` `.---.` `-. +dhh. shhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhh. odhh` .` `----. `----` ./ossoooooooooooss/.`--````:sss: `-:://- `/+////+: `osoooooos. :``/::-.` `````..-:////:--..``````````` `.---.` `yhds `hhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhd: :dhd: .:.` `----. `-` `:ossoooooooooosss+:`.--``-++:``/ss+` ` -+/////+: `osoooooos/ -: `-..```````.---:---.``````..-://++oooooooo++//:..` `.----` -dhd/ -dhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhdo `yhds `---.` `----. `/ssooooooooossso/:`.---``-//////. -sss- ` `:+/////+: `osooooooss``/` ``..```...```````..-://+oossssssoooooooooooossssso+:.` `` .-:` odhh. /dhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhy` +dhd- `.---.` `-:. .ssoooooosssoo/:...---``-:////////+: `+ss: /+/////+: `+sooooooos: /: `````...--::/+++oossssssooooooooooooooooooooooooooossso+:. `` `. .hhdo sdhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhd- `hhdo `.---.` ` .. /soooooo//-....---.``-:////////////+/` /ss/``/+///+: `osooooooos+ .o `ooooooosssssssooooooooooooooooooooooooooooooooooooooooooss. `:-` +dhh. .hhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhd+ /dhd- `.---.` -+-`......``...-.`..-:///////////////////` /ss+ `///+: `osoooooooss. o: /yoooooooooooooooooooooooooooooooooooooooooooooooooooooooy/ `--:. .hhdo /dhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhy` `.` `yhhy` .` `.---. ``....`````.. `::///////////////////////+. :sy/ `++- .osooooooooy: :o `ssoooooooooooooooooooooooooooooooooooooooooooooooooooooss/` .- sdhh. `` sdhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhd: ``.-/+osy/ :dhd+ --` `.-:` -` :::::/` +s` /+/////////////////////////` /ss- -- -ssoooooooos+ `y- /yssssoooooooooooooooooooooooooooooooooooooooooooooooosso. .-. /dhd/ -so` .-.` -dhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhds .//+oosso/-.+y- odhd: `---` `.- `- .+///+: `so `/////////////////////////+/ `oyo` `:ssooooooooss. oo `..-:/+ooossssooooooooooooooooooooooooooooooooooooooss+- `----` -hhds -yo. `+sooso. odhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhd- -ys:.`.yo` .yo` `yhhh. `----` `` -- :+///+- .y+ `/////////////////////////+- .sy-`osoooooooooos- :y. ...`` ``.-:/++oosssssooooooooooooooooooooooooooss+:` .. `-. `yhhh` `oy. `+y/``-ss. .hhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhds /h- /h/ /h: .hhhy` .----` :. /+///+. :y/ `/+////////////////////////` +soosoooooooooos/ .y/ `----. ``` ``..:/++oossssssssoooooooossssso+:. .:--. sdhd- `oy+..+y+ -yo` odhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhd: `ss. `/. `.` -dhds` .----` `/``//////` /y+``:+//////////////////////+. /yoooooooooooos+ `ss` --` `.---.` `----. ``...-:///++++o++++/:-.` `..` `.---` odhd/ `/+oss/ -sy. .hhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhds` :s: `:+o. :dhds` .----` ./ `//////` +yo. -//////////////////////+` +soooooooooooso` +y: `---.` `.---.` `----. `....` ```` .---.` `-` +dhd/ `/: `` .so. odhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhd/ `oy+-` :dhds` .--:. -/ `////+/` +ys/``:+//////////////////+: .ssooooooooooss` /y/ .---.` `.---.` `----. `-:--. `----` .-:--` .---.` odhd/ +y: ` :dhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhh. .:+o/:.`/y/ :dhdy` ` .-:. :+ `//////` /sso- `:+///////////////+: `osooooooooooss. /y+` .` `.---.` `.---.` `----. `----. `----` .----` .-:- `sdhd/ /y: :y/ .:` `yhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhyds .o:-:ososs:. . -hhhh. `. `:. -+``/+///+. -ssso:``-/+//////////+/- .osooooooooooss. /yo` .:--` .----` `.---.` `----. `----. `----` .----` ` .ydhd: /y+` -yo` `sy- odyhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhyd/ `ss/+ssosy: .hhhd: `-. .. -o. :+///+: `+soss/. .-////////:.``/ssooooooooooss. /yo` .----` .----` `.---.` `----. `----. `----` .----` -hhhd- /+oso+os. `oy- :dhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhd- `+h/ `.-.``- `sdhd+ .:. ` `+: .////+/. .ososso/-.````` `.:ossooooooooooos+``+y+` -. .----` .----` .----` `.---. `----. `----` `-. /dhdy. .-/osso/+y: .hhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh` .osy+ +h+ /dhhh. .:. :+. -++//+/. -ossoosssooooosssooooooooooooss- .sy/ -:--. `----` .----` .----` `.---.` `----. `----. .ydyd+ -oy- .-+s/ `ydhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhyds --` :yo` .hhhd+ `-:. `:/. .:/+++/. .+ssoooooooooooooooooooooss: `+ys. `----. `----` .----` .----` `.---.` `----. `-:-` /dhhh- `+y+. +y+-` odyhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhydo .:ososs. +dhhh- `-:. :+:. `.--::` `-/osoooooooooooooosss+- .+ys: `-:. `----. `----` .----` .----` `.---.` `----. ` -ydhdo` `oy: `os:/sy/ +dyhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+ `-+syo:. `sy- .ydhds. `-:. ./oo+:-----:/+osooooooooosssso/-`.:oyo- `.---. `----. `----. `----` .----` .----` `.-:- .odhdy- -ys` `` .sy. /dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+ :oss+-` `:`. :hhhdo. `.:.` `.:+sssssssssssssssooo+::.``-/oso:.``--` `.---. `----. `----. .----` .----` `.---.` `` `+hhhh/ /sso:. `+y/ :dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+ ./. `:oyo. `+hhhho. .--` `..```..--------..`..---/+++/-.`` .----` `.---.` `----. `----. `----` .----` .-:-` `+hhhdo` `-/oss/-:oy: :dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+ `-+ss/-oy: `+hhhho. `..` `---.. `..---..``` ----` .----` `.---.` `----. `----. `----` .----` `` .+hhhdo. ://::-.` `:+o+/. /dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+ ./sso-` `/yo. .+hhhhs- `` `----. `.-... `.---` .----` .----` `.---.` `.---.` `----. `----` .--.` -ohhhho. .os//++oss+-` /dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo` :sso:+y/` `oh/ `+hhhhy/. `.---.` `----. `----. .----` .----` `.---.` `.---.` `----. `----. `:shhhh+. -ys. `+sss+.` +dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds` ./. -yo:-+ss/` `:shhhho-` `.---.` `----. `----` .----` .----` `.---.` `.---.` `----.` `..` `-ohhhhy/` :yo` .oy/`-oo. `odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhy. `/s++o+-` `` `-+hhhhyo-` `.---.` `----. `----. .----` .----` `.---.` `.---.` `---. `-+yhhhho-` -/` /yo-:so. `` .ydyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh: `oy/` .:/++oso:` `:ohhhhyo:. `...` `.---.` `----. `----` .----` .---.` `.---. ` `-+yhhhhs:` :ss/` ./sss-` -hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhd+` /: .+so//:..+y/ `:ohhhhho/.` `----.` `----. `----` .----` .---. `` `./oyhhhhs/. `/ss. `:+yo` /dhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds. `-+sss. `sy. .:oyhhhhyo/.` ```.` `----. `----` .---. `` `.:oyhhhhyo:. .o+. `oy+-`` .. `odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh/ :yo..+y+. /y+ `` `./oyhhhhys+:.` ` ```` `.:+syhhhhyo/.` `:ss+``:so//oso+:` :hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdo` . .+s/+y+` `:+oo+-` `./oyhhhhhys+/-.`` ``.-/+syhhhhhyo+-` `-/+o. `:osos:` `.:+- `+dhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh: `-ss+- -sy/--/ss/. `.-+oyhhhhhhhyo+/:--.```` ````.--:/+osyhhhhhhys+:.` `/ss+-.` `:os+. :yhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds. /y+. `+yo. `:ss. `.-/+osyhhhhhhhhyyysso++++++//++++++ossyyyhhhhhhhhyss+/-.` +h/` `-oy+` .odhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhh+` . -ss: -ss. `-` `.-:/+ossyyhhhhhhhhhhhhhhhhhhhhhhyysso+/:-.` +y+` ` :- `/hhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhy: +h/ `+yo. `oyso:.` ```...-----::::-----....`` ./+/-` :ss: -s+ -ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds- .oso-` `:ss: .sy-`:oss/` /yo:/sso/. `+yo.``-+yo. .sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds. .+ssosy+` :ys. `+h/ `` `` /h: `./sy: -sssss+. .odhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdo. `--.` /yss/-` :ss. `oyo+:.` `.:/osso- /h: `-+sy/ `..` .odhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdo. `+y+`.+so+oyo` +y/.:+sss- .osso:.`.oy: :yo.-oss/./yo` .odhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds- -s/ -y+-. /yo` .sy- /s/:-.` .:` /y+` .sy- :sss:. /:` .odhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy: +h: :ys` -ys` `-ss+o. .o/` -:` +h/ +h+ `-+ys` .ss: -sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh+` -o. -ys. .sy. +y/ :yso :y/ :++/. `/++oooss+. oh/ +y: +yooso/-` `o:` `/hdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds- .sy+-` .sy- :yo os+s+ +y- `oy/:sy: `ss:....:ss. `/ys:` /h+ `oy/ -ohhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhy+. .-/ossoosy: `sy- .yo -h+ .so` -yy- `oy/ +y- oy- `:ss+so` `sy: `/ydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy:` .-:. ../y/ /h/ :h+ :h/ .ss. `oy: /y+...-/ss. -sy- .:. `:shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs:` `/ooso/ oy. /y/+y- .so+/////oy: -yooo++ss. :yo `-ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs:` `-. -y+ /yso -yo--::::oy- .ss` -ys. `+/` `-ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs/. ` :s: -yo `sy- `oy- -o+` .:shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+-` `.` ..` `` `-+shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs/-` `-/syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys/-` `-/oyhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs+:.` `.:+syhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys+:.` `.:+oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso/:.`` ``.:/osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyo+/:..`` ``..-/+osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyss++/:-..```` ```..-:/++ssyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyssso+++////::::::::::::////+++oossyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

View File

@@ -0,0 +1,255 @@
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyyysssooo+++++++//////////++++++++oossssyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyso++//::--....``` ````....--://++ossyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhhhhhyyysoo+/::--..`` ``..---://oooyyyhhhhhhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyso++::-..``` ```..-::/+osyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyso+/:-..``` ```..--/+osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhyss/:-.``` ```.-:/osyhhdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhhhyo+--` `.-+oyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhhys++--` `.-/+syyhhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhyys+/--` `.-/+syyhhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhdhhyo+-..` ``.-/+syhddhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhddhso:-``` ```--oshddhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyy/:.` ``:/syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhso/.` `.:+ohhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhyyo/:`` ``:/osyhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdhyo+-.` `.-+oyhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdhh+/.`` ``./+yhdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhy+-.` `..---.. ` `-+sydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhso-.` ``````..:::.` `./ossssss:- ``-:///:::--..`` `.-oshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhhhso:.` `.--::/+++oooossy:. :+yss+++sss+-` ``/+ssyssssssssoo:-`` ``` .:+ohhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhhy+:`` .+sysssssooo++//:.` ..ssyo+```/oyss:. -/yyso+::://++ossys+. .///.` `:/shhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdhh+/.` ./sys+:-...```` `/oyss-` ..ssyo+` /oys+-` ```.-:s+:` `:syy/- `.:/hhdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhys:-` --/-. `-oys+.` ./oyso-` :/syy:- `.+syo:` `` :+yss.` `-::.` .:oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhy/:` ``osyo+ `.+syo:` `````` `-osy+: .+syo/ `-oyyo-` +oyo+ -oyy/: `-:yydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhyo:. /+yss`` `/oys+:-:://+oo+. `:syy:-`````````.:oyo/` `:oys+.` `:::---.` `.ssy+: -/syy-. ````` .-oyhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhhy/- .:syy:- :+ssossssssssoo-` `-sss++/////////++sso/` ./syo/ `.yyyssys+. -/yys-` +oyso`` :+so/-.`` -:yyhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdhs:- `.` .osyo: -:yss+/::---..`` `-sssssssssssssssssso/` .+sy+: `--:+oys/. `/oys+. ``ssy+/ `-oyssyss+/:-. .:oyhhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdhh/:` `.-/+s+-` `:oys+.` .-yys/- `-oss+/----------/oys/` `-osy/: `+syo:` `-oyyo-` .:yys/- `-osy++:+osssso//-.` `-:yhdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhy/- `-:+ossyso:` `+sys/. `.ssy+: ``` `-oyy/- `-oys+` -osyo+-` .:osyo-` ./syo/` :+yso- :/yys-.```-:+osyyy+: .:shdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhddo/` ``:/ossyso+/.`` :+yso-` osyo/``.--::://s+:` `-syh/- `-shy+.` `.+ssso++//:::/+ssss/` `-ssy/- `.+sys/. ``ssyo+ `../+o:. `/oddhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhho/ .:osssso+:-` .-yyy/- ``.` /+yssoosssyyyysyo:` ./++-. `.:/:-` .-oosssyyyyysssoo.` `-ssy+:` ./oys+.` :/yys+/.`` :+hhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhdyo:` ./syso/.` `` osyo+ ``..-:/+so-` :/ysooo++//:---..` `.----:://+/:.` ./oyso/--..`` `-osy+: `.+sssossso/:-`` `-oydhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdys.. `` `/oyso-` .-:+o.` /+yso::/+osssssso:` `.-..````` ``` `/+ssyssoo+/:/+ssy:- .+syo+-:/ssssso+-` `.osdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdho-. `.:+o.` ..ssy+/``.:/osyyy:- .:ssssssss++/:-..` ``-:/++sssssyyyso`` -/syy:- ``.-:+oyo-` `-+ydhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdd+:` .:yyyo/` /+yso++oyyss+:-` .+os/:-..`` ```..-////:.. `osyo+` ``-. ``::://-. `:/ddhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdo/ `-osyso-` .osssso+/.` `` -/yyso+-.`` `-osyyyyyyso:. -+hhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhs:` -:ssyo+`` `.+sss+. `..+/:` .-++osssso/:..` -:ssyo+///osyss/:. `-shhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh:. ..` :/ssy/:` -/yss/- ``-:/osyso-` `.::+ossyso/:-` `.ssyso..` -:+sssso:. .-yhdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhh/- -:so+. `-ossso/. ``osyso..-/+ssyss/:.` ```..---::::::::::::::::::::---..```` `.-:/osyss`` `.+oyss:. `-:ssyoo ./yhdyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhdhs-` :/yys+/ .-oossssss+/ .:sssossyyo+:-.` ``..-::/++oosssyyhhhhhhhhhhhhhhhhhhhhhhhhhhyysssoo++/::-..`` `.-/:: .:osys+.` /+yss`` `.oydhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh.` ` /+yyy/- `-+ssyso:-/+syy:- .:syss+:-`` ```..-:/+oyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyoo+::..``` ``ossss-. /+yss.` ``yhdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhh/- `./::` `-+syso:--osyss/:.` `-osyso-` `:/:-` ``..::++ssyhhhhhhhhhhhhhhhhhhhhhyyyyyysssoooooooooossssyyyyyhhhhhhhhhhhhhhhhhhhhhyyso+/:..``` -/yys/- -:ssyo+ ``` ./yhdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhs-` ``/oyss.` `/ossossso+:- `./oyys/- `..-//osyhhhhhhhhhhhhhhhyyssooo///::-----....`````````````...-----::://+oossyyhhhhhhhhhhhhhhhyss+/-..` :+yso- `-osyso-` `./++.` `.oydhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh-. `./+yys/:`` `.oosss+:` `.oos/- .-:/+yyhhhhhhhhhhhhyyss++/::-..```` ```..-:::++osyyhhhhhhhhhhhhyy++:-. -/yys/- -/ssyo/.` ``/+syyo/.` .-hhdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhd+: -/osyo/.` .-osyo+-` ...` `.:/+yyhhhhhhhhdhhyyo+/:-..``` ``..--/+osyhhddhhhhhhhyyo+:.` `.ssyss/:` .-ssyso.` `./osssooyss/- -/hhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdy/. -:sssss+:` `.+oyss:. ``.:/syhhhhhhhhdhyss+/-.``` ```.-//ssyhdhhhhhhhhyy+/-`` .-+sssso/---:+oyso:. -/sssso-.`/oyss/-` `:sdhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdd+: `./ossooosso+-` ..ssyso.` `.-+oyhhhhhhhhhhss+/-.``` ``.-:/oshhhhhhhhhhyso--`` `-:ossssssssss+.` `-:sssoo-. `./osyo/-` -/dhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyo ``+oyss:-.:/ssyoo.` -/syyo/` ``-:oyhdhhhhhhhyy+/:.` ````` ``.....`` `...````` `.-/+syhhhhhhhdhyo/:`` .-/oooo+++-. `./osssso+`` -:ssyo+ +sdhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhs-` ``oos/- :/ssys+-` `:+o:- `.:+shhdhhhhhhho+:.` ``` `.-----.. `.-:::--.` `.--:----`` ``..````` `.:/+yhhhhhhdhhso:.. `..`` `.+oyss++osyo/.` -:o/: -ohdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhdho.` `..` `-+oyys+/` `` -:syhhhhhhhhys+:-`` `.-----.` `.-:-----`` `.-:----.` ``--:----.` ``------..` `--/syhhhhhhhhys:-` `-+oyys+:``./oyyo:- .` `+ydhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh-. `.+oyss+:` -/oyhhhhhhhhs+/..` ``...` ``--:----`` `.-------`` `.-------`` ``.------.` ``--:---.. ``` `./+syhhhhhhhys/: -/ssys+-` `.+oyyy-. `.hhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ `-/osss+-. ``/+hhhhhhhhyy/:.`` ..-----.` ``-------.` ``-------`` `.------.` `.------.` ..-----..` `....`` `.-:syhhhhhhhh+/.` .:ooo-. `-+oo.` :+dhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydhs- `-/ssyss.` ``:+yhdhhhhdys+-` ``..`` ``.------. ``-------. `.------.. `.------.` ..------.` ..------`` --:--..`` `./sydhhhhdhy+/`` ``.. ``` .ohdyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhdyo` -/s++`` `.+sddhhhhhho+.` .-:::--` `.------.` `.----:-.` ..----:..` `.------.` `.------.` `-------`` `.--::---`` ``/ohhhhhhdds+-` `+sdhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhd-. `.`` ``/+yhdhhhhho+-` `` `.------.. `.------.` ..------.` ..------`` .------.`` `.------.` ``-------.` ``-------`` `-/+hhhhhdhho+`` `.hhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ `./ohhhhhdhy+:`` `.----.` `..-----.. `.------.` `.------.` ``-------`` `.-------`` `.-------` ``.------. ``------.. `:/shdhhhhds+-` :odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhy-` :+yhhhhhhdo/.` ..:-----.` .-------`` `.------.` `-------.` ``-------.` ``------.` `.------.` ..------.` `..:----.. `./+hhhhhhhh+/ `-ohdyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds.` :/dhhhydhh+:` ``.` ``-------`` `.-:-----`` `.-:----- `.-:----. ``--:----. `.------.. `.------.` ..:-----.` .-------` ` `-/yhdhhhdd+: `ohhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydd/- `-shdhhhhdo/` ``--::-.` `-----:-.` ``-------`` ``-------` `.----:-.` ..----:-. .-----:.. `.-----:.` `.------.` `-------`` ```. /odhhhhdhy:. -:ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdyy` ..yydhhhhho/ `.----:--` `-----:-. ``------.. `.------.` `.------.` ..------.` .----:--`` .----:-.`` ``-------.` ``-------.` `...` /+hhhhhdhy-. sydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+- `:oydhhhdyo:` ..` `.------.` `.------.` `..-----..` `.------.` `.------.` `-------`` `.-------`` `.-------`` ``.------.` ``------.. `.-..` `-oydhhhhhs:` ./hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydho. :+hhhhhdys.. `.----.. `.------.` `.------.` ..------`` `.-------`` `--:----.` ``-------.` ``-------` ``------.` `.------.` `..-----..` `.--.` `.oydhhhhho/ .+ydyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhho` -/ddhhhdho-` `.-::---.. `.-:----.` `.------.` ``-------`` `.-:-----`` `.-:----- `--:----. ``--:---.. `.------.. `.------.` ..:-----.` .-:-. `-+hdhhhdd+: `oyhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd/- .+ydhhhdd+: ``` ..------`` .-:--:--` -----:-.` ``-----:-.` ``-------`` `.----:--` `.---::-.` ..----:-. .-----:.. `.-----:.` `.------.` `.-:-.` -/ddhhhdho-` .-ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyy /odhhhhdo+ `.---`` `.-------`` `.-------` `.------.` ``-------. `.-----:.. `.-----.`` `....---`` ..---:--`` .----:--`` `-------.` ``-------.` ``---.` /ohhhhhds+`` sydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+: -/dhhhhhy/. --:----.` ``-------`` `.------.` `.------.` ..---::-.` `..-.... ``` `..------`` `.-------`` `.------.` ``.------.` `.--:.` .:shhhhhd+:` -/dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydhs- ./ydhhhhd/- ``.------.` ``------.. `.------.. `.------.` ..----..` ```.......-----.......``` ````..-..` ``-------` `.------.` `.------.` `..:--`` .:hhhhhdy+. .ohdyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy-` :+dhhhhdo/ -.` `.:-----.` `..:-----. `.-:----.` `.-:::::`` ``` ``...-::////+++ooooooooooooooooooo+++///::-..`` ````` ``--:---.. `.------.` `.------.` .-:--` :+dhhhhdo/ `.sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds/ .-dhhhhdy/. `.-::-.. `.------.` ..------.` ..------`` ...`` ````--://++ooossssssssssssssssssssosssssssssssssssssssooo//:--`` ..-----.. `.-:----.` `.------.` `----` `:sdhhhdd:- :+ddyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd-. `.oyhhhhd+: `.------.` `.------.` ``-------`` `.----:--`` ```..-:://+oosssssssooooooooooooooooooooooooooooooooooooooooooosssssso++/:-``` ..------`` .----:-.`` `------.` ``---.` :/dhhhhhs-` ..hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdys `-shdhhdyo` ` `.------.`` ``-------.` ``-------.` ``---..` ``.-:/++oosssssssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooosssss++:-.`` `.----:--`` `.-----.` ````` ``---`` +sdhhdhy:` osdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+: +sdhydhs-` `.-`` `.-------`` `.-------` ``-------. ``` `.-:++osssssssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosssso+/-.` ``.-----.` ``` ..:-` -ohdyhdyo`` -/dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhy-` -/ddhhhho.` `.--:--.` ``------.` `.------.` `.------.` ``:/oosssssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossssso+:-` `````````````````` ````` ..:.` `+ydhhdd+: -shdyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy/. `-shhhhhh-. ``-------. ``------.. `.------.. `.-::-.` `:+ossssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosssss+:.` ``.......`````````..-:::////++++ooso:` `` ``.-`` `.hhhhhds:` `:ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho` `-shdhhdo/ ..-----..` `.------.` `.------.` ``.- `/+sssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosssso+/-..``..---..`````..-::/++ooooooo+++/////::/:.` ..-` ``-.` :odhhhhy:` `+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyddo: /odhydhs- `..` ..------`` .------.` `-------.` `:/sssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossso+/:`````:::--.````.-/++ossso++/::--...````` ..:--` ``.`` -ohdyhds+ -/ddyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd.` ..dhhhhho.` .-::-.` `-------`` `.----:--`` `.----:--` `./syooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossso+-.```--//:-.```.-/oossso+::-.` ``` ..::--.` `` `oydhhdd:. ``hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdys `+sdhhdd/- .-:----.` ``-------.` ``-------.` `.---::`` :+ysooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossso+:.` .:/+/:-``..:+osssoo:-.`` ```` `.---...` `.------.. .-ddhhdyo` osdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ ./ydhhdys` ``.-------` ``.---::-.` ``------.. `.--- ..sssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+/.` .-+++:-```-:osyss+/-.` ..` `.-:-.` `.-::---.. `.------.` +sdhydy+. -+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:. `:yhhhhh/. `` `.------.` ..--.--.` `..---::.. ``` :+ssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosso+:.``./oo/:.` :/+ssss+:-`` `.:/oo+.` `..::-.` ..------`` `.------.` `:yhhhhh/. `:yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdho- +sdhydy+. ..:.. `.---::-.` ```..--.`` `-oyooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossso.` `.oos:-```:+sssss:-` `./+sssssso+` .-:--`` `.-------`` `.-------` `:ydyhdso .+ydyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy:` ``` `.dhhhhy+` `---::.. `.-..`` ````......``````` ``` .ossooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooso+.` `:oy+: ``-/ssysso:. `-/osssoooooosso/` `.-::-.` ``-------.` ``-------`` /sdhhdd-. ``` `-sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho` .o// /oddydd:- .-------`` `.-:/++ooooooooooo++//:--..`` -/ysoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss/- `/+y+/ `:/sssss/:` .-oosssoooooooooosso:. `.:::-.` ``-------. `.------.. .-dhhhds+ .o// `+yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdo/ -/yso`` `.shhhdyy` `.----:-- ..+ossssssssssssssssssssssooo+//`` +ossoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooss+/```:/yo:` `-+ossss+/` `.:osssoooooooooooooossoo.` ..:::-.` ..-----..` `.------.. sydhhds-` -/yss`` :+ddyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydd/- ``ssssy:- .ohdyhd+: `.` ``--:-. `-+ssssooooooooooooooooooooossssso`` `.ssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooyo/.` .+sy:- ``oosssyo/.` `++sssoooooooooooooooooosso/. `.-:---.` ..------.` .-------` -+dhhdhs- ``osssy:- .:ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.` :+ssosso/` `:hhhhhy- ..:-. ``.` .:sssoooooooooooooooooooooooooosy/: :/ysoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosy+:` /oh+: `/ossosy/: :+ssooooooooooooooooooooooosso-` .-::---.` ``-------`` `.-:--:-. -shdhhd/. :/ysosss+` ``hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyy `:oyoooooyo/. +sdhydy:` ----:-.` oossoooooooooooooooooooooooooosso- `.+soooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossoo :/hs/. `-ossosyo+ `-osyoooooooooooooooooooooooooossoo` --:--:-.` `-----:-.` ``-----` `-sdhhdyo `-oyoooooys/. sydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ ` ```````...-:sssooooosss:.` ``yhhhhy+` ..------.` .-ysooooooooooooooooooooooooooooyo:` ./oyooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosso-` `:sh+: `+oysosso-` ``+ossooooooooooooooooooooooooooooosy+: `.----:--` `.----:-.` ``-::.. +sdhhhh.` ` ```````...-:sssooooosss:.` /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+: `-:////+++++oooosooooooooosoo/::--...````` -:ddydd+: `.--::-. :+ssoooooooooooooooooooooooooosso/` `-sssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+.` -/yss`` -:ysosss+.` :/ysoooooooooooooooooooooooooooooooooso:` `.------.` `.------.` `.-:-` -/ddydd/- `-:////+++++oooosooooooooosoo/::--...````` -/dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh/. `.+oyssssssssssoooooooooooosssssssooo+++/:` /oddhhh.` ``` ``--:.` `.+soooooooooooooooooooooooooooosy:- /+ysooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss-. `.ssy/- `-+sssosy:. `:oyooooooooooooooooooooooooooooooooooosss:- `.------.` ..------.` ...` ``yhhhds+ `.+oyssssssssssoooooooooooossssssoooo+++/:` `:hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy- `.ooysooooooooooooooooooooooooossssyy+/.` .ohhhdyo `---` ``.` `:oyoooooooooooooooooooooooooossoo` ``ossooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosy+/ `/oys+. `-ossosso+ .:sssoooooooooooooooooooooooooooooooooooossso`` `.-:----.` `.------.` ```` +sdhhds.` ``ooysoooooooooooooooooooooooooosssyyo/.` -ohdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdh+. `.+ssooooooooooooooooooooooooosss/:` ./ydhhd+: ..:----`` .+ssoooooooooooooooooooooooooosy/- ``sssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooss+. .+sys+` /+ysosss:` ``ossooooooooooooooooooooooooooooooooooooooooss+: .-:-----` -------.` -/dhhdy+. `.+osooooooooooooooooooooooooosss/:` ./ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy/. `:/ssooooooooooooooooooooosso/-` -shdhhy:` `.------.. .ossooooooooooooooooooooooooosso- +ossooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss/`` :+yyy:- `.sssooyo:` -/ysooooooooooooooooooooooooooooooooooooooooooos+-` `.-------`` `.------.` -yhdhhy- -/ssooooooooooooooooooooosso+-` `:ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds-` `/+ssoooooooooooooooooss+/.` `:hhhdho. `.------.` -ossoooooooooooooooooooooooooyo-` :/ysoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss-. ..sssso`` :+ssosso/` `.+sssoooooooooooooooooooooooooooooooooooooooooooss+. `.------.` `.------.` .+hdhhh/. /+ssoooooooooooooooooss++.` `.shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhho` .:ssooooooooooooooooso/.` :+dhhdy/` `.----:-` .ossooooooooooooooooooooooosso/` ...` `-ossooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooss+/ `/ssss/- `-oyooosy:. .+ssoooooooooooooooooooooooooooooooooooooooooooooosy/- ``` `.------.. `.------.` `-sdhhdo/ .:ysooooooooooooooooso/.` +yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ :+ysooooooooooooooooyo/. osdhhho.` ...` `.--:-` .+ssooooooooooooooooooooooosy-. //:` `:oyooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosso-` `/oys+. `-ossoosoo` -/ysooooooooooooooooooooooooooooooooooooooooooooooosso+ `.-.` `.-:----.. `.-:----.` `+yhhdys :+ysooooooooooooooooyo/. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ oossoooooosssoooooooso+. ``yhhhds+ `.-:-.` ``:-.` ./oyooooooooooooooooooooosso+ `.+++-` :+ssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+.` `` ``::.` /+ysoosy/- `oossoooooooooooooooooooooooooooooooooooooooooooooooooss.` ---.` .-------`` .------` /oddhhh.` +ossoooooosssoooooooss+. :/ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd/: `.sssoosssssooossssooosso. ..hhhdd+: `-:----. ``.` `-oyoooooooooooooooooooooss/- -:+++// ``osssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosy:- ``/:-.``` :/+oosso-` .-ysooooooooooooooooooooooooooooooooooooooooooooooooooosy:- .-:--`` `.-------`` `.--:-` -/ddhhd-. ``sssoosssssooosssoooosso-` -:ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd:- .:yssssso+/:...:/ssssssss:` -:ddhdd:- ..------.` `/ossooooooooooooooooooss+. `.:+///++-. .:sssoooooooooooooooooooooooooooooooooooooooooooooooooooooooosso+ -://:::--.`````..:--` :+ssoooooooooooooooooooooooooooooooooooooooooooooooooooss+: ..:----.` ``------.`` `.:-.` .-dhhdd/: .-ysssssoo/:...:/ssssssss:. .-dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd-. :+yso+/-.` --/oossy/- :+ddhhh.` ..------.` -:ysoooooooooooooooooos+.` .:/+/////+/-` `-+sssooooooooooooooooooooooooooooooooooooooooooooooooooooosss:. `:/::::://:::--..````` `.+sooooooooooooooooooooooooooooooooooooooooooooooooooooosso/` `-------.` `.------.. `.-` ``hhhdds/ :+yso+/-.` .-/+ossy/. `.hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.` `:/:-.` ../+y/: /sdhhhy`` `.------`` `` ``sssooooooooooooooosso/ .-+/////////+:. .-osssoooooooooooooooooooooooooooooooooooooooooooooooooooyo:` ` `.-:://:::::::::::::.` ./oyooooooooooooooooooooooooooooooooooooooooooooooooooooosso/` ..------.` `..-----..` ``` sydhhy+ :/:-.` ../+s/: ``hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh`` `` ``... `+yhhdyo `.-`` `-------.` `` :/ysooooooooooooooss/- :/+//////////++-. .:ossooooooooooooooooooooooooooooooooooooooooooooooooss+: `/:-` ``.--:::::::::://:` `-ossooooooooooooooooooooooooooooooooooooooooooooooooooooosso/` ..------.` ..------.` +sdhhho` `` ``... yyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyy` .ohhhds+ `.:--` `.------. ``` `-+ssooooooooooooosy:- :/+////////////+/-` `/+sssoooooooooooooooooooooooooooooooooooooooooooosss.` .-++//:.` ```.---::::/:.` -/ssoooooooooooooooooooooooooooooooooooooooooooooooooooooosso/ `` `.------`` `.-------`` /odhhds-` oydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdys `-sdhhdo/ .-::--.` `.----:`` ` `.+sssooooooooooosy/- :/+//////////////+:- `/+sssooooooooooooooooooooooooooooooooooooooooosy/: `:+///++-. `...````````.` +ossooooooooooooooooooooooooooooooooooooooooooooooooooooooss/- ..-` ``-------.` ``-------`` :+dhhdy:` osdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdso `:ydhhd+: `.------.` `.-::.. .-sssooooooooooss+: -:+///////////////++:-` `-+osssoooooooooooooooooooooooooooooooooooooss+. .//+//+// `/oss+//:-.` ``sssooooooooooooooooooooooooooooooooooooooooooooooooooooooosy-. --:--` `.----:-.` ``------.. -+dhhdy+. +sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ ./ydhhd+- `.------.. `.-:-` :/sssoooooooosso/` `-+/////////////////+//-. `./+sssooooooooooooooooooooooooooooooooosss+.` -:+////+-. `:oysssssys/. -:ysooooooooooooooooooooooooooooooooooooooooooooooooooooooosss`` ------.` `.------.` ..-----` ./hhhdy+. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ .+ydhhh/. `.-------`` `---` .:osssooooooooyo-` `:/+////////////////////-.` ``-/osssoooooooooooooooooooooooooooooosy:- `.++///+/:` `-ossooooos+.` :+ssooooooooooooooooooooooooooooooooooooooooooooooooooooooss+/ `.------.. `.------.` ..-::`` `:yhhdho. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo+ .ohdhhh:` ``` `.-------`` ``-.. -:sssoooooooss+. `:+////////////////////+/:-. `./+sssoooooooooooooooooooooooooossoo` -/+////+:` :+ysoooosso/ `.+soooooooooooooooooooooooooooooooooooooooooooooooooooooooosy/: `.------.` `.------.` ``-:`` -yhhdho. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy:` ``:-.` ``------.` `.`` :/yssoooooosy/- .-++////////////////////+++-. `./+ssssooooooooooooooooooooosss:. `-/+///++:- ``sssooooosy:- `:oyooooooooooooooooooooooooooooooooooooooooooooooooooooooosss-` ``` .-:--:-.` `--:----.` ```` -shddhs- :odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- ``:::-. ``-----:.. ` `-+sssooooosss`` :/+//////////////////////++/--` .:+osssooooooooooooooooooyo:` `-+//////+`` :/ysooooosss.` .ossoooooooooooooooooooooooooooooooooooooooooooooooooooooooss/. `.-:`` `.----:--`` `.----:-- -shddhs- :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- ``:---:-.` `..----:..` `.oosssooosso/` .:/+//////////////////////+++::.`` .-++sssssooooooooooosso/ //+////+:- `.+ssooooosso+ .:ssooooooooooooooooooooooooooooooooooooooooooooooooooooooooyo-` `--:--.` ``-------` `.------.` -shddhs- :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- ..------.` ..------`` `-/osssoooss+.` `-:++///////////////////////+///:.` ``-:/ossssooooooosss.` .-++//////.` .+ssoooooosy/: :+ysoooooooooooooooooooooooooooooooooooooooooooooooooooooosso/` `-------. `.------.. `.------.` -shddhs- :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- `-------`` `.-------`` `-:ssssooss+/ ``:/+/////////////////////////////:-. `.-/+ossssoosy+: `://////+/-` .:ssoooooosso-` +ossooooooooooooooooooooooooooooooooooooooooooooooooooooooss/: `..:----..` `.-:----.. `.------`` -shddhs- :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- ``--:----.` ``-------` .-osysooss+: `.:/+////////////////////////////++:-.` ```:/+ssyso-` `:/+//////: +ossooooooyo/. `.sssooooooooooooooooooooooooooooooooooooooooooooooooooooooosy-. ..:-----.` .-:-----` --:::`` -shddhs- :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo/ .ohdhhy- ``` `.-:--:-. `-----:-. -:ssssoyso-` ../++////////////////////////////++//-.` ../:.` -:+/////++.. .-ysooooooooyo-` ` -:ysoooooooooooooooooooooooooooooooooooooooooooooooooooooossoo `... `-------`` ``-------`` `.-:`` -shddhs- :odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo+ .ohdhhh:` ``--` `.------.` ..-----..` .-+osssyo+`` ..........-://+////////////////////+//:-.``` `.++/////+// /ossoooooosso/ ` :+ssoooooooooooooooooooooooooooooooooooooooooooooooooooooosy+: .-:-.`` ``-------.` ``-------.` `.`` -yhhdhs- /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ .+ydhhh/. ---.` ..------.` ..------`` `-:/:---`` `````--///////////////////////++///-. `-/+//////+-. `-oyoooooooosy/- `` `/sssooooooooooooooooooooooooooooooooooooooooooooooooooooosss:. .------` ``-------.` `.------.. -yhhdho. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds+ .+ydhhd+- --:--.` `.------.` ``-------`` ``` ```....... .-:-` .-//+////////////////////+++-` `-/+/////+//. `-ossooooooooss.` `. `-oyoooooooooooooooooooooooooooooooooooooooooosssssssssssssys+. `.---::-.` `.------.` `..-----..` .:hhhdho. /odhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdso ./ydhhd+: .-:----.` `--:----.` ``--:----.` ``` `.-::/++oooooooo/: ``o/-` `:/++//////////////////+/.` .-+///////+/.` :/ysooooooossoo ``.. ./oyooooooooooooooooooooooooooooooooossssssssssoooooooooossyo-` ``..-:::.. `.------.` ..------`` -/dhhdy+. +sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdys `-sdhhdo/ `.-------`` `.-:-----` `.------. ```-:/+ossssssssosssosss+` +:.` -.```:/+///////////////++.. ``+///////++:- ``sssoooooooosy+: `-```-sssoooooooooooooooooooooooooosssssso++///:-.....````````.... ````` ``.--.. `.------.` ``----:-- :+dhhdy/. +sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyy `.ohhhds+ ``-------`` `.------.` ..---::.. ``--/+osssssooooooooooooosy/- `./- ``so/.` .:/+////////////+:: `-/+///////++`` -/ysoooooooooss:. `-` `./++oosssssssssssssssssssssssoo+/:--.```` ``````````````````` ```` ``...`` `-------.` ``--:-. /odhhds-` osdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy`` `+yhhdso `.------.` `.------.` ..-..`` `.-/+sssssooooooooooooooossso+```-/.` -:yys+/`` -:++////////+//.` `:/+///////+/: `+sssooooooooss+. ..-` ``..-::://++oooooooooo+//::..` `````..----:::::::::---...`` ``` `.------.` `.-.. +sdhhho.` syhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.` +sdhhyy ` `.------.. `.------.` ` `-:+ossssooooooooooooooooossso/.``.:-- .-ossss/:` ::+/////++/:` -:+//////////-` ./oyooooooooooyo:` --.` ...```` ``.....---..`` ``..--://////////::----......````` `.------.` ``` sydhhy+` ``yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd-. /oddhhh.` `-.` `.-------`` `-----:-.` :/oossssooooooooooooooooosssso-. `.::-` ...` .:ossso+. ``...--::/.` `.++////////+/-` .:sssoooooooooss+`` :- ``+++//::-..` `.--:////////::--...``` `````````````` `.------.` ``yhhdds/ `.hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd:. -:ddhhd-. `.-:`` `.-------`` `.--.. `./+ssssooooooooooooooooooossso/-. `-::.` ../++:- ``/osss+/ ``` `.:////////////:` +ossoooooooooss+: .-:- `.::---..``` ``.---:://:::--..````` `..--::://++++++ooo++++++/::--.` `.------.` ..dhhdd+: .-dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd/- .-dhhdd+: `-:--.` ``-------`` `` `:/osssooooooooooooooooooossso+-.```:::.```-:////++.. `.ossss:- `` `.//+////////++.. .-ssooooooooooosy-. -/-. ````` ``..---------..`````````````..::///+ooosssssssssssssssssssssssssso++/:..`` `.----:-` -:ddhdd:. .:ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddo: ``hhhhds/ `.-----. `.------.. `-/sssooooooooooooooooosssss+/:.``.-::-. ``-:+///////+:.` -/ssss+.` ` ``//+/////////+// /ossoooooooooosss`` :/`` ````...`````.....```` ```````--:://+ooosssssssoooooooooooooooooooooooooooosssssoo+/:``` ``` `.--:-` :oddhhh.` -/ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds/ oydhhho` `.----:-.` `..-----` ./oysoooooooooooooosssssoo/:- ``..:::.```.:/++////////+++-` `:ossso-` -:++//////////+-. `:oyoooooooooooss++ `-// ```````` `````...--::/+++oosssssssssoooooooooooooooooooooooooooooooooooooooooossssoo/-.`` ```` `.-. +yhhhyy /oddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo` /odhhdy:` ..------.` .-:.` :/yssooooooooossssssoo+::.. `.--::-.` `.::/++////////////+//`` -/ssso+ -/++////////+/:` `-sssoooooooooooss:. .+:- `````.....---::///++ooooossssssssooooooooooooooooooooooooooooooooooooooooooooooooooooooosssss+/-` `.. `` `.shhhds+ +shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds-` ./hhhdho. `.------.` `` ``` +oyssssssssssoo++/:-..```---::-..` ..-////////////////////++:- ``oosss:- ``/////////+/:` +ossooooooooooosso. `-o-` .+++++oooooooosssssssssssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosssss:. `-:-.` .+ydhhd+- `.ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy:` -yhdhhy-` ``-------.` :::` .-/+++++///::-..````..---:-.````.--/////////////////////////+/-` .:ssss+.` -:+/////++.. .-ssoooooooooooooyo:` :/+. .:ysssssssssssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss-` `-:---`` -shdhhy:` `-sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy+. .+ydhhd+- `-------. -/o:-```````````````.------.`````..::/++////////////////////////////.` ./oyss+. `./////+/: `/ossooooooooooooss+.` o+:` /+ysoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooys+. `----:-. ./hhhdho. ./ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhs- `.sdhhds+ `` `.----:-.` `.:::----.......---..`` ``..::/+++///////////////////////////////+// /ossy/- `-/+///.` ./syoooooooooooooss+: ``s/` oossooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+.` ``--:.` /odhhds-` .ohdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:. ``..-.` +sdhhhh`` `... `.---:--` ` `````````` --.` .-/++++////////////////////////////////////++.. .-ssso+ `:++/.` -/ssoooooooooooooosy-. -/o/ ``sssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss:. ` ``.` `yyhhhy+` `.. `-yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+- ``.--:/+osy+/ -/ddydd/- `-:.. `.--::.` `-`` `--------:- ooo- `.//+///////////////////////////////////////+/:` +osss.` -::- ``ossoooooooooooooosoo` +s:- -/yysooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss/: ``-.` -:ddhdd+: .:ooo`` `` ./dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdo+ `.-::/+ossyssossso` `.hhhhds+ ..:-.` `--:-. `--. .//+/////+/.` /+h/- `-/+////////////////////////////////////////+/-` -/yyy/- ```` :+ssoooooooooooooosy+/ `-oy`` -:ooosssssssoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+-` `.-:--.` /oddhhd-. `osyso`` `./++//:.` :+dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdys `.-:++ossyyssso+/-.`-osy.. osdhydy-` `--:--` `--: `-- `./+/////+/:` `:yo+ ://///////////////////////////////////////+//. -osyo/ `:oyooooooooooooooosss:` .ooo ``..-:/++ossysssssooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooossyoo.` `------:`` `.sdhhdys .-yyo-` +oyyyyyyso.` osdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh`` ./shsso++-:/sy/- `-sh+: ./dhhdhs- ..:----` `..` -:`` -/+//////+-` `:sh-. ..++////////////////////////////////////////+:. `:oys+.` :/ysooooooooooooooooys/. .:h+: ``` `.-::/+oossssssssoooooooooooooooooooooooooooooooooooooooooooooooooooooooosss+:` --:-- .ohdhhd+- :+ho-` .:yyo:.-:+syo/` yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd:- `.+ss+.` `+ss+` `+ss+` -shdhhd+- `------.. ` ..:. .-++/////+/: `+yo/` //+///////////////////////////////////////+/: `+syo:-.sssooooooooooooooooss+.` /oy:` `.---..``` `..-:://+ooosssssssssoooooooooooooooooooooooooooooooooooooooosssss+/.` ``---`` `.`` ./hhhdhy- `+ss+` `/oyo:` `.+syo.` .-dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyddo/ :+yo.` :+hs:` :+hs:` `-sdhhdys `..-----.. `:-```/////////+`` -/hs:` .-+////////////////////////////////////////// :ossooossooooooooooooooooss+: ``ys+. ..-::---.` ``..--::/++ooossssssssssoooooooooooooooooooooooooossssss+/-` --::---` +sdhydy:` `/syo:.``./syo/` `.+yo/` :+ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+` .:hs/. .-hy+. .-so:` +sdhhhd-. .-------`` ---` -:+/////++-. `.yss:. `-/+//////////////////////////////////////++.` -/sssssooooooooooooooooooss.. -:hs:` `` `.-:----.` `....``` ```..--://++ooosssssssssssssssssssssssssssoo+/--`` `.------.. `.hhhhhy+` -:yyso+/+syy-. ./sh/- +sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy-` ``sss:` ``:-.` ```` .-ddhhds/ `.-------`` `./. `.+///////+:` /oho+ -:++////////////////////////////////////++.` -/ysooooooooooooooooooosso+ `/ss+` ---` `--:----.` ``--:----.` `````..-::///++++ooooooooooo++//:-.``` ``.--. `.-:--::`` /oddydm/- :/ossyyy+/ .:syy.. `.sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdho. /oho/ ``.-: osdhydy:` ``-------.` `::: `-/+/////+/:` `-syy/- `//+///////////////////////////////////++.` -/ysoooooooooooooooooooss:. `:sh/: `--:--`` `.-------` `.-:--:-. ``..`` `````````````` `.::----.` .-:-- `-sdhhdys ``` ``.--.` `.syyo/ ./ydyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy:` -:o:- `.++syy-. ./hhhhhy:` ``------.. `:/`` -/+//////+-. `:oyso:` `-//+///////////////////////////////////` :+ssooooooooooooooooooss+. `-osy.. ``-------`` `.------.` `.------.` `..-----..` ``` ` ```...` `-------`` `.`` `-shdhhd+- `.so/. `.o+/.` -shdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+: :+yys+/.` .+ydyhds+ ..---::.` -::- `.++/////+/: `/osss/- `.:/+///////////////////////////////+/: `/sssoooooooooooooooooos+.` :+yo+ `.------.. `.------.` ..------.` ..--:---`` ..---...`` .-:::--.` ``-------.` /odhhdho. -/hy+. `` -/dhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdyo `..`` `-oys+.` `oyhhhhd-. ..--:-. ``+/.` :/+/////++.. .-sssss-. `.//+/////////////////////////////+:. `-oyooooooooooooooooooss+: ``ssy/- `.------.. `.------.` `.------`` `-------`` `.-:::---`` ``.-------` ``.------. `.hhhhhho.` `.+ys+` `.-.` +sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh`` `.:/+os+/:.. ./sy+: -:ddhhdy+` `` ``--:-.` ::+. `-+////////:` /+ysss+-` `.:/+/////////////////////////+//. `-ossooooooooooooooooosss.` -/yyo- `-.` .-------`` `.-:----.` ``--:----.` ``-------.` ``-------` `.------.` `.-::-- /sdhydd/- ./sh:- `:sy/: `-:`` `yhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydd+: .:yyoo+ssyso++oss.` osdhydho. ``.`` ``--:.` .+/: `./+/////+/:. `.+sssss+/```.-//+////////////////////++/:` /+ssooooooooooooooooosy+/ `.+syo-` ..:--.` ``-------`` `.-------`` `.-------` `.------. ``------.. `.------.. ..-`` ./ydyhdys` ./yso` `-oyy-. ./sh:- -:ddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhy+` ``::.``.-/++sssss+/:.````.-`` `:yhhhhd+: `..`` ``--- `./o.` -:++/////+:- ``/osssss+:```.-:/+/////////////////+//`` .-sssooooooooooooooooosso-` .+sy+: .-:----.` ``-------.` ``------.`` `.------.` ..------.` ..-----.. `.------.` -/hhhhhh/. +oyoo..`` :+ho+ .:yss`` +sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdy:` `.ossoosssoo/++sy:- `:ydhhhhh.` ``-.` .-`` -:+:```//+/////++.` `.ssssosso:-`` .-/////////////////:.```-+sssooooooooooooooooosso-` -/yss.` ``.------. `.------.. `.------.` ..------.` ..------.` .-------`` .------.` ``yydhhdy/. `+osssso+::ooy:. /oh+/ `-sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydhs- .-yso:.--/oossso+-. :+ddyhds+` ..-.. .`` +//. `-//+/////+:.` .:ossoosss+/.````.--::::::::--.` `./+sssooooooooooooooooooss/- ``ssy+: ` `.------.` ..-----..` `.------.. `.------.` `.------`` `.-------`` `.---::.` `/oddyhdo/ `.-:/oossssso/-.` `.yss-` .ohdyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd+- :+hs/. `.--.```.-` ``sydhydyo. .-:.` ` `-+/: `.:++///////-. `./ossoossso+/--.`` `````` ``.-:+osssoooooooooooooooooosyo+```:+ys+. `-.. `.------.` ..------.` .-------`` `.------.` ``-------.` ``-------`` ``--.` ./ydhhdhy.` `.-:/oosssoo//+ys:` ./hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdyo `-:/oss+.` +oy/- .:yhhhhdo+ ``:--` ./+-. `.//+///////.. `.+ossooossssoo++/::::::/++oosssooooooooooooooooooooss+-` ./syo/` .-:--.` `.------.` ``.------`` `.-------`` `.-------`` ``.------.` ``-------. `` /odhhhhh/. `.://`` `..-//oosyyo/` +sdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.. `.syyss:- :+yso`` `-shhhhhd:- `.:--` `.+/-``.-//+///////-` `./osssooosssssssssssssssssoooooooooooooooooooooss+/`` :+yss-. .-:----.` `-------.` ``-------.` ``-------`` `.------.` `.------.` ..------.` .-hhhhhdy:` `+osyy-. `` ```.:/+:. `.hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyddo: ///-. ./sy/: -/ddhhhhs-` `-:-.` .-+::```-:++////++:-```-:ssssooooooooooooooooooooooooooooooooooooosso+`` -:yyy+: `.-------` `.------. ``-------. `.------.. `.------.` ..------.` ..---:-` `.ohhhhdd+: -/yys/:` :/o/-`` `` :/ddyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhds.` .-:osyo-` +odhhhhh/- ``--:.. `://:.` ..::////++/:.` .-+osssoooooooooooooooooooooooooooooosssso/. `./oyyo/` ```` ``-------` `.----:-.` ..----:-.` ..----:..` `.-----:.` `.------.` `--`` ./hhdyhdso `-oys+.` .-yyyyyo+:.` `ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydho. `.::ossoosss:. .ohdhhhhh-. ``-::.` :/+/:.` ``..---:::.` .-/+oooooooooooooooooooooooooooossso+-. `.+oyss:- ``--:-. `.------.. `.------.` ..------.` ..------`` `.------.`` ``-------.` ` ..yhdhhdhs-` `-osy:- `/oso://syy+/ .+ydyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhd/- ../+osyso/-.:+yo+`` `/odhhhhhs:` `..:--`` `.:/o+/:-..`` ````` ```.-:+osoooooooooooooooooooosssss+/-.```-+oyso:- ``::----.` `..-----.. `.------.` `.------.` ``-------`` `.-------`` ``.------- `-oydhhhds+` :+yso` .-:. ``:/yss`` ./hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdys .-/ooyss+/..` `-oyh/- ``osdhhhhh+: ..:--`` ``-:+ssso+/////////++ooooooooooooooooooooosssssoo+:-`` .-+oyys/:.` ..------.` .-------`` `.-:----.` `-------.` ``-------.` ``-------` `.-::-. -/hhhhhdys`` -/yss.. `:syy-. +sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd-. `.:/ssyss+/.`` `./o.. `-shdyhhhh:- `--:-` `.-ooyyysssssssssssooooooooooossssssssoo+/:```` .-/syyso:-` `..` ``-------`` `.-:-----`` `.-:----- `--:--:-. ``--:---.. `.------.. ...` .-hhhhydhy:` -osyo+/.` :+yso`` `.hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy+` .+yhso/-. `./-. /oddhhhdy/.` --:-. ```` `.:/++oossssssssssssssssoo++//::.. ```.-:+oyys+/.. ``--::-.` ``-----:-.` ``-------`` ``------.` `.----:-.` ..----:-. .-----:.. .:ydhhyhds/` `:/ssyss/:.`` .-yys:. +sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhydy/. `.:/.` `--osyso`` +sdhhhhds+`` `.--..` `...`` `...-------------...`````....-:/++ooo++--.` ` ``.----:--` ``.------.` `.------.. `.------.. `.------.` ..------.` .------` ``/odhhhhdso`` .-/osyys+/--:+syo:` `:ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh/. -:+syso+syo/` ./yhhhhhds+.` ``---.` ``---..``` ``..--:///////:::-.`` ``..-.` `.------.` `.------.` `..-----..` `.------.. `.------.` `-------`` `..-`` `./odhhhhdy+-` ``.````` `.:/osssssss/: `:hhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdyo `-/ssyso-..:+hs+. -:hhdhhdhy+: ``.-`` `.-:----.` ````.....``` ``--:---.. `.------.` ..------.` ..------`` `.-:-----` `--:----.` ``-------.` -/yhdhhhhd/-` `-+ooo+++///:-. `.-:+/:--`` +sdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdd:. -:ossoo/.` ``osyo/ -/hddyhhhh/: `..`` `.::----.` ``......`` ``------. `.-:----.` `.-:----.` `-------`` `.-------`` `.-:-----` `.-:----- `--::::.` -:hhhhyddh+: `+oyssosssyyyyss/-` `` .-dhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhho` `./+yysss+/` `-oyy:- `/sddhhhdhs:. ``` `.------.. ..::::--.` ..:-----.` .----:--`` .-:--:--` -----:-.` ``-----:-.` ``-------`` `.------.` `...` `-ohdhhhhds+.` -:hyo-```..--:/+oyss/:` `+ydhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydho- :/syyo+:/+ys/.` `-oyh/- +ohhhhhdhh/:` `.------.. `.------.` `-------`` `.-------`` `.-------` `.------.` ``-------. `.------.. `.------.. `-:yhdhhhhhs+`` .-yss-` :/sssss+:.`` .+ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhd+: /+y+/.` `.osy+:`` ..+osss.. `:oydhhhhhyo:- .------.`` ``-------.` ``-------.` ``-------`` `.------.` `.------.` ..-----..` `.------.. `.----.. .:oyhhhhhdys/. +oho/ `-+so+:+oyys:. -/dhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh.` `.-`` .:sss///+oyso:- `.oshhhhhdhy/:` `.-------`` `.-------`` ``.------. `.------.. `.------.. `.------.` ..------.` .------.`` `..` `-/yhdhhhhdyo-. -/yss.` -/syy-. `.++o-` ``yydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhds+ -/ssssssss/:.` `.:syddhhhhhy+: ``--:::--` `.------.` `.:-----.` `..:----.. `.-:----.` `.------.` `-------`` `.---::-- :/shhhhhddhs/.` ``.` .+sy+:`..ssy/- ``` /oddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdy+. ..sss/-..-.. ````.-:.. ``+shhhhhhhhs+:.` ``..--:-. `.------.. `.------.` ..------`` .-------`` .------.` `-------.` ``-..`` ``-+ohhhhhhhhso.` `+oy+: `./oysoooso-` ./ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhd+: `/oys/. ``-://+ooosss+:.` `.-+shhhhhhhhso-.` ``..-..` `.------.` `.------.` ``-------`` `.-------`` `.-------` ``.----:-. `.-oshhhhhhhhso:.` :/ssy/-` `.++ssss+.`` -/hhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh.` `+so/` `./osssssoo+//ssy/: ``/+yhhhhhhhyyo:-`` ``` `.----:-.`` ``-------.` ``-------.` ``-------`` `.----:-.` `.-..`` ``-:+sydhhhhhhyo/`` `-+sys/.` .:+osso/:` ``yydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhds+` .--. :/sss+/:--.`` /oho+ `.:+yhhhhhhdhho+:.. `.----:--`` ``.------.` ``-------. `.------.. `.------`` `.:+oyhdhhhhhhh+/-` ` .-ssy:. `./+yss`` `/oddyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdho. `-/syyso`` `osy/- -:+sydhhhhhhhys/:.` ````.....` `.--:::--` `..--:::-.` `..-----.` `````` `.:/syhhhhhhhdys+:- `-+/: osy+:`` ``--- ./ydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdo+ .:+syoo+sy+:` .-yso-` ``./+shhhhhhhhhyso::.`` ``......`` ..-..-..` `````` ``-:ooyhhhhhhhhhyo+..` -/yyy/:` -:ssssso+/-. /odhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhd:- /+yso..`/+yso-. :/hs+. ``.:/syhhhhhhhhhyyo+:-``` ```--+osyhhhhhhhhhys/:.`` `.:osys+-``.:osso//+sssss+/:.` .-hhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhs-` `-/-. ``+oyso...+syo-` ``--:::..` `.:+ohhhhhhhhhdhyso+:-.`` ```--+osyhdhhhhhhhhhso:.` ``--:.` .-ssyo+/+sss-. ``-:/ooyso-` `.ohhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhh/. ./osoossy/- `/+sssyyso/-. -:/oshhhhhhhhddhhyso/:-..`` ``..-:/osyhhddhhhhhhhhso+:- .-/ossyy/- .-+syyss:. `.:-` .:yhdyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdhy.` `/oyys/: `-+syo+:::osyso-. ``-:/osyhhhhhhhhhhhyyyoo+/:--..`` ```.--://+oyyyhhhhhhhhhhhhso+:-.` .-osyss/::.. `:/sss/:` ``sydhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdy+.` -:osso+-` ``+oyso.` .-/osso/. `.-:/ooyyhhhhhhhhhhhhhyyysso+//:::---..``` ```..---::://+ossyyyhhhhhhhhhhhhhyyoo/:-.` `-osso+-. ``:/ssy+:` `+sdhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhs:. +oyso.` `:+yyo:. `-:sss:. ```.-:/+ssyyhhhhhhhhhhhhhhhhhhyyyyssooo+++++++++++++++++++oosssyyyhhhhhhhhhhhhhhhhhhhyss+/:-.``` .+sh/:` `-+syso-` `-ohdhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhdys`` `./.` .+sys+.` `ssy/- ```.-:++osyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhhhhyyso+:-.```` -oyy:- `.sso-` `oydhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhdy+. :+yss.` `-/yss:. ``/:.`` ``..-:/++ossyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyysso++/:--.`` ` ./sys+.` ``` ``` `/sddyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhs:. +oho/ ./oyso-` :+yys+/..` ```..--:::::///////+++++++///////::::---..`` `.-/:-.. `:+yys:. `-o+/` `-ohdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyy.` /+ho+.` :+yys:. `:oyoo+ssso/:- .-+ossssoo:-.` ``+oyso.` ``+oho+ `.sydhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyo.` .:ssyo+-` -:yyy/: .:syy--`--ooyss/:` /+yso::/osyso+/`` `-+syo/.` `-/oyys:. `+sdhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyydhh/. ``/+yys+/::/osyo:. osyo+ `.:+syo-` /oh+: `.-+oyyy+: `/oyso///+syyo/.` .:yhdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdd:- -/oyyyyyys:- :+yso. :/hs+. ``..` `````` /oh+: `./oys+. `+osyyyys/: .-hhdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdy/.` `.-::::-- `-oysso:-`` `.+syo:` :+ys+/:..` `..:/+osoo/-. /oh+: ``:/yyy/- `-----.` .:shhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhds+`` .:sss++oss+/-...:osy/: `.+ssssssso+/:.` `.-:+osssso+osyso`` /oh+/ `.:/oosoosss.` ``/ohhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhds+.` `+oyo+`..:+sssoossyso`` .+sy+:.--+ossss+-` `.+ssssoo:-.``.:oyy:- :+yso..-+oyss+/.-+syo/` `/odhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdhy/- -:hys:. ``:/yssoo+-. .:yyy.` ``.:+yso-` ..:-.` `/sys/.` `:oyo/` `-ossoosss/:.`` `+syo-` .:yhdhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhh/:` ``/:-` :+ho+`` +oyo/ `ssy/: :+yyso+//:.` -:o/.` .-yyo-` `/oyo-` `.+syso-` `.`` `-:hhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdyo:. /oh+: .-yys:. `.sss:. `.:/sssssy:. `:/-. `..` :+hs/. osy+/ ``.:oss+.` .-yss:. .-+yhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdys-. osh/- :+ys/. :/ys+. -/yso..-.` `-oys+-` `.-`` ````` ````````.....`` `+os:. -/hs+. -/yss...:/oosss/- /oyso`` .-sydhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhy+-` -/o:. `-oys+.` `.+sy+.` +oh+/ `:oysso- `:sy/- `:/++//-. ``//+++ooooosss++.` osho/ :+ys:` .+syooossoo/:-` `-o/:` `./shdhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdys-. ``` .+sy/: ./sh+: `.sss:. .+osssy/- ./yh:- :+yssssyoo`` ``sssooo++++/+osyo/` -/yys/-` `.oys+` `-oyss+:-.`` `` `.oshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhy+.` .:ssyo+/:-`` -/sss.` -/hs+. `-sss:/sss`` .osy.` .-yys/:.:+sy+: `osy/-```````.+sy+.` `-+syso:. .+sh/- :+ys/. `./shhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhys-.` `.-:/oosss++///osyo/ `/oyo:` .:yoo`./sh/- `-sss`` ./oys/. `.+syo-` osy/- /oyo-` ..+oyso/+sss`` ..ssy/- `..oshhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhs+-. ..://ossssso+-` `.oys+` -/ho+ `+ss+.` -/yo+ .+syo/` -/yso-` +oh+: `/oys:` `./ossss+/ +oho+ `-/sydhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhdyy:-` ..-::.` `..-/sh/: /oh+/ -:hs+. :+h+/ .:yss.` `osy+: /+yo+.....--/oss+-` .-ssy/- .-/-. `.-sydhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhyo:- `/osssyy/:.` +oy/- ``osy:.:+h+: .:yso...```````+oy+: :/ysooossssssss:- +oy+/ .:+yhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhhh+/.` `-:/++ooss+. ``sss:` -/yoooos:. .:ssoooooooooooosy/: -/yso++//::/osy-. -/yso` `.:+yhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhyo/`` ```..:::` .-hyo- .+sssso-` -/yso////++++++osy/- .:yss```` .:syo/` `:sso`` ``/+yhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdyo:.` `.o+:` `.+yys+. -/yso``````````osy/- `:sss.` `/oys/. `... `.:osdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyhhdys:-.` -:so:` -/hso `ssy/- `-oyy-. ..ooo-. `-:syhddyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhdhhs+:.` .`` .-/:: `/++:. `://.` ````` `.:/syhdhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyhhhhhyo/-- ```` .-/oshhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyy+/-` `./+yyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhhso-. ..oshhdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhddhy+/.`` ``./+shhddhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhdddyyo/:..` ``.-:osydddhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhys+/:.` `.::+sshhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyhhhhhhhss+/:.` ``-:+oshhhhhhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhhhyso/:`` ``:/+syhhhhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhys+/--``` ```.-/+syydddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhysoo/:-..``` ```...:/oosyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyoo/::--.``` ```..-::/+osyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyhhhhhhhhhhyysso++::--..`` ``..--::/+oosyyhhhhhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyss++//:--...``` ```...--::/++osyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyyyyssoo++++/////:::::::::::::::::::://///+++++osssyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

View File

@@ -0,0 +1,51 @@
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyysoo++//////++oosyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhyo+/-.`` ``.-:+oyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs+:.` `.:+shhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhyo:.` `` `.` `.` `.:oyhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhyo:` . :/-. -/./`./.-. /` . `:oyhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhy+. `.` /- `o-. +:-+-/-`/:-/ `+ ::-. ./yhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhs/` ` .+-- `+.-./--`.` ```---`::./.:/-.` ` `/shhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhy/` . .+.-+--. ``` ```.....`` ````/:-` `/-:- `/yhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhy+. `- :::-:--.` .-:/++++//////++++/:-.` `` `+. -+`.` `+yhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhy- -//` ./` ` .:+++:-.`` ` ` ` ``.-:+++:. -:::-/::- -shhhhhhhhhhhhhh
hhhhhhhhhhhhho` ` `:: ` `:++:.````.`...........`.`````.:++:. -.`- ` `ohhhhhhhhhhhhh
hhhhhhhhhhhh+` ` .+o:.```.`..`..`................` .:o+. +hhhhhhhhhhhh
hhhhhhhhhhh+ .+o-``.`..`..`..`..`..`..`...........```-o+. /hhhhhhhhhhh
hhhhhhhhhh+ `/s- `..`..`..`..`...--:::::--.``........```-s/` +hhhhhhhhhh
hhhhhhhhhs `o+```..`..`..`.-/++oooooooooooo+/-..`..`.`````+s. ohhhhhhhhh
hhhhhhhhy. .y: .`..`..`..`:ooooooooooooooooo+/:-::-...-`..` :y. `yhhhhhhhh
hhhhhhhh/ . .y: .`.`.:---. /oooooooooooooooo/::/:-:++:..`..... -y. . /hhhhhhhh
hhhhhhhy` `.:s:`` s/ .```+ooooo/-ooooooooooooooo+::/+./ooooo+...`..`. /y` `.:s:`` yhhhhhhh
hhhhhhh+ `/ooooo/` /s ..` :ooooo+`ooooooooooooooo//:+/.+oooooooo.`..`..` s/ `/ooooo/` +hhhhhhh
hhhhhhh. oooo/ h-`.`` :ooooo.:-ooooooooooooo:--/+`ooooooooooo`.`..`.`-h` oooo/ .hhhhhhh
hhhhhhh `. `- -h ``.. `+oos.///-/oooooooooo-----./oooooooooos.`..`..` y: `. `- yhhhhhh
hhhhhhy +s `..`` :oo:-///:-:+oooooo-/-/o-.sooooooooooo ..`..`. o+ yhhhhhh
hhhhhhy ++ ..`.. `:o/-/////:-:/oo-/:/o+ oooooooooooo-`.`..`.. ++ shhhhhh
hhhhhhy +o .`..`.. `-:.-.-:///:.-/::oo.-ooooooosooo+`.`..`..` o+ yhhhhhh
hhhhhhh -y `..`..`..:+ooo+../-:/--//:oo/.:::///::-...`` ` ..`. y: yhhhhhh
hhhhhhh. `h-`.`..`-+ooo+/--:/-/:`://-ooo-`.`.-:::/++ooooo+:-``.`.h` .hhhhhhh
hhhhhhh+ ` /s `..`.---.-:://///::/:::ooo:-+oooooooooooooooooo:`. s+ /hhhhhhh
hhhhhhhy .:/:/` `y/ .`.`-/-/-////////:/-/ooo/:`://++oooooooooooo/-`. :y` `/`::` yhhhhhhh
hhhhhhhh/ `/`.`: .y- ..`.:/-/-////////.ooooo:-.`..`....:::///:-..`. -y. .::`/` :hhhhhhhh
hhhhhhhhy` `--/:` .y: `..-:/-//://///:/oooo:/.`..`..`..`..`..`..`. :y- /.:`-` `yhhhhhhhh
hhhhhhhhhs `::.-- .s+````.:/::++/::/+ooo+::.`..`..`..`..`..`..```/s. ..:/-: ohhhhhhhhh
hhhhhhhhhh+ ``.-/: `/s-````-:::/ooooo++/:-.`..`..`..`..`..`..` -s+` /-`:/` +hhhhhhhhhh
hhhhhhhhhhh/ ..``::. .oo-```.-:::::::--...`..`..`..`..`..`.``-oo. ..-:--: /hhhhhhhhhhh
hhhhhhhhhhhh+ -:/.+` .+o:` `.``..`.......`..`..`..`.````:o+- `+.::-` /hhhhhhhhhhhh
hhhhhhhhhhhhho` `:.---: ./++:.`````.`...........`.``` .:+o/. ` :-.:/ ` `ohhhhhhhhhhhhh
hhhhhhhhhhhhhhs- -::-:`.. .:++/:..`` `` ` ` ``..:/++:. ``-::::.` -shhhhhhhhhhhhhh
hhhhhhhhhhhhhhhy+` :.-:.-: ` `.-//+++////////+++//-.` ` ::` .:- `+yhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhy:` /-.:./-:. ` ``......`` `` /-:-:--: `:yhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhs:` ```/-/:.:--- .` ` `/././::/``` `:shhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhs/. : -:`-:`+`:: -` --` :-:`:.-: /:-` - ./shhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhyo:` `.--`/- +.:+ /-.+ +-/- -+ - `-oyhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhyo:`` `` . .- /../ :`.- . ``:oyhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhys+:`` ``-+syhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhso+:.`` ``.:/oshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhysso++////////++oosyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

View File

@@ -0,0 +1,416 @@
<?php
namespace League\CLImate\Argument;
use League\CLImate\Exceptions\UnexpectedValueException;
use function is_array;
class Argument
{
/**
* An argument's name.
*
* Use this name when internally referring to the argument.
*
* @var string
*/
protected $name;
/**
* An argument's short representation.
*
* @var string
*/
protected $prefix;
/**
* An argument's long representation.
*
* @var string
*/
protected $longPrefix;
/**
* An argument's description.
*
* @var string
*/
protected $description;
/**
* Whether or not an argument is required.
*
* @var bool
*/
protected $required = false;
/**
* Whether or not an argument only needs to be defined to have a value.
*
* These arguments have the value true when they are defined on the command
* line.
*
* @var bool
*/
protected $noValue = false;
/**
* Which data type to cast an argument's value to.
*
* Valid data types are "string", "int", "float", and "bool".
*
* @var string
*/
protected $castTo = 'string';
/**
* An argument's default value.
*
* @var string
*/
protected $defaultValue = [];
/**
* An argument's value, after type casting.
*
* @var string[]|int[]|float[]|bool[]
*/
protected $values = [];
/**
* Build a new command argument.
*
* @param string $name
*/
public function __construct($name)
{
$this->setName($name);
}
/**
* Build a new command argument from an array.
*
* @param string $name
* @param array $params
*
* @return Argument
*/
public static function createFromArray($name, array $params)
{
$argument = new Argument($name);
$params = self::getSettableArgumentParams($params);
foreach ($params as $key => $value) {
$method = 'set' . ucwords($key);
$argument->{$method}($value);
}
return $argument;
}
/**
* Get argument params based on settable properties
*
* @param array $params
*
* @return array
*/
protected static function getSettableArgumentParams(array $params)
{
$allowed = [
'prefix',
'longPrefix',
'description',
'required',
'noValue',
'castTo',
'defaultValue',
];
return array_intersect_key($params, array_flip($allowed));
}
/**
* Retrieve an argument's name.
*
* Use this name when internally referring to the argument.
*
* @return string
*/
public function name()
{
return $this->name;
}
/**
* Set an argument's name.
*
* Use this name when internally referring to the argument.
*
* @param string $name
*/
protected function setName($name)
{
$this->name = trim($name);
}
/**
* Retrieve an argument's short form.
*
* @return string
*/
public function prefix()
{
return $this->prefix;
}
/**
* Set an argument's short form.
*
* @param string $prefix
*/
protected function setPrefix($prefix)
{
$this->prefix = trim($prefix);
}
/**
* Retrieve an argument's long form.
*
* @return string
*/
public function longPrefix()
{
return $this->longPrefix;
}
/**
* Set an argument's short form.
*
* @param string $longPrefix
*/
protected function setLongPrefix($longPrefix)
{
$this->longPrefix = trim($longPrefix);
}
/**
* Determine if an argument has a prefix.
*
* @return bool
*/
public function hasPrefix()
{
return $this->prefix() || $this->longPrefix();
}
/**
* Retrieve an argument's description.
*
* @return string
*/
public function description()
{
return $this->description;
}
/**
* Set an argument's description.
*
* @param string $description
*/
protected function setDescription($description)
{
$this->description = trim($description);
}
/**
* Determine whether or not an argument is required.
*
* @return bool
*/
public function isRequired()
{
return $this->required;
}
/**
* Set whether an argument is required or not.
*
* @param bool $required
*/
protected function setRequired($required)
{
$this->required = (bool) $required;
}
/**
* Determine whether or not an argument only needs to be defined to have a
* value.
*
* @return bool
*/
public function noValue()
{
return $this->noValue;
}
/**
* Set whether or not an argument only needs to be defined to have a value.
*
* @param bool $noValue
*/
protected function setNoValue($noValue)
{
$this->setCastTo('bool');
$this->noValue = (bool) $noValue;
}
/**
* Retrieve the data type to cast an argument's value to.
*
* @return string
*/
public function castTo()
{
return $this->castTo;
}
/**
* Set the data type to cast an argument's value to.
*
* Valid data types are "string", "int", "float", and "bool".
*
* @param string $castTo
*
* @return void
* @throws UnexpectedValueException if $castTo is not a valid data type.
*/
protected function setCastTo($castTo)
{
if (!in_array($castTo, ['string', 'int', 'float', 'bool'])) {
throw new UnexpectedValueException(
"An argument may only be cast to the data type "
. "'string', 'int', 'float', or 'bool'."
);
}
$this->castTo = $this->noValue() ? 'bool' : $castTo;
}
/**
* Retrieve an argument's default values.
*
* @return string
*/
public function defaultValue()
{
return $this->defaultValue;
}
/**
* Set an argument's default value.
*
* @param string $defaultValue
*/
public function setDefaultValue($defaultValue)
{
if (!is_array($defaultValue)) {
$defaultValue = [$defaultValue];
}
$this->defaultValue = $defaultValue;
}
/**
* Retrieve an argument's value.
*
* Argument values are type cast based on the value of $castTo.
*
* @return string|int|float|bool
*/
public function value()
{
if ($this->values) {
return end($this->values);
}
$cast_method = 'castTo' . ucwords($this->castTo);
return $this->{$cast_method}(current($this->defaultValue()));
}
/**
* Retrieve an argument's values.
*
* Argument values are type cast based on the value of $castTo.
*
* @return string[]|int[]|float[]|bool[]
*/
public function values()
{
if ($this->values) {
return $this->values;
}
$cast_method = 'castTo' . ucwords($this->castTo);
return array_map([$this, $cast_method], $this->defaultValue());
}
/**
* @deprecated use values() instead.
*/
public function valueArray()
{
return $this->values();
}
/**
* Set an argument's value based on its command line entry.
*
* Argument values are type cast based on the value of $castTo.
*
* @param string|bool $value
*/
public function setValue($value)
{
$cast_method = 'castTo' . ucwords($this->castTo);
$this->values[] = $this->{$cast_method}($value);
}
/**
* @param string $value
*
* @return string
*/
protected function castToString($value)
{
return (string) $value;
}
/**
* @param string $value
*
* @return int
*/
protected function castToInt($value)
{
return (int) $value;
}
/**
* @param string $value
*
* @return float
*/
protected function castToFloat($value)
{
return (float) $value;
}
/**
* @param string $value
*
* @return bool
*/
protected function castToBool($value)
{
return (bool) $value;
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace League\CLImate\Argument;
class Filter
{
protected $arguments = [];
/**
* Set the available arguments
*
* @param array $arguments
*/
public function setArguments(array $arguments)
{
$this->arguments = $arguments;
}
/**
* Retrieve optional arguments
*
* @return Argument[]
*/
public function optional()
{
return $this->filterArguments(['isOptional']);
}
/**
* Retrieve required arguments
*
* @return Argument[]
*/
public function required()
{
return $this->filterArguments(['isRequired']);
}
/**
* Retrieve arguments with prefix
*
* @return Argument[]
*/
public function withPrefix()
{
return $this->filterArguments(['hasPrefix']);
}
/**
* Retrieve arguments without prefix
*
* @return Argument[]
*/
public function withoutPrefix()
{
return $this->filterArguments(['noPrefix']);
}
/**
* Find all required arguments that don't have values after parsing.
*
* These arguments weren't defined on the command line.
*
* @return Argument[]
*/
public function missing()
{
return $this->filterArguments(['isRequired', 'noValue']);
}
/**
* Filter defined arguments as to whether they are required or not
*
* @param string[] $filters
*
* @return Argument[]
*/
protected function filterArguments($filters = [])
{
$arguments = $this->arguments;
foreach ($filters as $filter) {
$arguments = array_filter($arguments, [$this, $filter]);
}
if (in_array('hasPrefix', $filters)) {
usort($arguments, [$this, 'compareByPrefix']);
}
return array_values($arguments);
}
/**
* Determine whether an argument as a prefix
*
* @param Argument $argument
*
* @return bool
*/
protected function noPrefix($argument)
{
return !$argument->hasPrefix();
}
/**
* Determine whether an argument as a prefix
*
* @param Argument $argument
*
* @return bool
*/
protected function hasPrefix($argument)
{
return $argument->hasPrefix();
}
/**
* Determine whether an argument is required
*
* @param Argument $argument
*
* @return bool
*/
protected function isRequired($argument)
{
return $argument->isRequired();
}
/**
* Determine whether an argument is optional
*
* @param Argument $argument
*
* @return bool
*/
protected function isOptional($argument)
{
return !$argument->isRequired();
}
/**
* Determine whether an argument is optional
*
* @param Argument $argument
*
* @return bool
*/
protected function noValue($argument)
{
return $argument->values() == [];
}
/**
* Compare two arguments by their short and long prefixes.
*
* @see usort()
*
* @param Argument $a
* @param Argument $b
*
* @return int
*/
public function compareByPrefix(Argument $a, Argument $b)
{
if ($this->prefixCompareString($a) < $this->prefixCompareString($b)) {
return -1;
}
return 1;
}
/**
* Prep the prefix string for comparison
*
* @param Argument $argument
*
* @return string
*/
protected function prefixCompareString(Argument $argument)
{
return mb_strtolower($argument->longPrefix() ?: $argument->prefix() ?: '');
}
}

View File

@@ -0,0 +1,261 @@
<?php
namespace League\CLImate\Argument;
use League\CLImate\CLImate;
use League\CLImate\Exceptions\InvalidArgumentException;
class Manager
{
/**
* An array of arguments passed to the program.
*
* @var Argument[] $arguments
*/
protected $arguments = [];
/**
* A program's description.
*
* @var string $description
*/
protected $description;
/**
* Filter class to find various types of arguments
*
* @var \League\CLImate\Argument\Filter $filter
*/
protected $filter;
/**
* Summary builder class
*
* @var \League\CLImate\Argument\Summary $summary
*/
protected $summary;
/**
* Argument parser class
*
* @var \League\CLImate\Argument\Parser $parser
*/
protected $parser;
public function __construct()
{
$this->filter = new Filter();
$this->summary = new Summary();
$this->parser = new Parser();
}
/**
* Add an argument.
*
* @param Argument|string|array $argument
* @param $options
*
* @return void
* @throws InvalidArgumentException if $argument isn't an array or Argument object.
*/
public function add($argument, array $options = [])
{
if (is_array($argument)) {
$this->addMany($argument);
return;
}
if (is_string($argument)) {
$argument = Argument::createFromArray($argument, $options);
}
if (!$argument instanceof Argument) {
throw new InvalidArgumentException('Please provide an argument name or object.');
}
$this->arguments[$argument->name()] = $argument;
}
/**
* Add multiple arguments to a CLImate script.
*
* @param array $arguments
*/
protected function addMany(array $arguments = [])
{
foreach ($arguments as $name => $options) {
$this->add($name, $options);
}
}
/**
* Determine if an argument exists.
*
* @param string $name
* @return bool
*/
public function exists($name)
{
return isset($this->arguments[$name]);
}
/**
* Retrieve an argument's value.
*
* @param string $name
* @return string|int|float|bool|null
*/
public function get($name)
{
return isset($this->arguments[$name]) ? $this->arguments[$name]->value() : null;
}
/**
* Retrieve an argument's all values as an array.
*
* @param string $name
* @return string[]|int[]|float[]|bool[]
*/
public function getArray($name)
{
return isset($this->arguments[$name]) ? $this->arguments[$name]->values() : [];
}
/**
* Retrieve all arguments.
*
* @return Argument[]
*/
public function all()
{
return $this->arguments;
}
/**
* Determine if an argument has been defined on the command line.
*
* This can be useful for making sure an argument is present on the command
* line before parse()'ing them into argument objects.
*
* @param string $name
* @param array $argv
*
* @return bool
*/
public function defined($name, array $argv = null)
{
// The argument isn't defined if it's not defined by the calling code.
if (!$this->exists($name)) {
return false;
}
$argument = $this->arguments[$name];
$command_arguments = $this->parser->arguments($argv);
foreach ($command_arguments as $command_argument) {
if ($this->isArgument($argument, $command_argument)) {
return true;
}
}
return false;
}
/**
* Check if the defined argument matches the command argument.
*
* @param Argument $argument
* @param string $command_argument
*
* @return bool
*/
protected function isArgument($argument, $command_argument)
{
$possibilities = [
$argument->prefix() => "-{$argument->prefix()}",
$argument->longPrefix() => "--{$argument->longPrefix()}",
];
foreach ($possibilities as $key => $search) {
if ($key && strpos($command_argument, $search) === 0) {
return true;
}
}
return false;
}
/**
* Retrieve all arguments as key/value pairs.
*
* @return array
*/
public function toArray()
{
$return = [];
foreach ($this->all() as $name => $argument) {
$return[$name] = $argument->value();
}
return $return;
}
/**
* Set a program's description.
*
* @param string $description
*/
public function description($description)
{
$this->description = trim($description);
}
/**
* Output a script's usage statement.
*
* @param CLImate $climate
* @param array $argv
*/
public function usage(CLImate $climate, array $argv = null)
{
$this->summary
->setClimate($climate)
->setDescription($this->description)
->setCommand($this->parser->command($argv))
->setFilter($this->filter, $this->all())
->output();
}
/**
* Parse command line arguments into CLImate arguments.
*
* @param array $argv
*/
public function parse(array $argv = null)
{
$this->parser->setFilter($this->filter, $this->all());
$this->parser->parse($argv);
}
/**
* Get the trailing arguments
*
* @return string|null
*/
public function trailing()
{
return $this->parser->trailing();
}
/**
* Get the trailing arguments as an array
*
* @return array|null
*/
public function trailingArray()
{
return $this->parser->trailingArray();
}
}

View File

@@ -0,0 +1,309 @@
<?php
namespace League\CLImate\Argument;
use League\CLImate\Exceptions\InvalidArgumentException;
class Parser
{
/**
* Filter class to find various types of arguments
*
* @var \League\CLImate\Argument\Filter $filter
*/
protected $filter;
/**
* Summary builder class
*
* @var \League\CLImate\Argument\Summary $summary
*/
protected $summary;
protected $trailing;
protected $trailingArray;
public function __construct()
{
$this->summary = new Summary();
}
/**
* @param Filter $filter
* @param Argument[] $arguments
*
* @return \League\CLImate\Argument\Parser
*/
public function setFilter($filter, $arguments)
{
$this->filter = $filter;
$this->filter->setArguments($arguments);
return $this;
}
/**
* Parse command line arguments into CLImate arguments.
*
* @param array $argv
*
* @return void
* @throws InvalidArgumentException if required arguments aren't defined.
*/
public function parse(array $argv = null)
{
$cliArguments = $this->arguments($argv);
if (in_array('--', $cliArguments)) {
$cliArguments = $this->removeTrailingArguments($cliArguments);
}
$unParsedArguments = $this->prefixedArguments($cliArguments);
$this->nonPrefixedArguments($unParsedArguments);
// After parsing find out which arguments were required but not
// defined on the command line.
$missingArguments = $this->filter->missing();
if (count($missingArguments) > 0) {
throw new InvalidArgumentException(
'The following arguments are required: '
. $this->summary->short($missingArguments) . '.'
);
}
}
/**
* Get the command name.
*
* @param array $argv
*
* @return string
*/
public function command(array $argv = null)
{
return $this->getCommandAndArguments($argv)['command'];
}
/**
* Get the passed arguments.
*
* @param array $argv
*
* @return array
*/
public function arguments(array $argv = null)
{
return $this->getCommandAndArguments($argv)['arguments'];
}
/**
* Get the trailing arguments
*
* @return string|null
*/
public function trailing()
{
return $this->trailing;
}
/**
* Get the trailing arguments as an array
*
* @return array|null
*/
public function trailingArray()
{
return $this->trailingArray;
}
/**
* Remove the trailing arguments from the parser and set them aside
*
* @param array $arguments
*
* @return array
*/
protected function removeTrailingArguments(array $arguments)
{
$trailing = array_splice($arguments, array_search('--', $arguments));
array_shift($trailing);
$this->trailingArray = $trailing;
$this->trailing = implode(' ', $trailing);
return $arguments;
}
/**
* Parse command line options into prefixed CLImate arguments.
*
* Prefixed arguments are arguments with a prefix (-) or a long prefix (--)
* on the command line.
*
* Return the arguments passed on the command line that didn't match up with
* prefixed arguments so they can be assigned to non-prefixed arguments.
*
* @param array $argv
* @return array
*/
protected function prefixedArguments(array $argv = [])
{
foreach ($argv as $key => $passed_argument) {
$argv = $this->trySettingArgumentValue($argv, $key, $passed_argument);
}
// Send un-parsed arguments back upstream.
return array_values($argv);
}
/**
* Parse unset command line options into non-prefixed CLImate arguments.
*
* Non-prefixed arguments are parsed after the prefixed arguments on the
* command line, in the order that they're defined in the script.
*
* @param array $unParsedArguments
*/
protected function nonPrefixedArguments(array $unParsedArguments = [])
{
foreach ($this->filter->withoutPrefix() as $key => $argument) {
if (isset($unParsedArguments[$key])) {
$argument->setValue($unParsedArguments[$key]);
}
}
}
/**
* Parse the name and value of the argument passed in
*
* @param string $cliArgument
* @return string[] [$name, $value]
*/
protected function getNameAndValue($cliArgument)
{
// Look for arguments defined in the "key=value" format.
if (strpos($cliArgument, '=') !== false) {
return explode('=', $cliArgument, 2);
}
// If the argument isn't in "key=value" format then assume it's in
// "key value" format and define the value after we've found the
// matching CLImate argument.
return [$cliArgument, null];
}
/**
* Attempt to set the an argument's value and remove applicable
* arguments from array
*
* @param array $argv
* @param int $key
* @param string $passed_argument
*
* @return array The new $argv
*/
protected function trySettingArgumentValue($argv, $key, $passed_argument)
{
list($name, $value) = $this->getNameAndValue($passed_argument);
// Look for the argument in our defined $arguments
// and assign their value.
if (!($argument = $this->findPrefixedArgument($name))) {
return $argv;
}
// We found an argument key, so take it out of the array.
unset($argv[$key]);
return $this->setArgumentValue($argv, $argument, $key, $value);
}
/**
* Set the argument's value
*
* @param array $argv
* @param Argument $argument
* @param int $key
* @param string|null $value
*
* @return array The new $argv
*/
protected function setArgumentValue($argv, $argument, $key, $value)
{
// Arguments are given the value true if they only need to
// be defined on the command line to be set.
if ($argument->noValue()) {
$argument->setValue(true);
return $argv;
}
if (is_null($value)) {
if (count($argv) === 0) {
return $argv;
}
// If the value wasn't previously defined in "key=value"
// format then define it from the next command argument.
$nextArgvValue = $argv[$key + 1];
if ($this->isValidArgumentValue($nextArgvValue)) {
$argument->setValue($nextArgvValue);
unset($argv[$key + 1]);
return $argv;
}
}
$argument->setValue($value);
return $argv;
}
/**
* Check if the value is considered a valid input value.
*
* @param $argumentValue
* @return bool
*/
protected function isValidArgumentValue($argumentValue)
{
return empty($this->findPrefixedArgument($argumentValue));
}
/**
* Search for argument in defined prefix arguments
*
* @param string $name
*
* @return Argument|false
*/
protected function findPrefixedArgument($name)
{
foreach ($this->filter->withPrefix() as $argument) {
if (in_array($name, ["-{$argument->prefix()}", "--{$argument->longPrefix()}"])) {
return $argument;
}
}
return false;
}
/**
* Pull a command name and arguments from $argv.
*
* @param array $argv
* @return array
*/
protected function getCommandAndArguments(array $argv = null)
{
// If no $argv is provided then use the global PHP defined $argv.
if (is_null($argv)) {
global $argv;
}
$arguments = $argv;
$command = array_shift($arguments);
return compact('arguments', 'command');
}
}

View File

@@ -0,0 +1,215 @@
<?php
namespace League\CLImate\Argument;
use League\CLImate\CLImate;
class Summary
{
/**
* @var \League\CLImate\CLImate $climate
*/
protected $climate;
/**
* @var string $description
*/
protected $description;
/**
* @var string $command
*/
protected $command;
/**
* @var Filter $filter
*/
protected $filter;
/**
* @param \League\CLImate\CLImate $climate
*
* @return \League\CLImate\Argument\Summary
*/
public function setClimate(CLImate $climate)
{
$this->climate = $climate;
return $this;
}
/**
* @param string $description
*
* @return \League\CLImate\Argument\Summary
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @param string $command
*
* @return \League\CLImate\Argument\Summary
*/
public function setCommand($command)
{
$this->command = $command;
return $this;
}
/**
* @param Filter $filter
* @param Argument[] $arguments
*
* @return \League\CLImate\Argument\Summary
*/
public function setFilter($filter, $arguments)
{
$this->filter = $filter;
$this->filter->setArguments($arguments);
return $this;
}
/**
* Output the full summary for the program
*/
public function output()
{
// Print the description if it's defined.
if ($this->description) {
$this->climate->out($this->description)->br();
}
// Print the usage statement with the arguments without a prefix at the end.
$this->climate->out("Usage: {$this->command} "
. $this->short($this->getOrderedArguments()));
// Print argument details.
foreach (['required', 'optional'] as $type) {
$this->outputArguments($this->filter->{$type}(), $type);
}
}
/**
* Build a short summary of a list of arguments.
*
* @param Argument[] $arguments
*
* @return string
*/
public function short($arguments)
{
return implode(' ', array_map([$this, 'argumentBracketed'], $arguments));
}
/**
* Build an argument's summary for use in a usage statement.
*
* For example, "-u username, --user username", "--force", or
* "-c count (default: 7)".
*
* @param Argument $argument
*
* @return string
*/
public function argument(Argument $argument)
{
$summary = $this->prefixedArguments($argument);
$printedName = mb_strstr($summary, ' ' . $argument->name());
// Print the argument name if it's not printed yet.
if (!$printedName && !$argument->noValue()) {
$summary .= $argument->name();
}
if ($defaults = $argument->defaultValue()) {
if (count($defaults) == 1) {
$summary .= " (default: {$defaults[0]})";
} else {
$summary .= ' (defaults: ' . implode(', ', $defaults) . ')';
}
}
return $summary;
}
/**
* Build argument summary surrounded by brackets
*
* @param Argument $argument
*
* @return string
*/
protected function argumentBracketed(Argument $argument)
{
return '[' . $this->argument($argument) . ']';
}
/**
* Get the arguments ordered by whether or not they have a prefix
*
* @return Argument[]
*/
protected function getOrderedArguments()
{
return array_merge($this->filter->withPrefix(), $this->filter->withoutPrefix());
}
/**
* Print out the argument list
*
* @param array $arguments
* @param string $type
*/
protected function outputArguments($arguments, $type)
{
if (count($arguments) == 0) {
return;
}
$this->climate->br()->out(mb_convert_case($type, MB_CASE_TITLE) . ' Arguments:');
foreach ($arguments as $argument) {
$this->climate->tab()->out($this->argument($argument));
if ($argument->description()) {
$this->climate->tab(2)->out($argument->description());
}
}
}
/**
* Builds the summary for any prefixed arguments
*
* @param Argument $argument
*
* @return string
*/
protected function prefixedArguments(Argument $argument)
{
$prefixes = [$argument->prefix(), $argument->longPrefix()];
$summary = [];
foreach ($prefixes as $key => $prefix) {
if (!$prefix) {
continue;
}
$sub = str_repeat('-', $key + 1) . $prefix;
if (!$argument->noValue()) {
$sub .= " {$argument->name()}";
}
$summary[] = $sub;
}
return implode(', ', $summary);
}
}

446
vendor/league/climate/src/CLImate.php vendored Normal file
View File

@@ -0,0 +1,446 @@
<?php
namespace League\CLImate;
use League\CLImate\Argument\Manager as ArgumentManager;
use League\CLImate\Decorator\Style;
use League\CLImate\Settings\Manager as SettingsManager;
use League\CLImate\TerminalObject\Dynamic\Spinner;
use League\CLImate\TerminalObject\Router\Router;
use League\CLImate\Util\Helper;
use League\CLImate\Util\Output;
use League\CLImate\Util\UtilFactory;
/**
* @method CLImate black(string $str = null)
* @method CLImate red(string $str = null)
* @method CLImate green(string $str = null)
* @method CLImate yellow(string $str = null)
* @method CLImate blue(string $str = null)
* @method CLImate magenta(string $str = null)
* @method CLImate cyan(string $str = null)
* @method CLImate lightGray(string $str = null)
* @method CLImate darkGray(string $str = null)
* @method CLImate lightRed(string $str = null)
* @method CLImate lightGreen(string $str = null)
* @method CLImate lightYellow(string $str = null)
* @method CLImate lightBlue(string $str = null)
* @method CLImate lightMagenta(string $str = null)
* @method CLImate lightCyan(string $str = null)
* @method CLImate white(string $str = null)
*
* @method CLImate backgroundBlack(string $str = null)
* @method CLImate backgroundRed(string $str = null)
* @method CLImate backgroundGreen(string $str = null)
* @method CLImate backgroundYellow(string $str = null)
* @method CLImate backgroundBlue(string $str = null)
* @method CLImate backgroundMagenta(string $str = null)
* @method CLImate backgroundCyan(string $str = null)
* @method CLImate backgroundLightGray(string $str = null)
* @method CLImate backgroundDarkGray(string $str = null)
* @method CLImate backgroundLightRed(string $str = null)
* @method CLImate backgroundLightGreen(string $str = null)
* @method CLImate backgroundLightYellow(string $str = null)
* @method CLImate backgroundLightBlue(string $str = null)
* @method CLImate backgroundLightMagenta(string $str = null)
* @method CLImate backgroundLightCyan(string $str = null)
* @method CLImate backgroundWhite(string $str = null)
*
* @method CLImate bold(string $str = null)
* @method CLImate dim(string $str = null)
* @method CLImate underline(string $str = null)
* @method CLImate blink(string $str = null)
* @method CLImate invert(string $str = null)
* @method CLImate hidden(string $str = null)
*
* @method CLImate info(string $str = null)
* @method CLImate comment(string $str = null)
* @method CLImate whisper(string $str = null)
* @method CLImate shout(string $str = null)
* @method CLImate error(string $str = null)
*
* @method mixed out(string $str)
* @method mixed inline(string $str)
* @method mixed table(array $data)
* @method mixed json(mixed $var)
* @method mixed br($count = 1)
* @method mixed tab($count = 1)
* @method mixed draw(string $art)
* @method mixed border(string $char = null, integer $length = null)
* @method mixed dump(mixed $var)
* @method mixed flank(string $output, string $char = null, integer $length = null)
* @method mixed progress(integer $total = null)
* @method Spinner spinner(string $label = null, string ...$characters = null)
* @method mixed padding(integer $length = 0, string $char = '.')
* @method mixed input(string $prompt, Util\Reader\ReaderInterface $reader = null)
* @method mixed confirm(string $prompt, Util\Reader\ReaderInterface $reader = null)
* @method mixed password(string $prompt, Util\Reader\ReaderInterface $reader = null)
* @method mixed checkboxes(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
* @method mixed radio(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
* @method mixed animation(string $art, TerminalObject\Helper\Sleeper $sleeper = null)
* @method mixed columns(array $data, $column_count = null)
* @method mixed clear()
* @method CLImate clearLine()
*
* @method CLImate addArt(string $dir)
*/
class CLImate
{
/**
* An instance of the Style class
*
* @var \League\CLImate\Decorator\Style $style
*/
public $style;
/**
* An instance of the Terminal Object Router class
*
* @var \League\CLImate\TerminalObject\Router\Router $router
*/
protected $router;
/**
* An instance of the Settings Manager class
*
* @var \League\CLImate\Settings\Manager $settings
*/
protected $settings;
/**
* An instance of the Argument Manager class
*
* @var \League\CLImate\Argument\Manager $arguments
*/
public $arguments;
/**
* An instance of the Output class
*
* @var \League\CLImate\Util\Output $output
*/
public $output;
/**
* An instance of the Util Factory
*
* @var \League\CLImate\Util\UtilFactory $util
*/
protected $util;
public function __construct()
{
$this->setStyle(new Style());
$this->setRouter(new Router());
$this->setSettingsManager(new SettingsManager());
$this->setOutput(new Output());
$this->setUtil(new UtilFactory());
$this->setArgumentManager(new ArgumentManager());
}
/**
* Set the style property
*
* @param \League\CLImate\Decorator\Style $style
*/
public function setStyle(Style $style)
{
$this->style = $style;
}
/**
* Set the router property
*
* @param \League\CLImate\TerminalObject\Router\Router $router
*/
public function setRouter(Router $router)
{
$this->router = $router;
}
/**
* Set the settings property
*
* @param \League\CLImate\Settings\Manager $manager
*/
public function setSettingsManager(SettingsManager $manager)
{
$this->settings = $manager;
}
/**
* Set the arguments property
*
* @param \League\CLImate\Argument\Manager $manager
*/
public function setArgumentManager(ArgumentManager $manager)
{
$this->arguments = $manager;
}
/**
* Set the output property
*
* @param \League\CLImate\Util\Output $output
*/
public function setOutput(Output $output)
{
$this->output = $output;
}
/**
* Set the util property
*
* @param \League\CLImate\Util\UtilFactory $util
*/
public function setUtil(UtilFactory $util)
{
$this->util = $util;
}
/**
* Extend CLImate with custom methods
*
* @param string|object|array $class
* @param string $key Optional custom key instead of class name
*
* @return \League\CLImate\CLImate
*/
public function extend($class, $key = null)
{
$this->router->addExtension($key, $class);
return $this;
}
/**
* Force ansi support on
*
* @return \League\CLImate\CLImate
*/
public function forceAnsiOn()
{
$this->util->system->forceAnsi();
return $this;
}
/**
* Force ansi support off
*
* @return \League\CLImate\CLImate
*/
public function forceAnsiOff()
{
$this->util->system->forceAnsi(false);
return $this;
}
/**
* Write line to writer once
*
* @param string|array $writer
*
* @return \League\CLImate\CLImate
*/
public function to($writer)
{
$this->output->once($writer);
return $this;
}
/**
* Output the program's usage statement
*
* @param array $argv
* @return void
*/
public function usage(array $argv = null)
{
$this->arguments->usage($this, $argv);
}
/**
* Set the program's description
*
* @param string $description
*
* @return \League\CLImate\CLImate
*/
public function description($description)
{
$this->arguments->description($description);
return $this;
}
/**
* Check if we have valid output
*
* @param mixed $output
*
* @return boolean
*/
protected function hasOutput($output)
{
if (!empty($output)) {
return true;
}
// Check for type first to avoid errors with objects/arrays/etc
return ((is_string($output) || is_numeric($output)) && strlen($output) > 0);
}
/**
* Search for the method within the string
* and route it if we find one.
*
* @param string $method
* @param string $name
*
* @return string The new string without the executed method.
*/
protected function parseStyleMethod($method, $name)
{
// If the name starts with this method string...
if (substr($name, 0, strlen($method)) == $method) {
// ...remove the method name from the beginning of the string...
$name = substr($name, strlen($method));
// ...and trim off any of those underscores hanging around
$name = ltrim($name, '_');
$this->style->set($method);
}
return $name;
}
/**
* Search for any style methods within the name and apply them
*
* @param string $name
* @param array $method_search
*
* @return string Anything left over after applying styles
*/
protected function applyStyleMethods($name, $method_search = null)
{
// Get all of the possible style attributes
$method_search = $method_search ?: array_keys($this->style->all());
$new_name = $this->searchForStyleMethods($name, $method_search);
// While we still have a name left and we keep finding methods,
// loop through the possibilities
if (strlen($new_name) > 0 && $new_name != $name) {
return $this->applyStyleMethods($new_name, $method_search);
}
return $new_name;
}
/**
* Search for style methods in the current name
*
* @param string $name
* @param array $search
* @return string
*/
protected function searchForStyleMethods($name, $search)
{
// Loop through the possible methods
foreach ($search as $method) {
// See if we found a valid method
$name = $this->parseStyleMethod($method, $name);
}
return $name;
}
/**
* Build up the terminal object and return it
*
* @param string $name
* @param array $arguments
*
* @return object|null
*/
protected function buildTerminalObject($name, $arguments)
{
// Retrieve the parser for the current set of styles
$parser = $this->style->parser($this->util->system);
// Reset the styles
$this->style->reset();
// Execute the terminal object
$this->router->settings($this->settings);
$this->router->parser($parser);
$this->router->output($this->output);
$this->router->util($this->util);
return $this->router->execute($name, $arguments);
}
/**
* Route anything leftover after styles were applied
*
* @param string $name
* @param array $arguments
*
* @return object|null
*/
protected function routeRemainingMethod($name, array $arguments)
{
// If we still have something left, let's figure out what it is
if ($this->router->exists($name)) {
$obj = $this->buildTerminalObject($name, $arguments);
// If something was returned, return it
if (is_object($obj)) {
return $obj;
}
} elseif ($this->settings->exists($name)) {
$this->settings->add($name, reset($arguments));
// Handle passthroughs to the arguments manager.
} else {
// If we can't find it at this point, let's fail gracefully
$this->out(reset($arguments));
}
}
/**
* Magic method for anything called that doesn't exist
*
* @param string $requested_method
* @param array $arguments
*
* @return \League\CLImate\CLImate|\League\CLImate\TerminalObject\Dynamic\DynamicTerminalObject
*
* List of many of the possible method being called here
* documented at the top of this class.
*/
public function __call($requested_method, $arguments)
{
// Apply any style methods that we can find first
$name = $this->applyStyleMethods(Helper::snakeCase($requested_method));
// The first argument is the string|array|object we want to echo out
$output = reset($arguments);
if (strlen($name)) {
// If we have something left, let's try and route it to the appropriate place
if ($result = $this->routeRemainingMethod($name, $arguments)) {
return $result;
}
} elseif ($this->hasOutput($output)) {
// If we have fulfilled all of the requested methods and we have output, output it
$this->out($output);
}
return $this;
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace League\CLImate\Decorator\Component;
class BackgroundColor extends Color
{
/**
* The difference to add to a foreground color code
* to get a background color code
*
* @const integer ADD
*/
const ADD = 10;
/**
* Get the code for the requested color
*
* @param mixed $val
*
* @return mixed
*/
public function get($val)
{
$color = parent::get($this->strip($val));
if ($color) {
$color += self::ADD;
}
return $color;
}
/**
* Set the current background color
*
* @param mixed $val
*
* @return boolean
*/
public function set($val)
{
return parent::set($this->strip($val));
}
/**
* Get all of the available background colors
*
* @return array
*/
public function all()
{
$colors = [];
foreach ($this->colors as $color => $code) {
$colors['background_' . $color] = $code + self::ADD;
}
return $colors;
}
/**
* Strip the color of any prefixes
*
* @param string $val
*
* @return string
*/
protected function strip($val)
{
return str_replace('background_', '', $val);
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace League\CLImate\Decorator\Component;
abstract class BaseDecorator implements DecoratorInterface
{
/**
* An array of defaults for the decorator
*
* @var array $defaults;
*/
protected $defaults = [];
/**
* An array of currently set codes for the decorator
*
* @var array $current;
*/
protected $current = [];
public function __construct()
{
$this->defaults();
}
/**
* Load up the defaults for this decorator
*/
public function defaults()
{
foreach ($this->defaults as $name => $code) {
$this->add($name, $code);
}
}
/**
* Reset the currently set decorator
*/
public function reset()
{
$this->current = [];
}
/**
* Retrieve the currently set codes for the decorator
*
* @return array
*/
public function current()
{
return $this->current;
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace League\CLImate\Decorator\Component;
class Color extends BaseDecorator
{
/**
* The available colors
*
* @var array
*/
protected $colors = [];
/**
* An array of default colors
*
* @var array $defaults
*/
protected $defaults = [
'default' => 39,
'black' => 30,
'red' => 31,
'green' => 32,
'yellow' => 33,
'blue' => 34,
'magenta' => 35,
'cyan' => 36,
'light_gray' => 37,
'dark_gray' => 90,
'light_red' => 91,
'light_green' => 92,
'light_yellow' => 93,
'light_blue' => 94,
'light_magenta' => 95,
'light_cyan' => 96,
'white' => 97,
];
/**
* Add a color into the mix
*
* @param string $key
* @param integer $value
*/
public function add($key, $value)
{
$this->colors[$key] = (int) $value;
}
/**
* Retrieve all of available colors
*
* @return array
*/
public function all()
{
return $this->colors;
}
/**
* Get the code for the color
*
* @param string $val
*
* @return string
*/
public function get($val)
{
// If we already have the code, just return that
if (is_numeric($val)) {
return $val;
}
if (array_key_exists($val, $this->colors)) {
return $this->colors[$val];
}
return null;
}
/**
* Set the current color
*
* @param string $val
*
* @return boolean
*/
public function set($val)
{
$code = $this->get($val);
if ($code) {
$this->current = [$code];
return true;
}
return false;
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace League\CLImate\Decorator\Component;
class Command extends BaseDecorator
{
/**
* Commands that correspond to a color in the $colors property
*
* @var array
*/
public $commands = [];
/**
* The default commands available
*
* @var array $defaults
*/
protected $defaults = [
'info' => 'green',
'comment' => 'yellow',
'whisper' => 'light_gray',
'shout' => 'red',
'error' => 'light_red',
];
/**
* Add a command into the mix
*
* @param string $key
* @param mixed $value
*/
public function add($key, $value)
{
$this->commands[$key] = $value;
}
/**
* Retrieve all of the available commands
*
* @return array
*/
public function all()
{
return $this->commands;
}
/**
* Get the style that corresponds to the command
*
* @param string $val
*
* @return string
*/
public function get($val)
{
if (array_key_exists($val, $this->commands)) {
return $this->commands[$val];
}
return null;
}
/**
* Set the currently used command
*
* @param string $val
*
* @return string|false
*/
public function set($val)
{
// Return the code because it is a string corresponding
// to a property in another class
return ($code = $this->get($val)) ? $code : false;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace League\CLImate\Decorator\Component;
interface DecoratorInterface
{
public function add($key, $value);
/**
* @return void
*/
public function defaults();
public function get($val);
public function set($val);
public function all();
public function current();
/**
* @return void
*/
public function reset();
}

View File

@@ -0,0 +1,89 @@
<?php
namespace League\CLImate\Decorator\Component;
class Format extends BaseDecorator
{
/**
* The available formatting options
*
* @var array
*/
protected $formats = [];
/**
* An array of default formats
*
* @var array $defaults
*/
protected $defaults = [
'bold' => 1,
'dim' => 2,
'underline' => 4,
'blink' => 5,
'invert' => 7,
'hidden' => 8,
];
/**
* Add a format into the mix
*
* @param string $key
* @param mixed $value
*/
public function add($key, $value)
{
$this->formats[$key] = (int) $value;
}
/**
* Retrieve all of the available formats
*
* @return array
*/
public function all()
{
return $this->formats;
}
/**
* Get the code for the format
*
* @param string $val
*
* @return string
*/
public function get($val)
{
// If we already have the code, just return that
if (is_numeric($val)) {
return $val;
}
if (array_key_exists($val, $this->formats)) {
return $this->formats[$val];
}
return null;
}
/**
* Set the current format
*
* @param string $val
*
* @return boolean
*/
public function set($val)
{
$code = $this->get($val);
if ($code) {
$this->current[] = $code;
return true;
}
return false;
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace League\CLImate\Decorator\Parser;
use League\CLImate\Util\Helper;
class Ansi extends Parser
{
/**
* Wrap the string in the current style
*
* @param string $str
*
* @return string
*/
public function apply($str)
{
return $this->start() . $this->parse($str) . $this->end();
}
/**
* Get the string that begins the style
*
* @param string $codes
* @return string
*/
protected function start($codes = null)
{
$codes = $codes ?: $this->currentCode();
$codes = $this->codeStr($codes);
return $this->wrapCodes($codes);
}
/**
* Get the string that ends the style
*
* @param string|array $codes
* @return string
*/
protected function end($codes = null)
{
if (empty($codes)) {
$codes = [0];
} else {
$codes = Helper::toArray($codes);
// Reset everything back to normal up front
array_unshift($codes, 0);
}
return $this->wrapCodes($this->codeStr($codes));
}
/**
* Wrap the code string in the full escaped sequence
*
* @param string $codes
*
* @return string
*/
protected function wrapCodes($codes)
{
return "\e[{$codes}m";
}
/**
* Parse the string for tags and replace them with their codes
*
* @param string $str
*
* @return string
*/
protected function parse($str)
{
$count = preg_match_all($this->tags->regex(), $str, $matches);
// If we didn't find anything, return the string right back
if (!$count || !is_array($matches)) {
return $str;
}
// All we want is the array of actual strings matched
$matches = reset($matches);
return $this->parseTags($str, $matches);
}
/**
* Parse the given string for the tags and replace them with the appropriate codes
*
* @param string $str
* @param array $tags
*
* @return string
*/
protected function parseTags($str, $tags)
{
// Let's keep a history of styles applied
$history = ($this->currentCode()) ? [$this->currentCode()] : [];
foreach ($tags as $tag) {
$str = $this->replaceTag($str, $tag, $history);
}
return $str;
}
/**
* Replace the tag in the str
*
* @param string $str
* @param string $tag
* @param array $history
*
* @return string
*/
protected function replaceTag($str, $tag, &$history)
{
// We will be replacing tags one at a time, can't pass this by reference
$replace_count = 1;
if (strpos($tag, '/')) {
// We are closing out the tag, pop off the last element and get the codes that are left
array_pop($history);
$replace = $this->end($history);
} else {
// We are starting a new tag, add it onto the history and replace with correct color code
$history[] = $this->tags->value($tag);
$replace = $this->start($this->tags->value($tag));
}
return str_replace($tag, $replace, $str, $replace_count);
}
/**
* Stringify the codes
*
* @param mixed $codes
*
* @return string
*/
protected function codeStr($codes)
{
// If we get something that is already a code string, just pass it back
if (!is_array($codes) && strpos($codes, ';')) {
return $codes;
}
$codes = Helper::toArray($codes);
// Sort for the sake of consistency and testability
sort($codes);
return implode(';', $codes);
}
/**
* Retrieve the current style code
*
* @return string
*/
protected function currentCode()
{
return $this->codeStr($this->current);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace League\CLImate\Decorator\Parser;
class NonAnsi extends Parser
{
/**
* Strip the string of any tags
*
* @param string $str
*
* @return string
*/
public function apply($str)
{
return preg_replace($this->tags->regex(), '', $str);
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace League\CLImate\Decorator\Parser;
use League\CLImate\Decorator\Tags;
abstract class Parser
{
/**
* An array of the currently applied codes
*
* @var array $current;
*/
protected $current = [];
/**
* An array of the tags that should be searched for
* and their corresponding replacements
*
* @var \League\CLImate\Decorator\Tags $tags
*/
public $tags;
public function __construct(array $current, Tags $tags)
{
$this->current = $current;
$this->tags = $tags;
}
/**
* Wrap the string in the current style
*
* @param string $str
*
* @return string
*/
abstract public function apply($str);
}

View File

@@ -0,0 +1,26 @@
<?php
namespace League\CLImate\Decorator\Parser;
use League\CLImate\Util\System\System;
use League\CLImate\Decorator\Tags;
class ParserFactory
{
/**
* Get an instance of the appropriate Parser class
*
* @param System $system
* @param array $current
* @param Tags $tags
* @return Parser
*/
public static function getInstance(System $system, array $current, Tags $tags)
{
if ($system->hasAnsiSupport()) {
return new Ansi($current, $tags);
}
return new NonAnsi($current, $tags);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace League\CLImate\Decorator\Parser;
trait ParserImporter
{
/**
* An instance of the Parser class
*
* @var \League\CLImate\Decorator\Parser\Parser $parser
*/
protected $parser;
/**
* Import the parser and set the property
*
* @param \League\CLImate\Decorator\Parser\Parser $parser
*/
public function parser(Parser $parser)
{
$this->parser = $parser;
}
}

View File

@@ -0,0 +1,295 @@
<?php
namespace League\CLImate\Decorator;
use League\CLImate\Decorator\Parser\ParserFactory;
use League\CLImate\Util\Helper;
use League\CLImate\Util\System\System;
/**
* @method void addColor(string $color, integer $code)
* @method void addFormat(string $format, integer $code)
* @method void addCommand(string $command, mixed $style)
*/
class Style
{
/**
* An array of Decorator objects
*
* @var Component\DecoratorInterface[] $style
*/
protected $style = [];
/**
* An array of the available Decorators
* and their corresponding class names
*
* @var array $available
*/
protected $available = [
'format' => 'Format',
'color' => 'Color',
'background' => 'BackgroundColor',
'command' => 'Command',
];
protected $parser;
/**
* An array of the current styles applied
*
* @var array $current
*/
protected $current = [];
public function __construct()
{
foreach ($this->available as $key => $class) {
$class = 'League\CLImate\Decorator\Component\\' . $class;
$this->style[$key] = new $class();
}
}
/**
* Get all of the styles available
*
* @return array
*/
public function all()
{
$all = [];
foreach ($this->style as $style) {
$all = array_merge($all, $this->convertToCodes($style->all()));
}
return $all;
}
/**
* Attempt to get the corresponding code for the style
*
* @param mixed $key
*
* @return mixed
*/
public function get($key)
{
foreach ($this->style as $style) {
if ($code = $style->get($key)) {
return $code;
}
}
return false;
}
/**
* Attempt to set some aspect of the styling,
* return true if attempt was successful
*
* @param string $key
*
* @return boolean
*/
public function set($key)
{
foreach ($this->style as $style) {
if ($code = $style->set($key)) {
return $this->validateCode($code);
}
}
return false;
}
/**
* Reset the current styles applied
*
*/
public function reset()
{
foreach ($this->style as $style) {
$style->reset();
}
}
/**
* Get a new instance of the Parser class based on the current settings
*
* @param \League\CLImate\Util\System\System $system
*
* @return \League\CLImate\Decorator\Parser\Parser
*/
public function parser(System $system)
{
return ParserFactory::getInstance($system, $this->current(), new Tags($this->all()));
}
/**
* Compile an array of the current codes
*
* @return array
*/
public function current()
{
$full_current = [];
foreach ($this->style as $style) {
$full_current = array_merge($full_current, Helper::toArray($style->current()));
}
$full_current = array_filter($full_current);
return array_values($full_current);
}
/**
* Make sure that the code is an integer, if not let's try and get it there
*
* @param mixed $code
*
* @return boolean
*/
protected function validateCode($code)
{
if (is_integer($code)) {
return true;
}
// Plug it back in and see what we get
if (is_string($code)) {
return $this->set($code);
}
if (is_array($code)) {
return $this->validateCodeArray($code);
}
return false;
}
/**
* Validate an array of codes
*
* @param array $codes
*
* @return boolean
*/
protected function validateCodeArray(array $codes)
{
// Loop through it and add each of the properties
$adds = [];
foreach ($codes as $code) {
$adds[] = $this->set($code);
}
// If any of them came back true, we're good to go
return in_array(true, $adds);
}
/**
* Convert the array of codes to integers
*
* @param array $codes
* @return array
*/
protected function convertToCodes(array $codes)
{
foreach ($codes as $key => $code) {
if (is_int($code)) {
continue;
}
$codes[$key] = $this->getCode($code);
}
return $codes;
}
/**
* Retrieve the integers from the mixed code input
*
* @param string|array $code
*
* @return integer|array
*/
protected function getCode($code)
{
if (is_array($code)) {
return $this->getCodeArray($code);
}
return $this->get($code);
}
/**
* Retrieve an array of integers from the array of codes
*
* @param array $codes
*
* @return array
*/
protected function getCodeArray(array $codes)
{
foreach ($codes as $key => $code) {
$codes[$key] = $this->get($code);
}
return $codes;
}
/**
* Parse the add method for the style they are trying to add
*
* @param string $method
*
* @return string
*/
protected function parseAddMethod($method)
{
return strtolower(substr($method, 3, strlen($method)));
}
/**
* Add a custom style
*
* @param string $style
* @param string $key
* @param string $value
*/
protected function add($style, $key, $value)
{
$this->style[$style]->add($key, $value);
// If we are adding a color, make sure it gets added
// as a background color too
if ($style == 'color') {
$this->style['background']->add($key, $value);
}
}
/**
* Magic Methods
*
* List of possible magic methods are at the top of this class
*
* @param string $requested_method
* @param array $arguments
*/
public function __call($requested_method, $arguments)
{
// The only methods we are concerned about are 'add' methods
if (substr($requested_method, 0, 3) != 'add') {
return false;
}
$style = $this->parseAddMethod($requested_method);
if (array_key_exists($style, $this->style)) {
list($key, $value) = $arguments;
$this->add($style, $key, $value);
}
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace League\CLImate\Decorator;
class Tags
{
/**
* Original keys passed in to build tags
*
* @var array $tags
*/
protected $keys = [];
/**
* Available tags and their values
*
* @var array $tags
*/
protected $tags = [];
public function __construct(array $keys)
{
$this->keys = $keys;
$this->build();
}
/**
* Get all available tags
*
* @return array
*/
public function all()
{
return $this->tags;
}
/**
* Get the value of the requested tag
*
* @param string $key
*
* @return string|null
*/
public function value($key)
{
return (array_key_exists($key, $this->tags)) ? $this->tags[$key] : null;
}
/**
* Get the regular expression that can be used to parse the string for tags
*
* @return string
*/
public function regex()
{
return '(<(?:(?:(?:\\\)*\/)*(?:' . implode('|', array_keys($this->keys)) . '))>)';
}
/**
* Build the search and replace for all of the various style tags
*/
protected function build()
{
foreach ($this->keys as $tag => $code) {
$this->tags["<{$tag}>"] = $code;
$this->tags["</{$tag}>"] = $code;
$this->tags["<\\/{$tag}>"] = $code;
}
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace League\CLImate\Exceptions;
interface Exception
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace League\CLImate\Exceptions;
class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace League\CLImate\Exceptions;
class RuntimeException extends \RuntimeException implements Exception
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace League\CLImate\Exceptions;
class UnexpectedValueException extends \UnexpectedValueException implements Exception
{
}

174
vendor/league/climate/src/Logger.php vendored Normal file
View File

@@ -0,0 +1,174 @@
<?php
namespace League\CLImate;
use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use function array_key_exists;
use function is_array;
use function str_replace;
use function strpos;
/**
* A PSR-3 compatible logger that uses CLImate for output.
*/
class Logger extends AbstractLogger
{
/**
* @var array $levels Conversion of the level strings to their numeric representations.
*/
private $levels = [
LogLevel::EMERGENCY => 1,
LogLevel::ALERT => 2,
LogLevel::CRITICAL => 3,
LogLevel::ERROR => 4,
LogLevel::WARNING => 5,
LogLevel::NOTICE => 6,
LogLevel::INFO => 7,
LogLevel::DEBUG => 8,
];
/**
* @var int $level Ignore logging attempts at a level less than this.
*/
private $level;
/**
* @var CLImate $climate The underlying climate instance we are using for output.
*/
private $climate;
/**
* Create a new Logger instance.
*
* @param string $level One of the LogLevel constants
* @param CLImate $climate An existing CLImate instance to use for output
*/
public function __construct($level = LogLevel::INFO, CLImate $climate = null)
{
$this->level = $this->convertLevel($level);
if ($climate === null) {
$climate = new CLImate;
}
$this->climate = $climate;
# Define some default styles to use for the output
$commands = [
"emergency" => ["white", "bold", "background_red"],
"alert" => ["white", "background_yellow"],
"critical" => ["red", "bold"],
"error" => ["red"],
"warning" => "yellow",
"notice" => "light_cyan",
"info" => "green",
"debug" => "dark_gray",
];
# If any of the required styles are not defined then define them now
foreach ($commands as $command => $style) {
if (!$this->climate->style->get($command)) {
$this->climate->style->addCommand($command, $style);
}
}
}
/**
* Get a numeric log level for the passed parameter.
*
* @param string $level One of the LogLevel constants
*
* @return int
*/
private function convertLevel($level)
{
# If this is one of the defined string log levels then return it's numeric value
if (!array_key_exists($level, $this->levels)) {
throw new InvalidArgumentException("Unknown log level: {$level}");
}
return $this->levels[$level];
}
/**
* Get a new instance logging at a different level
*
* @param string $level One of the LogLevel constants
*
* @return Logger
*/
public function withLogLevel($level)
{
$logger = clone $this;
$logger->level = $this->convertLevel($level);
return $logger;
}
/**
* Log messages to a CLImate instance.
*
* @param string $level One of the LogLevel constants
* @param string|object $message If an object is passed it must implement __toString()
* @param array $context Placeholders to be substituted in the message
*
* @return void
*/
public function log($level, $message, array $context = []): void
{
if ($this->convertLevel($level) > $this->level) {
return;
}
# Handle objects implementing __toString
$message = (string)$message;
# Handle any placeholders in the $context array
foreach ($context as $key => $val) {
$placeholder = "{" . $key . "}";
# If this context key is used as a placeholder, then replace it, and remove it from the $context array
if (strpos($message, $placeholder) !== false) {
$val = (string)$val;
$message = str_replace($placeholder, $val, $message);
unset($context[$key]);
}
}
# Send the message to the climate instance
$this->climate->{$level}($message);
# Append any context information not used as placeholders
$this->outputRecursiveContext($level, $context, 1);
}
/**
* Handle recursive arrays in the logging context.
*
* @param string $level One of the LogLevel constants
* @param array $context The array of context to output
* @param int $indent The current level of indentation to be used
*
* @return void
*/
private function outputRecursiveContext($level, array $context, $indent)
{
foreach ($context as $key => $val) {
$this->climate->tab($indent);
$this->climate->{$level}()->inline("{$key}: ");
if (is_array($val)) {
$this->climate->{$level}("[");
$this->outputRecursiveContext($level, $val, $indent + 1);
$this->climate->tab($indent)->{$level}("]");
} else {
$this->climate->{$level}((string)$val);
}
}
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace League\CLImate\Settings;
class Art implements SettingsInterface
{
/**
* An array of valid art directories
* @var array[] $dirs
*/
public $dirs = [];
/**
* Add directories of art
*/
public function add()
{
$this->dirs = array_merge($this->dirs, func_get_args());
$this->dirs = array_filter($this->dirs);
$this->dirs = array_values($this->dirs);
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace League\CLImate\Settings;
class Manager
{
/**
* An array of settings that have been... set
*
* @var array $settings
*/
protected $settings = [];
/**
* Check and see if the requested setting is a valid, registered setting
*
* @param string $name
*
* @return boolean
*/
public function exists($name)
{
return class_exists($this->getPath($name));
}
/**
* Add a setting
*
* @param string $name
* @param mixed $value
*/
public function add($name, $value)
{
$setting = $this->getPath($name);
$key = $this->getClassName($name);
// If the current key doesn't exist in the settings array, set it up
if (!array_key_exists($name, $this->settings)) {
$this->settings[$key] = new $setting();
}
$this->settings[$key]->add($value);
}
/**
* Get the value of the requested setting if it exists
*
* @param string $key
*
* @return mixed
*/
public function get($key)
{
if (array_key_exists($key, $this->settings)) {
return $this->settings[$key];
}
return false;
}
/**
* Get the short name for the requested settings class
*
* @param string $name
*
* @return string
*/
protected function getPath($name)
{
return 'League\CLImate\Settings\\' . $this->getClassName($name);
}
/**
* Get the short class name for the setting
*
* @param string $name
*
* @return string
*/
protected function getClassName($name)
{
return ucwords(str_replace('add_', '', $name));
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace League\CLImate\Settings;
trait SettingsImporter
{
/**
* Dictates any settings that a class may need access to
*
* @return array
*/
public function settings()
{
return [];
}
/**
* Import the setting into the class
*
* @param \League\CLImate\Settings\SettingsInterface $setting
*/
public function importSetting($setting)
{
$short_name = basename(str_replace('\\', '/', get_class($setting)));
$method = 'importSetting' . $short_name;
if (method_exists($this, $method)) {
$this->$method($setting);
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace League\CLImate\Settings;
interface SettingsInterface
{
/**
* @return void
*/
public function add();
}

View File

@@ -0,0 +1,47 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
use League\CLImate\Decorator\Parser\ParserImporter;
use League\CLImate\Settings\SettingsImporter;
use League\CLImate\Util\UtilImporter;
use function strlen;
abstract class BasicTerminalObject implements BasicTerminalObjectInterface
{
use SettingsImporter, ParserImporter, UtilImporter;
/**
* Set the property if there is a valid value
*
* @param string $key
* @param string $value
*/
protected function set($key, $value)
{
if (strlen((string) $value)) {
$this->$key = $value;
}
}
/**
* Get the parser for the current object
*
* @return \League\CLImate\Decorator\Parser\Parser
*/
public function getParser()
{
return $this->parser;
}
/**
* Check if this object requires a new line to be added after the output
*
* @return boolean
*/
public function sameLine()
{
return false;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
use League\CLImate\Decorator\Parser\Parser;
use League\CLImate\Util\UtilFactory;
interface BasicTerminalObjectInterface
{
public function result();
public function settings();
/**
* @param $setting
* @return void
*/
public function importSetting($setting);
/**
* @return boolean
*/
public function sameLine();
/**
* @param \League\CLImate\Decorator\Parser\Parser $parser
*/
public function parser(Parser $parser);
/**
* @param UtilFactory $util
*/
public function util(UtilFactory $util);
}

View File

@@ -0,0 +1,67 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
class Border extends BasicTerminalObject
{
/**
* The character to repeat for the border
*
* @var string $char
*/
protected $char = '-';
/**
* The length of the border
*
* @var integer $length
*/
protected $length;
public function __construct($char = null, $length = null)
{
$this->char($char)->length($length);
}
/**
* Set the character to repeat for the border
*
* @param string $char
*
* @return Border
*/
public function char($char)
{
$this->set('char', $char);
return $this;
}
/**
* Set the length of the border
*
* @param integer $length
*
* @return Border
*/
public function length($length)
{
$this->set('length', $length);
return $this;
}
/**
* Return the border
*
* @return string
*/
public function result()
{
$length = $this->length ?: $this->util->width() ?: 100;
$str = str_repeat($this->char, $length);
$str = substr($str, 0, $length);
return $str;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
class Br extends Repeatable
{
/**
* Return an empty string
*
* @return string
*/
public function result()
{
return array_fill(0, $this->count, '');
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
class Clear extends BasicTerminalObject
{
/**
* Clear the terminal
*
* @return string
*/
public function result()
{
return "\e[H\e[2J";
}
public function sameLine()
{
return true;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
final class ClearLine extends Repeatable
{
/**
* Clear the lines.
*
* @return string
*/
public function result()
{
$string = "";
while ($this->count > 0) {
$string .= $this->util->cursor->startOfCurrentLine();
$string .= $this->util->cursor->deleteCurrentLine();
--$this->count;
$string .= $this->util->cursor->up();
}
$string .= $this->util->cursor->down();
return $string;
}
/**
* @inheritdoc
*/
public function sameLine()
{
return true;
}
}

View File

@@ -0,0 +1,207 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
use League\CLImate\TerminalObject\Helper\StringLength;
class Columns extends BasicTerminalObject
{
use StringLength;
/**
* Number of columns
*
* @var integer $column_count
*/
protected $column_count;
/**
* Data to columnize
*
* @var array $data
*/
protected $data;
public function __construct($data, $column_count = null)
{
$this->data = $data;
$this->column_count = $column_count;
}
/**
* Calculate the number of columns organize data
*
* @return array
*/
public function result()
{
$keys = array_keys($this->data);
$first_key = reset($keys);
return (!is_int($first_key)) ? $this->associativeColumns() : $this->columns();
}
/**
* Get columns for a regular array
*
* @return array
*/
protected function columns()
{
$this->data = $this->setData();
$column_widths = $this->getColumnWidths();
$output = [];
$count = count(reset($this->data));
for ($i = 0; $i < $count; $i++) {
$output[] = $this->getRow($i, $column_widths);
}
return $output;
}
/**
* Re-configure the data into it's final form
*/
protected function setData()
{
// If it's already an array of arrays, we're good to go
if (is_array(reset($this->data))) {
return $this->setArrayOfArraysData();
}
$column_width = $this->getColumnWidth($this->data);
$row_count = $this->getMaxRows($column_width);
return array_chunk($this->data, $row_count);
}
/**
* Re-configure an array of arrays into column arrays
*/
protected function setArrayOfArraysData()
{
$this->setColumnCountViaArray($this->data);
$new_data = array_fill(0, $this->column_count, []);
foreach ($this->data as $items) {
for ($i = 0; $i < $this->column_count; $i++) {
$new_data[$i][] = (array_key_exists($i, $items)) ? $items[$i] : null;
}
}
return $new_data;
}
/**
* Get columns for an associative array
*
* @return array
*/
protected function associativeColumns()
{
$column_width = $this->getColumnWidth(array_keys($this->data));
$output = [];
foreach ($this->data as $key => $value) {
$output[] = $this->pad($key, $column_width) . $value;
}
return $output;
}
/**
* Get the row of data
*
* @param integer $key
* @param array $column_widths
*
* @return string
*/
protected function getRow($key, $column_widths)
{
$row = [];
for ($j = 0; $j < $this->column_count; $j++) {
if (isset($this->data[$j]) && array_key_exists($key, $this->data[$j])) {
$row[] = $this->pad($this->data[$j][$key], $column_widths[$j]);
}
}
return trim(implode('', $row));
}
/**
* Get the standard column width
*
* @param array $data
*
* @return integer
*/
protected function getColumnWidth($data)
{
// Return the maximum width plus a buffer
return $this->maxStrLen($data) + 5;
}
/**
* Get an array of each column's width
*
* @return array
*/
protected function getColumnWidths()
{
$column_widths = [];
for ($i = 0; $i < $this->column_count; $i++) {
if (!isset($this->data[$i])) {
$column_widths[] = 0;
continue;
}
$column_widths[] = $this->getColumnWidth($this->data[$i]);
}
return $column_widths;
}
/**
* Set the count property
*
* @param integer $column_width
*/
protected function setColumnCount($column_width)
{
$this->column_count = (int) floor($this->util->width() / $column_width);
}
/**
* Set the count property via an array
*
* @param array $items
*/
protected function setColumnCountViaArray($items)
{
$counts = array_map(function ($arr) {
return count($arr);
}, $items);
$this->column_count = max($counts);
}
/**
* Get the number of rows per column
*
* @param integer $column_width
*
* @return integer
*/
protected function getMaxRows($column_width)
{
if (!$this->column_count) {
$this->setColumnCount($column_width);
}
return ceil(count($this->data) / $this->column_count);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
use League\CLImate\TerminalObject\Helper\Art;
class Draw extends BasicTerminalObject
{
use Art;
public function __construct($art)
{
// Add the default art directory
$this->addDir(__DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . 'ASCII');
$this->art = $art;
}
/**
* Return the art
*
* @return array
*/
public function result()
{
$file = $this->artFile($this->art);
return $this->parse($file);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace League\CLImate\TerminalObject\Basic;
class Dump extends BasicTerminalObject
{
/**
* The data to convert to JSON
*
* @var mixed $data
*/
protected $data;
public function __construct($data)
{
$this->data = $data;
}
/**
* Return the data as JSON
*
* @return string
*/
public function result()
{
ob_start();
var_dump($this->data);
$result = ob_get_contents();
ob_end_clean();
return $result;
}
}

Some files were not shown because too many files have changed in this diff Show More