From 36f73843b62050604d75ce478ffa64f14a05defd Mon Sep 17 00:00:00 2001
From: Victor Giers
Date: Mon, 21 Jun 2021 20:27:39 +0200
Subject: [PATCH] initial commit
---
README.md | 2 +
p5js/commands.js | 747 +
p5js/console.js | 278 +
p5js/console_animations/dance.txt | 2040 +
p5js/console_animations/fire.txt | 3600 ++
p5js/index.html | 158 +
p5js/p5.js | 32625 ++++++++++++++++
.../virtualCommandline/virtualCommandline.pde | 87 +
8 files changed, 39537 insertions(+)
create mode 100644 README.md
create mode 100644 p5js/commands.js
create mode 100644 p5js/console.js
create mode 100644 p5js/console_animations/dance.txt
create mode 100644 p5js/console_animations/fire.txt
create mode 100644 p5js/index.html
create mode 100644 p5js/p5.js
create mode 100644 processing3/virtualCommandline/virtualCommandline.pde
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..40b6fb7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+Processing 3 version is just basic text input in command line style
+p5.js version has some working commands that make the webbrowser do things, also play animations
diff --git a/p5js/commands.js b/p5js/commands.js
new file mode 100644
index 0000000..a01d63f
--- /dev/null
+++ b/p5js/commands.js
@@ -0,0 +1,747 @@
+var busy = true;
+var seqIntro_b = true;
+if (location.search.split('intro=')[1] == 'false'){
+ busy = false;
+ seqIntro_b = false;
+}
+var seqDance_b = false;
+var seqFire_b = false;
+var seqOutside_b = false;
+var seqMaria_b = false;
+var seqSkip_b = false;
+var seqGenome_b = false;
+var seqConstructivism_b = false;
+var pfc = 0; //save framecount here to get proper delta framecount in sequence
+var npfc = 0; //^ again for nesting shit
+var minc = 0; //movie increment - how often a console animation is played before it breaks. handled in sequences function
+
+function loadAnimationTexts(){
+ danceText = loadStrings('console_animations/dance.txt');
+ fireText = loadStrings('console_animations/fire.txt');
+}
+
+function seqConstructivism(){
+ var cframe = frameCount - pfc;
+ if (cframe == 1) commandLine.pushLineString("Like me on Facebook!");
+ if (cframe == 20){
+ commandLine.pushLineString("");
+ PopupCenter('https://www.facebook.com/constructivism2.0/', 'Constructivism 2.0', screen.width, screen.height);
+ busy = false;
+ seqConstructivism_b = false;
+ }
+
+}
+
+function seqGenome(){
+
+ var cframe = frameCount - pfc;
+ if (cframe == 1) commandLine.pushLineString("genome");
+ if (cframe == 10) commandLine.pushLineString("Description:");
+ if (cframe == 15){
+ commandLine.pushLineString("/ˈdʒiːnəʊm/");
+ commandLine.pushLineString("noun - Biology");
+ commandLine.pushLineString("noun: genome; plural noun: genomes");
+ }
+ if (cframe == 25) commandLine.pushLineString("- the haploid set of chromosomes in a gamete or microorganism, or in each cell of a multicellular organism.");
+ if (cframe == 25) commandLine.pushLineString("- the complete set of genes or genetic material present in a cell or organism.");
+ if (cframe == 40) commandLine.pushLineString("");
+ if (cframe == 40) commandLine.pushLineString("This will download the genetic code / genome of one Homo Sapiens (human)");
+ if (cframe == 40) commandLine.pushLineString("Mirrored from Source, packed as .zip-file: https://www.ncbi.nlm.nih.gov/guide/howto/dwn-genome/");
+ if (cframe == 40) commandLine.pushLineString("Neither including assembled chromosome sequences nor archived files.");
+ if (cframe == 40) commandLine.pushLineString("");
+ if (cframe == 65) commandLine.pushLineString("I recommend finding the right structure for this set of data to implement it");
+ if (cframe == 65) commandLine.pushLineString("into TensorFlow or similar machine-learning software in order to find out about your species,");
+ if (cframe == 65) commandLine.pushLineString("to push enlightenment further.");
+ if (cframe == 65) commandLine.pushLineString("Potentially you will first have to generate more data like this, so this would be only an example.");
+ if (cframe == 145) commandLine.pushLineString("");
+ if (cframe == 155) commandLine.pushLineString("Read the included README-file first.");
+ if (cframe == 155) commandLine.pushLineString("");
+ if (cframe == 155) commandLine.pushLineString("Starting download in 5...");
+ if (cframe == 185) commandLine.changeLineString("Starting download in 4...");
+ if (cframe == 215) commandLine.changeLineString("Starting download in 3...");
+ if (cframe == 245) commandLine.changeLineString("Starting download in 2...");
+ if (cframe == 275) commandLine.changeLineString("Starting download in 1...");
+ if (cframe == 280){
+ commandLine.changeLineString("Initializing download of the human genome...");
+ commandLine.pushLineString("");
+ PopupCenter("ftp://ftp.ncbi.nih.gov/genomes/H_sapiens/", "ftp://ftp.ncbi.nih.gov/genomes/", window.width, window.height);
+ window.open("https://drive.google.com/a/hbksaar.de/uc?export=download&confirm=LHNV&id=0B6B3OnIFgX8pTktKZ05XdGNFYzg");
+ busy = false;
+ seqGenome_b = false;
+ }
+}
+function seqIntro(){
+ var cframe = frameCount - pfc;
+
+ if (cframe == 1) commandLine.pushLineString("tests.openface_api_tests.test_pipeline ...");
+ if (cframe == 2) commandLine.changeLineString("tests.openface_api_tests.test_pipeline ... FAIL");
+ if (cframe == 3) commandLine.pushLineString("tests.openface_batch_represent_tests.test_batch_represent ...");
+ if (cframe == 4) commandLine.changeLineString("tests.openface_batch_represent_tests.test_batch_represent ... FAIL");
+ if (cframe == 5) commandLine.pushLineString("tests.openface_demo_tests.test_compare_demo ...");
+ if (cframe == 6) commandLine.changeLineString("tests.openface_demo_tests.test_compare_demo ... FAIL");
+ if (cframe == 7) commandLine.pushLineString("tests.openface_demo_tests.test_classification_demo_pretrained ...");
+ if (cframe == 8) commandLine.changeLineString("tests.openface_demo_tests.test_classification_demo_pretrained ... FAIL");
+ if (cframe == 9) commandLine.pushLineString("tests.openface_demo_tests.test_classification_demo_pretrained_multi ...");
+ if (cframe == 10) commandLine.changeLineString("tests.openface_demo_tests.test_classification_demo_pretrained_multi ... FAIL");
+ if (cframe == 11) commandLine.pushLineString("tests.openface_demo_tests.test_classification_demo_training ...");
+ if (cframe == 12) commandLine.changeLineString("tests.openface_demo_tests.test_classification_demo_training ... FAIL");
+ if (cframe == 13) commandLine.pushLineString("tests.openface_neural_net_training_tests.test_dnn_training ...");
+ if (cframe == 14) commandLine.changeLineString("tests.openface_neural_net_training_tests.test_dnn_training ... FAIL");
+ if (cframe == 15) commandLine.pushLineString("tests.openface_neural_net_training_tests.test_dnn_training ...");
+ if (cframe == 16) { commandLine.pushLineStrings([
+ " ",
+ "======================================================================",
+ "FAIL: tests.openface_api_tests.test_pipeline",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_api_tests.py\", line 55, in test_pipeline",
+ " assert bb.left() == 341",
+ "AssertionError"
+ ]);
+ }
+ if (cframe == 17) { commandLine.pushLineStrings([
+ " ",
+ "======================================================================",
+ "FAIL: tests.openface_batch_represent_tests.test_batch_represent",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_batch_represent_tests.py\", line 68, in test_batch_represent",
+ " assert p.returncode == 0",
+ "AssertionError:"
+ ]);
+ }
+ if (cframe == 18) { commandLine.pushLineStrings([
+ "-------------------- >> begin captured stdout << ---------------------",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ==="
+ ]);
+ }
+ if (cframe == 25) { commandLine.pushLineStrings([
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ " ",
+ " ",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ==="
+ ]);
+ }
+ if (cframe == 30) { commandLine.pushLineStrings([
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ " ",
+ " ",
+ " ",
+ "/iris/torch/install/bin/luajit: /iris/torch/install/share/lua/5.1/trepl/init.lua:389: module 'csvigo' not found:No LuaRocks module found for csvigo",
+ " no field package.preload['csvigo']",
+ " no file '/iris/.luarocks/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/.luarocks/share/lua/5.1/csvigo/init.lua'",
+ " no file '/iris/torch/install/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/torch/install/share/lua/5.1/csvigo/init.lua'",
+ " no file './csvigo.lua'",
+ " no file '/iris/torch/install/share/luajit-2.1.0-beta1/csvigo.lua'",
+ " no file '/iris/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/share/lua/5.1/csvigo/init.lua'",
+ " no file '/iris/.luarocks/lib/lua/5.1/csvigo.so'",
+ " no file '/iris/torch/install/lib/lua/5.1/csvigo.so'",
+ " no file '/iris/torch/install/lib/csvigo.so'",
+ " no file './csvigo.so'",
+ " no file '/iris/lua/5.1/csvigo.so'",
+ " no file '/iris/lua/5.1/loadall.so'",
+ "stack traceback:",
+ " [C]: in function 'error'",
+ " /iris/torch/install/share/lua/5.1/trepl/init.lua:389: in function 'require'",
+ " ./batch-represent/main.lua:9: in main chunk",
+ " [C]: in function 'dofile'",
+ " .../bin/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:150: in main chunk",
+ " [C]: at 0x004065d0",
+ " ",
+ " ",
+ "--------------------- >> end captured stdout << ----------------------"
+ ]);
+ }
+ if (cframe == 35) { commandLine.pushLineStrings([
+ " ",
+ "======================================================================",
+ "FAIL: tests.openface_demo_tests.test_compare_demo",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_demo_tests.py\", line 38, in test_compare_demo",
+ " assert \"0.763\" in out",
+ "AssertionError:",
+ "-------------------- >> begin captured stdout << ---------------------",
+ "Comparing /iris/openface/images/examples/lennon-1.jpg with /iris/openface/images/examples/lennon-2.jpg.",
+ " + Squared l2 distance between representations: 0.782",
+ " ",
+ " ",
+ " ",
+ "--------------------- >> end captured stdout << ----------------------"
+ ]);
+ }
+ if (cframe == 37) { commandLine.pushLineStrings([
+ " ",
+ "======================================================================",
+ "FAIL: tests.openface_demo_tests.test_classification_demo_pretrained",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_demo_tests.py\", line 51, in test_classification_demo_pretrained",
+ " assert \"Predict SteveCarell with 0.97 confidence.\" in out",
+ "AssertionError:",
+ "-------------------- >> begin captured stdout << ---------------------",
+ " ",
+ "=== /iris/openface/images/examples/carell.jpg ===",
+ "Predict SteveCarell with 0.99 confidence.",
+ " ",
+ "/iris/python2.7/dist-packages/sklearn/lda.py:4: DeprecationWarning: lda.LDA has been moved to discriminant_analysis.LinearDiscriminantAnalysis in 0.17 and will be removed in 0.19",
+ " \"in 0.17 and will be removed in 0.19\", DeprecationWarning)",
+ " ",
+ " ",
+ "--------------------- >> end captured stdout << ----------------------"
+ ]);
+ }
+ if (cframe == 39) { commandLine.pushLineStrings([
+ " ",
+ "======================================================================",
+ "FAIL: tests.openface_demo_tests.test_classification_demo_pretrained_multi",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_demo_tests.py\", line 64, in test_classification_demo_pretrained_multi",
+ " assert \"Predict EvaLongoria @ x=91 with 0.99 confidence.\" in out",
+ "AssertionError:",
+ "-------------------- >> begin captured stdout << ---------------------",
+ " ",
+ "=== /iris/openface/images/examples/longoria-cooper.jpg ===",
+ "List of faces in image from left to right",
+ "Predict EvaLongoria @ x=92 with 0.99 confidence.",
+ "Predict BradleyCooper @ x=192 with 0.99 confidence.",
+ " ",
+ "/iris/python2.7/dist-packages/sklearn/lda.py:4: DeprecationWarning: lda.LDA has been moved to discriminant_analysis.LinearDiscriminantAnalysis in 0.17 and will be removed in 0.19",
+ " \"in 0.17 and will be removed in 0.19\", DeprecationWarning)",
+ " ",
+ " ",
+ "--------------------- >> end captured stdout << ----------------------"
+ ]);
+ }
+ if (cframe == 44) { commandLine.pushLineStrings([
+ "======================================================================",
+ "FAIL: tests.openface_demo_tests.test_classification_demo_training",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_demo_tests.py\", line 98, in test_classification_demo_training",
+ " assert p.returncode == 0",
+ "AssertionError:",
+ "-------------------- >> begin captured stdout << ---------------------",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ==="
+ ]);
+ }
+ if (cframe == 45) { commandLine.pushLineStrings([
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ " ",
+ " ",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ==="
+ ]);
+ }
+ if (cframe == 46) { commandLine.pushLineStrings([
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ " ",
+ " "
+ ]);
+ }
+ if (cframe == 47) { commandLine.pushLineStrings([
+ "/iris/torch/install/bin/luajit: /iris/torch/install/share/lua/5.1/trepl/init.lua:389: module 'csvigo' not found:No LuaRocks module found for csvigo",
+ " no field package.preload['csvigo']",
+ " no file '/iris/.luarocks/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/.luarocks/share/lua/5.1/csvigo/init.lua'",
+ " no file '/iris/torch/install/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/torch/install/share/lua/5.1/csvigo/init.lua'",
+ " no file './csvigo.lua'",
+ " no file '/iris/torch/install/share/luajit-2.1.0-beta1/csvigo.lua'",
+ " no file '/iris/share/lua/5.1/csvigo.lua'",
+ " no file '/iris/share/lua/5.1/csvigo/init.lua'",
+ " no file '/iris/.luarocks/lib/lua/5.1/csvigo.so'",
+ " no file '/iris/torch/install/lib/lua/5.1/csvigo.so'",
+ " no file '/iris/torch/install/lib/csvigo.so'",
+ " no file './csvigo.so'",
+ " no file '/iris/lua/5.1/csvigo.so'",
+ " no file '/iris/lua/5.1/loadall.so'",
+ "stack traceback:",
+ " [C]: in function 'error'",
+ " /iris/torch/install/share/lua/5.1/trepl/init.lua:389: in function 'require'",
+ " ./batch-represent/main.lua:9: in main chunk",
+ " [C]: in function 'dofile'",
+ " .../bin/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:150: in main chunk",
+ " [C]: at 0x004065d0",
+ " ",
+ " ",
+ "--------------------- >> end captured stdout << ----------------------",
+ " "
+ ]);
+ }
+ if (cframe == 50) { commandLine.pushLineStrings([
+ "======================================================================",
+ "FAIL: tests.openface_neural_net_training_tests.test_dnn_training",
+ "----------------------------------------------------------------------",
+ "Traceback (most recent call last):",
+ " File \"/iris/python2.7/dist-packages/nose/case.py\", line 197, in runTest",
+ " self.test(*self.arg)",
+ " File \"/iris/openface/tests/openface_neural_net_training_tests.py\", line 76, in test_dnn_training",
+ " assert p.returncode == 0",
+ "AssertionError:",
+ "-------------------- >> begin captured stdout << ---------------------",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ==="
+ ]);
+ }
+ if (cframe == 54) { commandLine.pushLineStrings([
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ " ",
+ " ",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0004.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0012.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0006.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0011.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0009.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0008.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Ann_Veneman/Ann_Veneman_0003.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Adrien_Brody/Adrien_Brody_0001.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0005.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0007.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0002.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0010.jpg ===",
+ "=== /iris/openface/data/lfw-subset/raw/Anna_Kournikova/Anna_Kournikova_0006.jpg ==="
+ ]);
+ }
+ if (cframe == 55) { commandLine.pushLineStrings([
+ " cudnn : false",
+ " testBatchSize : 800",
+ " embSize : 128",
+ " cache : \"/tmp/OpenFaceTrainingTest-Net-8TbarF\"",
+ " cudnn_bench : false",
+ " cuda : false",
+ " modelDef : \"../models/openface/nn4.def.lua\"",
+ " data : \"/tmp/OpenFaceTrainingTest-Img-t6cTJ7/aligned\"",
+ " epochSize : 1",
+ " nDonkeys : -1",
+ " save : \"/tmp/OpenFaceTrainingTest-Net-8TbarF/1\"",
+ " nGPU : 1",
+ " device : 1",
+ " epochNumber : 1",
+ " manualSeed : 2",
+ " testing : false",
+ " alpha : 0.2",
+ " nEpochs : 10",
+ " peoplePerBatch : 3",
+ " imagesPerPerson : 10",
+ " lfwDir : \"../data/lfw/aligned\"",
+ " imgDim : 96",
+ " retrain : \"none\"",
+ "}",
+ ]);
+ }
+ if (cframe == 70) commandLine.pushLineString("Saving everything to: /tmp/OpenFaceTrainingTest-Net-8TbarF/1");
+
+
+ if (cframe > 80){
+ commandLine.pushLineString("");
+ commandLine.pushLineString("Welcome to /)(&§§?=!?°§/&$5).");
+ commandLine.pushLineString("Type a command to begin with...");
+ commandLine.pushLineString("Available commands are: [info] [maria] [gerkzeuk] [laserharp] [electronic art] [street] [dance] [t] [genome] [fire] [blog] [constructivism2] and [skip]");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("");
+ busy = false;
+ seqIntro_b = false;
+
+
+ //commandLine.pushLineString("");
+ //pfc = frameCount;
+ //busy = true;
+ //seqOutside_b = true;
+ }
+
+}
+
+function printInfo(){
+ commandLine.pushLineString("This website works similar to a command-line interface.");
+ commandLine.pushLineString("Available commands are:");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("info");
+ commandLine.pushLineString("Gives the information you are reading right now");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("gerkzeuk");
+ commandLine.pushLineString("Gives information about an automatic artist called \'gerkzeuk\' in a pop-up window");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("laserharp");
+ commandLine.pushLineString("Gives information about an instrumental cage that works with lasers and ultrasonic sensors in a pop-up window");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("skip");
+ commandLine.pushLineString("Closes the command-line and brings you to a website containing further information");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("Further commands are available to run interactive and non-interactive animations:");
+ commandLine.pushLineString("street, dance, t, fire");
+ commandLine.pushLineString("");
+ commandLine.pushLineString("And there are more:");
+ commandLine.pushLineString("electronic art, blog, genome, constructivism2");
+ commandLine.pushLineString("");
+}
+
+//Abusing multicultutral acceptance, shame, guilt, ethno-pluralism and constructivism to elaborate ethics of the new world order... Done
+var danceText;
+function seqDance(){
+ var cframe = frameCount - pfc;
+ if (cframe == 0) commandLine.pushLineString("Analyzing users rational and emotional capabilities...");
+ if (cframe == 5) commandLine.changeLineString("Analyzing users rational and emotional capabilities... Done");
+ if (cframe == 8) commandLine.pushLineString("Analyzing users behaviours...");
+ if (cframe == 10) commandLine.pushLineString("Analyzing users behaviours... Done");
+ if (cframe == 15) commandLine.changeLineString("Offering practice in paradigm shifting.");
+ if (cframe == 25) commandLine.pushLineString("Stimulating users ability to see and feel in 5...");
+ if (cframe == 37) commandLine.changeLineString("Stimulating users ability to see and feel in 4...");
+ if (cframe == 49) commandLine.changeLineString("Stimulating users ability to see and feel in 3...");
+ if (cframe == 61) commandLine.changeLineString("Stimulating users ability to see and feel in 2...");
+ if (cframe == 73) commandLine.changeLineString("Stimulating users ability to see and feel in 1...");
+ if (cframe == 78) commandLine.pushLineString("");
+ if (cframe == 85) commandLine.pushLineString("---*---------------")
+ if (cframe == 87) commandLine.changeLineString("------*------------")
+ if (cframe == 89) commandLine.changeLineString("---------*---------")
+ if (cframe == 71) commandLine.changeLineString("-------------*-----")
+ if (cframe == 73) commandLine.changeLineString("-----------------*-")
+ if(cframe == 75) npfc = frameCount;
+ if(cframe > 75){
+ var dframe = frameCount - npfc;
+ if (dframe > 0 && dframe < danceText.length/60+1) {
+ for(var i = 0; i < 60; i++) {
+ commandLine.pushLineString(danceText[i+((dframe-1)*60)]);
+ }
+ }
+ if (dframe == danceText.length/60+1){
+ npfc = frameCount;
+ minc++;
+ if(minc > 10){
+ minc = 0;
+ busy = false;
+ seqDance_b = false;
+ }
+ }
+ }
+}
+var fireText;
+function seqFire(){
+ var cframe = frameCount - pfc;
+ if (cframe == 0) commandLine.pushLineString("Testing users monitor...");
+ if (cframe == 5) commandLine.changeLineString("Testing users monitor... Done");
+ if (cframe == 8) commandLine.pushLineString("More than a million lights available.");
+ if (cframe == 10) commandLine.pushLineString("Analyzing users behaviours...");
+ if (cframe == 15) commandLine.changeLineString("Analyzing users behaviours... Done.");
+ if (cframe == 25) commandLine.pushLineString("Stimulating users rational functions with cognitive insight in 5...");
+ if (cframe == 37) commandLine.changeLineString("Stimulating users rational functions with cognitive insight in 4...");
+ if (cframe == 49) commandLine.changeLineString("Stimulating users rational functions with cognitive insight in 3...");
+ if (cframe == 61) commandLine.changeLineString("Stimulating users rational functions with cognitive insight in 2...");
+ if (cframe == 73) commandLine.changeLineString("Stimulating users rational functions with cognitive insight in 1...");
+ if (cframe == 85) commandLine.changeLineString("Stimulating users rational functions with cognitive insight.");
+ if (cframe == 85) commandLine.pushLineString(" ");
+ if (cframe == 87) commandLine.pushLineString(".");
+ if (cframe == 100) commandLine.changeLineString("..");
+ if (cframe == 113) commandLine.changeLineString("...");
+ if (cframe == 120) commandLine.changeLineString("Cognitive insight not available.");
+ if (cframe == 139) commandLine.pushLineString("");
+ if (cframe == 143) commandLine.pushLineString("Keep watching, animation will end eventually.");
+ if (cframe == 167) commandLine.pushLineString("Initializing fire... *------------------");
+ if (cframe == 169) commandLine.changeLineString("Initializing fire... ---*---------------")
+ if (cframe == 173) commandLine.changeLineString("Initializing fire... ------*------------")
+ if (cframe == 177) commandLine.changeLineString("Initializing fire... ---------*---------")
+ if (cframe == 181) commandLine.changeLineString("Initializing fire... -------------*-----")
+ if (cframe == 185) commandLine.changeLineString("Initializing fire... -----------------*-")
+ if (cframe == 186) npfc = frameCount;
+ if (cframe > 186) {
+ var dframe = frameCount - npfc;
+ if (dframe > 0 && dframe < fireText.length/60+1) {
+ for(var i = 0; i < 60; i++) {
+ commandLine.pushLineString(fireText[i+((dframe-1)*60)]);
+ }
+ }
+ if (dframe == fireText.length/60+1){
+ npfc = frameCount;
+ minc++;
+ if(minc > 3){
+ minc = 0;
+ busy = false;
+ seqFire_b = false;
+ }
+ }
+ }
+}
+
+function seqOutside(){
+ var cframe = frameCount - pfc;
+ if (cframe == 0) commandLine.pushLineString("Preparing user to go outside...");
+ if (cframe == 10) commandLine.pushLineString("Analyzing users behaviours...");
+ if (cframe == 15) commandLine.changeLineString("Analyzing users behaviours... Done.");
+ if (cframe == 18) commandLine.pushLineString("Initiating direct contact to user...");
+ if (cframe == 23) commandLine.changeLineString("Initiating direct contact to user... Failed.");
+ if (cframe == 28) commandLine.pushLineString("Loading non-interactive instructions...");
+ if (cframe == 35) commandLine.pushLineString ("---*---------------")
+ if (cframe == 37) commandLine.changeLineString("------*------------")
+ if (cframe == 39) commandLine.changeLineString("---------*---------")
+ if (cframe == 41) commandLine.changeLineString("-------------*-----")
+ if (cframe == 43) commandLine.changeLineString("-----------------*-")
+ if (cframe == 45) commandLine.changeLineString("---------*---------")
+ if (cframe == 47) commandLine.changeLineString("*------------------")
+ if (cframe == 55){
+ commandLine.changeLineString(" ")
+ commandLine.changeLineString("* How to move:")
+ commandLine.pushLineString(" - Press W, A, S and D to walk")
+ commandLine.pushLineString(" - Drag and Drop the mouse to look around")
+ commandLine.pushLineString(" - Cross the street")
+ }
+ if (cframe == 57) commandLine.pushLineString(" ")
+ if (cframe == 110) commandLine.pushLineString("Assuming user is capable of comprehending and navigating 3D space.");
+ if (cframe == 120) commandLine.pushLineString("Starting boot sequence in 5...");
+ if (cframe == 132) commandLine.changeLineString("Starting boot sequence in 4...")
+ if (cframe == 144) commandLine.changeLineString("Starting boot sequence in 3...")
+ if (cframe == 156) commandLine.changeLineString("Starting boot sequence in 2...")
+ if (cframe == 168) commandLine.changeLineString("Starting boot sequence in 1...")
+ if (cframe == 180){
+ busy = false;
+ seqOutside_b = false;
+ commandLine.pushLineString("")
+ PopupCenter("http://www.victorgiers.com/street/street.html", 'street', screen.width, screen.height);
+ }
+}
+function seqMaria(){
+ var cframe = frameCount - pfc;
+ if (cframe == 0) commandLine.pushLineString("Preparing user to meet Maria...");
+ if (cframe == 10) commandLine.pushLineString("Analyzing users behaviours...");
+ if (cframe == 15) commandLine.changeLineString("Analyzing users behaviours... Done.");
+ if (cframe == 18) commandLine.pushLineString("Initiating direct contact to user...");
+ if (cframe == 23) commandLine.changeLineString("Initiating direct contact to user... Failed.");
+ if (cframe == 28) commandLine.pushLineString("Loading non-interactive instructions...");
+ if (cframe == 35) commandLine.pushLineString ("---*---------------")
+ if (cframe == 37) commandLine.changeLineString("------*------------")
+ if (cframe == 39) commandLine.changeLineString("---------*---------")
+ if (cframe == 41) commandLine.changeLineString("-------------*-----")
+ if (cframe == 43) commandLine.changeLineString("-----------------*-")
+ if (cframe == 45) commandLine.changeLineString("---------*---------")
+ if (cframe == 47) commandLine.changeLineString("*------------------")
+ if (cframe == 55){
+ commandLine.changeLineString(" ")
+ commandLine.changeLineString("* How to move:")
+ commandLine.pushLineString(" - Press W, A, S and D to walk")
+ commandLine.pushLineString(" - Click anywhere to be able to look around")
+ commandLine.pushLineString(" - Allow Pop-Up to listen to a beautiful song and watch the video if you want to")
+ }
+ if (cframe == 57) commandLine.pushLineString(" ")
+ if (cframe == 110) commandLine.pushLineString("Assuming user is capable of comprehending and navigating 3D space.");
+ if (cframe == 120) commandLine.pushLineString("Starting boot sequence in 5...");
+ if (cframe == 132) commandLine.changeLineString("Starting boot sequence in 4...")
+ if (cframe == 144) commandLine.changeLineString("Starting boot sequence in 3...")
+ if (cframe == 156) commandLine.changeLineString("Starting boot sequence in 2...")
+ if (cframe == 168) commandLine.changeLineString("Starting boot sequence in 1...")
+ if (cframe == 180){
+ busy = false;
+ seqOutside_b = false;
+ commandLine.pushLineString("")
+ PopupCenter("http://www.victorgiers.com/Maria/Maria.html", 'Maria', screen.width, screen.height);
+ }
+}
+
+function seqSkip(){
+ var cframe = frameCount - pfc;
+ if (cframe == 0) commandLine.pushLineString("Redirecting to some homepage...");
+ if (cframe == 20){
+ busy = false;
+ seqOutside_b = false;
+ window.location.href = "http://www.victorgiers.com/main.php";
+ }
+}
diff --git a/p5js/console.js b/p5js/console.js
new file mode 100644
index 0000000..41883e8
--- /dev/null
+++ b/p5js/console.js
@@ -0,0 +1,278 @@
+var commandLine;
+function setup() {
+ createCanvas(window.innerWidth,window.innerHeight);
+ textFont("Courier New");
+ textSize(14);
+ frameRate(12);
+ loadAnimationTexts();
+ commandLine = new CommandLine();
+}
+
+function draw() {
+ background(0);
+ stroke(255);
+ strokeWeight(0);
+ fill(255);
+ push();
+ translate(translateX, translateY);
+ scale(scaleFactor);
+// image(fingers,0,0, gwidth, gheight); // draw the video frame to canvas
+ pop();
+ if(busy) runSequence();
+ commandLine.show();
+}
+
+function CommandLine(){
+ this.userInput = "";
+ this.presentedLines = Array(60).fill("");
+
+ this.getUserInput = function(code,c){
+ if(!busy){
+ if (code != 8 && code != 10 && code != 16 && code != 17 && code != 18 && code != 20) {
+ this.userInput = this.userInput + c.toLowerCase();
+ }
+ if (code == 8 && this.userInput.length > 0) { //backspace
+ this.userInput = this.userInput.substr(0, this.userInput.length-1);
+ } else if (code == 13) { //enter
+ this.compareUserInput(this.userInput);
+ this.userInput = "";
+ }
+ }
+ }
+ this.pushLineStrings = function(bottomLines){
+ for(var i = 0; i < bottomLines.length; i ++){
+ this.presentedLines.splice(0, 0, bottomLines[i]);
+ }
+ }
+ this.pushLineString = function(bottomLine) {
+ for (var i = this.presentedLines.length-1; i > 0; i--) {
+ this.presentedLines[i] = this.presentedLines[i-1];
+ }
+ this.presentedLines[0] = bottomLine;
+ }
+ this.changeLineString = function(bottomLine) {
+ this.presentedLines[0] = bottomLine;
+ }
+ this.getInputLine = function(){
+ if(!busy){
+ this.inputString = frameCount % 2 == 0 ? "guest@iris ~ $ " + this.userInput + "_" : "guest@iris ~ $ " + this.userInput;
+ this.presentedLines[0] = this.inputString;
+ }
+ }
+
+ this.show = function(){
+ console.log(this.presentedLines[0]);
+ this.getInputLine();
+ for (var i = 0; i < this.presentedLines.length; i++) {
+ text(this.presentedLines[i], 13, window.innerHeight-150-(i*13));
+ }
+ }
+
+ this.compareUserInput = function(userin){
+ userin=userin.trim()
+ if(this.presentedLines[0].charAt(this.presentedLines[0].length-1) == '_'){
+ this.presentedLines[0] = this.presentedLines[0].substring (0, this.presentedLines[0].length-1);
+ }
+ if (userin === "gerkzeuk"){
+ this.pushLineString("");
+ PopupCenter('gerkzeuk/', 'gerkzeuk', 1024, screen.height);
+ } else if (userin === "info"){
+ printInfo();
+ } else if (userin === "laserharp" || userin === "laserharfe"){
+ this.pushLineString("");
+ PopupCenter('laser/', 'laserharfe', screen.width, screen.height);
+ } else if (userin === "dance"){
+ this.pushLineString("");
+ pfc = frameCount;
+ busy = true;
+ seqDance_b = true;
+ } else if (userin === "fire"){
+ this.pushLineString("");
+ pfc = frameCount;
+ busy = true;
+ seqFire_b = true;
+ } else if (userin === "t"){
+ window.location.href = "t/index.html"
+ } else if (userin === "electronic art"){
+ this.pushLineString("");
+ PopupCenter("https://www.youtube.com/watch?v=3-zyXnc2Xls", "Walter Giers - Electronic Art", screen.width, screen.height);
+ } else if (userin === "genome"){
+ pfc = frameCount;
+ busy = true;
+ seqGenome_b = true;
+ } else if (userin === "blog"){
+ this.pushLineString("");
+ PopupCenter('http://giers.wordpress.com/', 'Neugier & Ästhetik', screen.width, screen.height);
+ } else if (userin === "constructivism2"){
+ pfc = frameCount;
+ busy = true;
+ seqConstructivism_b = true;
+ } else if (userin === "go outside" || userin === "outside" || userin === "go" || userin === "street"){
+ this.pushLineString("");
+ pfc = frameCount;
+ busy = true;
+ seqOutside_b = true;
+ } else if (userin === "maria"){
+ this.pushLineString("");
+ pfc = frameCount;
+ busy = true;
+ seqMaria_b = true;
+ } else if (userin === "skip"){
+ this.pushLineString("");
+ pfc = frameCount;
+ busy = true;
+ seqSkip_b = true;
+ } else if (userin === ""){
+ this.pushLineString(this.inputString);
+ } else {
+ this.pushLineString("Unavailale or forbidden command.");
+ this.pushLineString("Available commands are: [info] [maria] [gerkzeuk] [laserharp] [electronic art] [street] [dance] [t] [genome] [fire] [blog] [constructivism2] and [skip]");
+ this.pushLineString("");
+ }
+ }
+}
+
+function PopupCenter(url, title, w, h) {
+ // Fixes dual-screen position Most browsers Firefox
+ var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
+ var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;
+
+ var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
+ var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
+
+ var left = ((width / 2) - (w / 2)) + dualScreenLeft;
+ var top = ((height / 2) - (h / 2)) + dualScreenTop;
+ var newWindow = window.open(url,title,'scrollbars=yes,width=' + w + ',height=' + h + ',top=' + top + ', left=' + left + ',resizable,scrollbars,toolbar,menubar');
+
+ // Puts focus on the newWindow
+ if (window.focus) {
+ newWindow.focus();
+ }
+}
+
+function runSequence(){
+ if(busy){
+ if (seqIntro_b){
+ seqIntro();
+ } else if(seqDance_b){
+ seqDance();
+ } else if(seqFire_b){
+ seqFire();
+ } else if(seqOutside_b){
+ seqOutside();
+ } else if(seqMaria_b){
+ seqMaria();
+ } else if(seqSkip_b){
+ seqSkip();
+ } else if(seqGenome_b){
+ seqGenome();
+ } else if(seqConstructivism_b){
+ seqConstructivism();
+ }
+ }
+}
+
+var gwidth = window.innerWidth;
+var gheight = window.innerHeight;
+var zoomedState = false;
+var scaleFactor = 1.0;
+var translateX = 0.0;
+var translateY = 0.0;
+
+function reset() {
+ scaleFactor = 1;
+ translateX = 0.0;
+ translateY = 0.0;
+}
+
+function collisionDetection() {
+ while (translateX > 0.0) translateX--;
+ while (translateY*scaleFactor > 0.0) translateY--;
+ while (translateX+gwidth*scaleFactor < gwidth) translateX++;
+ while (translateY+gheight*scaleFactor < gheight) translateY++;
+}
+
+function zoom(delta) {
+ translateX -= mouseX;
+ translateY -= mouseY;
+ scaleFactor *= delta;
+ translateX *= delta;
+ translateY *= delta;
+ translateX += mouseX;
+ translateY += mouseY;
+ collisionDetection();
+}
+
+function keyPressed(){
+ commandLine.getUserInput(keyCode, key);
+ return false;
+}
+
+function mousePressed() {
+ if (mouseButton == CENTER) {
+ if (!zoomedState && scaleFactor == 1.0) {
+ zoom(3);
+ } else {
+ reset();
+ }
+ zoomedState = !zoomedState;
+ }
+}
+
+function mouseDragged() {
+ if (zoomedState) {
+ translateX += (mouseX - pmouseX)/3; //this /3 shit is shit, drag n drop moves too fast, why
+ translateY += (mouseY - pmouseY)/3;
+ collisionDetection();
+ }
+}
+
+function mouseWheel(event) {
+ if(event.deltaY > 0){
+ zoom(1.0/1.05);
+ } else if(event.deltaY < 0){
+ zoom(1.05);
+ } else {
+ zoom(1.0);
+ }
+ zoomedState = true;
+ if (scaleFactor <= 1.0 && event.deltaY > 0){
+ reset();
+ }
+}
+
+//on backspace down + optional callback
+function onBackspace(e, callback){
+ var key;
+ if(typeof e.keyIdentifier !== "undefined"){
+ key = e.keyIdentifier;
+
+ }else if(typeof e.keyCode !== "undefined"){
+ key = e.keyCode;
+ }
+ if (key === 'U+0008' ||
+ key === 'Backspace' ||
+ key === 8) {
+ if(typeof callback === "function"){
+ callback();
+ }
+ return true;
+ }
+ return false;
+}
+
+//event listener
+window.addEventListener('keydown', function (e) {
+
+ switch(e.target.tagName.toLowerCase()){
+ case "input":
+ case "textarea":
+ break;
+ case "body":
+ onBackspace(e,function(){
+ e.preventDefault();
+ });
+
+ break;
+ }
+}, true);
diff --git a/p5js/console_animations/dance.txt b/p5js/console_animations/dance.txt
new file mode 100644
index 0000000..db06730
--- /dev/null
+++ b/p5js/console_animations/dance.txt
@@ -0,0 +1,2040 @@
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooossysssooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooydmmmmmmmhysooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooyhmmmmmmddyyssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooshhyyhhhhdmmmmddhyyysssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooooooooosyhdmmmmmmmddhhysssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssydmmmmmmmmmmddhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssydmmmmmmmmmmmmmmddhhyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+`` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooooooossssssssssyhhddmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+//::--..````````````.-............------------:::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssyyyhhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooooo+//:---...-+oo:.........------------::::://+ossssoo++///////////+++++oossyyhhhhhhhhhhhhhhyyyyyyyysssssssssssssssssyyyyyyyhhdmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+oooooooooooooossssssssss/-:/yddossoo++osssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyyysyyyyyyyyyhdmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+------::::::///+++++oooss+dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmdhhhhdddddddhhhhhddddddddddddddddddddddddddddddddd
+................-----:::::/ossyyosooooooooosssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddd
+------------------------------:---------:::::::////+ooooooo++++oydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++sdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++oyyhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++ooooosssyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++oooooooooooosssydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhddmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhdddddddmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssyhhddmmmmmmmmmmmmmmmmmmmmdddhhhhhddddmmmmmmmmmmmmmmmmmmmmhdddddddddddddmmmmmmmddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssyyhhhddddmmmmmmddhhhhhyyyhhhhhhhhhhddmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhdmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhdmmmmmmmmmmmmmdddhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhdmmmmmmmmmmmdddhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhdmmmmmmmmmmdddhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhdmmmmmmmddhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhdmmmmmmmhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhdmmmmmmdhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhdmmmmmddhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhdmmmmmdhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhdmmmmddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmmdddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddmmmmmmddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddmmmddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::/dho:///////////////////++++++++++++++++osyhhdhhysooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::smmmdo+//////////////////+++++++++++++++ohdmmmmmmmmdysssssossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------:::::::::ommmmmmdhso+/////////////++++++++++++++++oosshddddmmmmmddhyysssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------::::::/smmmmmmmmmdyo///////////++++++++++++++++oooooooosyyyhdmmmmmddhhysssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::+yhyyhdmmmmmdyo////////+++++++++++++++oooooooooooooosshdmmmmmmmmmdhyyssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------:::::::::::::/sdmmmmmmdhyo++++++++++++++++++ooooooooooooooooossydmmmmmmmmmmmddhhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+`` ```````````````............-------------:::::::::::::://+yhmmmmmmmmdhyoo+++++++++++ooooooooooooooooossssssyhddmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+//::--..````````````-/+:...-os/...------------::::::::::::://///+ohmmmmmmmmmmdhyysssssssssssssssssssooooosssssssssssyyhddddmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooooo+//:--...-/osso-..smmd/.------------://++ossyyyyyssssssssshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhhhhhyysssssssyyyyyhhdmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+ooooooooooooosssssssssss+-/mmmmmhsssssyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhyyyyyyhhdddmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+::::::::://////++++oooossommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+................----:::://+oo+++++++++ooossssyhhdmmmmmmmmmmddhhhhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhddddddddddddddddddddddddddddddddddddd
+----------------------------------------:::::://///+ooooo+++++++++++++oooosssyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmddddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssydmmmmmmmmmmmmmmmmmmmmmmddhhhddmmmmmmmmmmmmmmmmmmmmmmmdhhdddddmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssyhddddmmmmmmmmmmdddhhyyyyyhhhhhhhddmmmmmmmmmmmmmmmmmdddddddddddddmmmmmmmmmdddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyhhhhhhhhhyyyyyyyyhhhhhhhhhhhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhddmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdddmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhddmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhmmmmmmmmmddddhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhmmmmmmmmdhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhmmmmmmmdhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhmmmmmmmddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmmddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddmmmmmdddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddmmmmmmddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddmmmmmmddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddmmmmmddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////dh+/////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------::::::::::::::::::///////ommmy++////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::/+mmmmmdyo+////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::/hmmmmmmmdhs+//////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::/ymmmmmmmmmmy+//////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------::::::::::::::/yhyyshmmmmmmho+////////+++++++++++++++shdmmmddhysoooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::::/oydmmmmdhsoo+///+++++++++++++++sydddmmmmmmdhyyyssossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------::::::::::::::://+sdmmmmmmdhys+++++++++++++++++ossssyhddmmmmmmddhhysssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::////odmmmmmmmmmds+++++++++++++oooooooooossyhdmmmmmmmmdhhyssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------:::::::::::::://////ymmmmmmmmmmmdhssoo++++++ooooooooooooooosydmmmmmmmmmmdhhyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+`` ``````````````.::-....//-..-------------::::::::::::::///////ohdmmmmmmmmmmmmmdhsssoooooooooooooooooosssyhddmmmmmmmmmmmmdddhhhhhhhhhhhhhhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+///::-...``````````.+oso-..ommy...------------::::::::::::://////////+syhdmmmmmmmmmmmmmmddhyyyyyyyyssssoosssssssyyhhddmmmmmmmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooo+//:--.-/ossss/..dmmmy------------://+oossyyyyyyyyyhhhhhddhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddhhhhysyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+oooooooooooosssssssssssso-+mmmmmmyssyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+:::::::://////++++oooossssmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+................----:::///ossso+++++oooossssyhhddmmmmmmmmmmddhhyyyyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhdddddddddddddddddddddddddddddddddddddddd
+---------------------------------------::::::://///+ooo++++++++//+++++++oooooossyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++oooooooooooshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++oooooooooooooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssymmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooossssssssssshdmmmmmmmmmmmmmmmmmmdhyyyyyyyhhddmmmmmmmmmmmmmmmmmmmdhhddmmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssssyyhhddddddddddhhyyyyyyyyhhhhhhhhhdddmmmmmmmmmmmmmmmddddddddmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhddmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhddmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhdmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdddmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhdmmmmmmmmddddhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhdmmmmmmmdhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhdmmmmmmmdhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhmmmmmmddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddmmmmmdddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddmmmmddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddmmmmmddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddmmmmmmmdddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddmmmmmdddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddmmmmmdddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++o+++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++omdo++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://////////////////////ommmhso+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://///////////////+mmmmmdhs+///+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------:::::::::::::::://////////////ymmmmmmmmho//////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------::::::::::::::::::////////ymmmmmmmmmds+/////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://+hdddhhdmmmmdso+/////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::::/+++//+sdmmmmdhso////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::::::://///odmmmmmmds+///++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://///sdmmmmmmmdyo+++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://////sdmmmmmmmmdhso+++++++++++oshddddhhyssoooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------::::::::::::::://////+ymmmmmmmmmmdhhyso++++++oyhmmmmmmmmdhhyysoossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////ohmmmmmmmmmmmmmmdyo++++oossyydmmmmmmmmmmdhssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````.......--...-------------:::::::::::::://///////+shmmmmmmmmmmmmmmddysooooooooosyhdmmmmmmmmmdhhyysssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+`` ``````````````-/+/...:ys/..-------------::::::::::::::////////////++osyhdmmmmmmmmmmmmhysoooooooooosyhddmmmmmmmmmdhhhhhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+//::--..```````````-osso:..hmmd-..------------:::::::::::::///////+++///++ossyhdmmmmmmmmmmmmmmdhyyyssssoossssyhdmmmmmmmmmmmmmmmdddddddddddddddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooooo++/:--..-+ossss+..mmmmh:-----------://++oossyyyyyyyyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+oooooosssssssssssssssssso-/mmmmmmyossyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+////////+++++++oooossssssommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+............-----::://++++yyyyyyssssssssyyhhhddmmmmmmmmmmmmddhyyssyyhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhddddddddddddddddddddddddddddddddddddddddddd
+----------------------------:::------::::::://///+osssooo++++++///++++++ooooooossyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooosymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++oooooooooooooooooshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssydmmmmmmmmmmmmmmmmmmmmdhhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooossssssssssssshdmmmmmmmmmmmmmdhhyyyyyyyyyhhhhhdmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyhhhhhhhhyyyyyyyyyyyhhhhhhhhhhhhddmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhddmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhdmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhddmmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmmmmmdddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhmmmmmmmmdddhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhmmmmmmmdhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhdmmmmmmdhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhdmmmmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhmmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmdddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmmmdddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddmmmmmmddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddmmmdddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddmmmmmdddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
++////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++sdho++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++smmdyo++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++ommmmmds++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++hmmmmmmmyo++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://////////////////////+hmmmmmmmmhs++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////+mmmmmmmmmmdy++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////sdddhshmmmmmds+/++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------::::::::::::::::::///////////////+hmmmmmmho++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////ohdmmmmmdhso++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::::://///////oymmmmmmmdhyo++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::////////+dmmmmmmmmmdyo+++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------::::::::::::::::::::////////ymmmmmmmmmmmdyoo++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::::////////ohdmmmmmmmmmmmmdhys++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------::::::::::::::://///////+shdmmmmmmmmmmmmmhysoooyhhhhyysooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::://////////+++oyhdmmmmmmmmmmmmmmmmmmmmmmdhsoooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````..-.....---..-------------::::::::::::::///////////////+++sdmmmmmmmmmmmmmmmmmmmmmmmmmdhyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+` ``````````````:oso-..+mds..-------------::::::::::::::///////////////+++++ohdmmmmmmmmmmmmmdddddddmmmmmmmddhhyyyyyssssssyyyyyyyyyyyhhhhhyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+/::--.````````````.:osss/..dmmm:..------------::::::::::::://////++++++++oossyyhhhdmmmmmmmmmmmmmmmdhysyyyhdmmmmmmmmmmmddhhhhhhhyyyyyyyhdmmmmmdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooo+/::-..``-+ossss+..mmmmd/------------:::/++ossssssyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+sssssssssssssssssssssssso-:mmmmmmy+++ossshhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
++++++++++++ooooosssssssss+hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhdddddhddddddddddddddddddddddddddddddddd
+......--------::://++oooo+hmmmmddddhhhhhddddmmmmmmmmmmmmmmmmmdhyyssyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhdmmmmmmmmmmmdddddddddddddddddddddddddddddddd
+--------------------------:::::::::::::::::////+oosyyyyysso+++++///++++++ooooossyyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++oooooooooooooossymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooossssssydmmmmmmmmmmmmmmmmmmmmmdhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssssyhmmmmmmmmmmmmmmmmdhyyyyyyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssyhhddmmddddhhyyyyyyyyyyyyhhhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhddmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhddmmmmmmmmmmmmmmddddddddddmmmmmmmmmddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhdmmmmmmmmmmmmdddhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhdmmmmmmmmmmmdddhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhmmmmmmmmddddhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhmmmmmmmdhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhdmmmmmmdhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhdmmmmmmdhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhmmmmmddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddmmmmmddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddmmmmddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddmmmmddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddmmddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+yo++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+yo+++++++++++++++++++++++++ooooooooooooooooooosyoooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+y+///////++++++++++++++++++++++++oooooooooooooymdsoooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+s////////////////+++++++++++++++++++++++++++++smmmhooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////++++++++++++++++++++++ommmmmdyso+++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++smmmmmmmhs++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////++++++++++++++smmmmmmmmdy++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////++++mmmmmmmmmmmso++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------::::::::::::::::::::///////////////////////sddddhhmmmmmdyo++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------::::::::::::::::::///////////////////+oo+/+oymmmmmdhyo+++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////+hmmmmmmmdy+++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////+hmmmmmmmmdso++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://////////////ohmmmmmmmmmhyso++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::///////////+smmmmmmmmmmmdys+++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::::::://////////+hmmmmmmmmmmmmmdys+++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////+ydmmmmmmmmmmmmmmhooo+++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::::////////////osyhddmmmmmmmmmmdhysooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------::::::::::::::://////////////++oshdmmmmmmmmmmmdhsooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////++++sdmmmmmmmmmmmmmhsoooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````-//-...-++:..-------------::::::::::::::///////////////++++++sdmmmmmmmmmmmmmmdhsssooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ `````````````.+sso-..smmh-.-------------::::::::::::::///////////////++++++++ydmmmmmmmmmmmmmmmmdhhyyyysssssssssssssssssyyyyyyyyyyhdddddhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+/::-..````````````-/osss/..dmmmo..------------:::::::::::::////++oooooooossyyhhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmddddhhyyyhhhhhhhhhhhhhhhddmmmmmmmmhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooo+//:--..../osssss+..dmmmms------------:::/++ossyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+ssssssssssssssssssssssss+.-mmmmmmho++osssshhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
++++++++++ooooosssssssssss:smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhddddddddddddddddddddddddddddddddddddddddddd
+-..--------::::///++oosso+hmmmmmmmmddddddddmmmmmmmmmmmmmmmmmddhyssossyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+--------------------------:://:::::::::::://///+oosyyyyysoo+++++///++++++++oooooossyyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooossssdmmmmmmmmmmmmmmmmmmmmmdddhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooossssssssyhdmmmmmmmmmmmmmmmdhhyyyyyyyyhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssyyhddmmmdddhhyyyyyyyyyyyyyyhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhddmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhddmmmmmmmmmmmmmmdddddddddddddmmmmmmmmmddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhddmmmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhmmmmmmmmmmmddhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhdmmmmmmmdddhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhmmmmmmdhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhmmmmmmdhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhdmmmmmhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhdmmmmdhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhdddmmmmmdhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhdmmdmmmmddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddmmmdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddmmmddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++oo++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+yhy++++++++++ooooooooooooooooooooooooooooooooosoooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+yys+++++++++++++++++ooooooooooooooooooooooooosdyoooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+yy+++++++++++++++++++++++++ooooooooooooooooooymmhsoooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+y+///////++++++++++++++++++++++++ooooooooooooommmmdyoooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////+++++++++++++++++++++++++++++hmmmmmmhsooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////++++++++++++++++++++++ohmmmmmmmhso+++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////+++++++++++++++++++dmmmmmmmmdyo+++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////++++++++++++++ymmmmmmmmmmmyo+++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////++++hddhyshmmmmmmhoo+++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+ohmmmmmmdyso++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////+ohmmmmmmmdhso+++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::////////////////////////+ohmmmmmmmmmds+++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------::::::::::::::::::////////////////////odmmmmmmmmmmhso++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::////////////////smmmmmmmmmmmdhsso++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::::://///////////oydmmmmmmmmmmmmdhys++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::////////////+shmmmmmmmmmmmmmmdyo+++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////oshdmmmmmmmmmmmmdhsooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////+sydmmmmmmmmmmmmhysooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////+++oshmmmmmmmmmmmmddysooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////++++++oymmmmmmmmmmmmmmdhsoooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````:oo:...-oho..-------------::::::::::::::///////////////++++++++ohmmmmmmmmmmmmmmmdysoooosssssssssssssssssssyyyyyyyyyyyyhhhyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ `````````````-osso-..smmd-.-------------::::::::::::::///////////////++++++++ooshmmmmmmmmmmmmmmmmhyssssssssssssssssssssyyyyyyyyyhdmmmmmdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+::-..`````````````-+ssss/..hmmms-.------------:::::::::::::////++ooooooooosyyyhhhhhddddmmmmmmmmmmmmmmmmmmdyyyhhhddhhhhddddddddddddddddmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooo+//:--.```./osssss/..hmmmmh------------:::::/+++osssyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+ssssssssssssssoossssssss/..dmmmmmd+//++++ossyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddd
+++++++oooooosssssssssssso-:mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddddddd
+--------::::://++oossssss:ommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhyssosssyyyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+--------------------:::::--+osso+++/::://////+++oosyyyyyysso++++///++++++++ooooooossyyhhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosshmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssshdmmmmmmmmmmmmmmmmdhyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssyhhddmmmmddddhhyyyyyyyyyyyyyyhhhhdmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhdddmmmmmmmmmmmmmmdddhhddddmmmmmmmmmmmmmmmmmdddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhdmmmmmmmmmmmmmdddddhhhhddddddddddmmmmmmmmmddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhdmmmmmmmmmdddhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhmmmmmmmhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhdmmmmddhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhdmmmmdhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhddmmmmmmdhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhdddmmmmdhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhddmmmmddhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhdddddhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oossoooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+oyhyoooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+hhhs+++++++++oooooooooooooooooooooooooooooooymysooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+yyy+++++++++++++++++oooooooooooooooooooooooosmmhysoooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ys+++++++++++++++++++++++++oooooooooooooooooommmmdhsoooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+s////////++++++++++++++++++++++++oooooooooooosmmmmmmmhoooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
++////////////////+++++++++++++++++++++++++++++smmmmmmmmhoooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++ymmmmmmmmmhso+ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++ommmmmmmmmmmdyo+++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////++++++++++++++oyhysosdmmmmmmhs+++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++smmmmmmmmhoo++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++ydmmmmmmmdhso+++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------::::::::::::::::::////////////////////////////+shmmmmmmmmdhyo++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------:::::::::::::::://////////////////////////+odmmmmmmmmmmdyo+++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////ymmmmmmmmmmmmdysoo+++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://///////////////oydmmmmmmmmmmmmmdhso++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::///////////////+osydmmmmmmmmmmmmdhyoo+ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////+++oydmmmmmmmmmmmmmhsoooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++shmmmmmmmmmmmmmhsooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++oydmmmmmmmmmmmmmhysooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++oydmmmmmmmmmmmmmmdhyooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````-:-.....-::.-------------:::::::::::::::///////////////++++++++osdmmmmmmmmmmmmmmmmhsoooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ``````````.+ss:...-hmh-.-------------::::::::::::::///////////////+++++++++++sdmmmmmmmmmmmmmmmmdsssssssssssssssssssyyyyyyyyyyyhdmmmmdhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+` ````````````./osso...+mmm+.-------------::::::::::::::///////////////++++ooooosssshmmmmmmmmmmmmmmmmmdhsssyyyyyyyyhhhhhhhhhhhhhhhdmmmmmmmmdhyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+/::-..```````````./ossss-..ommmd/.------------::::::::::::://+ossyyhyyyyyyyhhdddddddmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooo++/::--../ossssss-..ommmmm+-----------:::/++ossyyhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhddddddmdddddddddddddddddddddddddddddddddddd
+osssssssssssssssssssssss-..ommmmmmyooosssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhmmmmmmmmmmmmmmmdddddddddddddddddddddddddddd
+////+++++ooooossssssssss+.-dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+......-----::::/++oosssso.-mmmmmmmmmmddddddddddmmmmmmmmmmmmmdhysooooooossssyyyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+---------------------------:++o++/::::::::////////+oooooo+++++/////+++++++++++ooooooooossssyyyyyhhmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssyhdmmmmmmmmmmmmmmmdhyyyyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooossssssssssyhhddddddhhhyyyyyyyyyyyyyyyyyhhhdmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmdddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhdddmmmmmmmmmmmmmmmddddddddmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyhddmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyhhmmmmmmmmmmmmmmmdddhhhhhhdddmmmmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhmmmmmmmmmmddddhhhhhhhhhhhhdddddddmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhmmmmmmmdhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhdmmmmmdhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhddddmmmmdhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhddmmmmmmdhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhdmmmmmdhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhmmmddhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooossooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++oyhyooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+yhhhs++++++++ooooooooooooooooooooooooooooooymysoooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+yyys++++++++++++++++ooooooooooooooooooooooosmmdysooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+yyo++++++++++++++++++++++++ooooooooooooooooohmmmmdhsoooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+yo///////++++++++++++++++++++++++oooooooooooohmmmmmmmyoooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+s////////////////+++++++++++++++++++++++++++++dmmmmmmmmyoooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////++++++++++++++++++++++ommmmmmmmmmhysoooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++hmmmmddmmmmmdhso++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////++++++++++++++osoo++sdmmmmmmmhso+++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++sdmmmmmmmmdyoo++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++shmmmmmmmmmdyso+++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------::::::::::::::::::////////////////////////////+oymmmmmmmmmmdhys++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------:::::::::::::::://////////////////////////++ymmmmmmmmmmmmdhs+++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////odmmmmmmmmmmmmmmdhsoo++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://////////////////oyhdmmmmmmmmmmmmmmhsso+ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////+oosyhdmmmmmmmmmmmddhysoooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::::::://///////////////++++shmmmmmmmmmmmmmdhsooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++ydmmmmmmmmmmmmmmdysooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++shmmmmmmmmmmmmmmmdhysooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++shmmmmmmmmmmmmmmmmdhysooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````:/-....../+.-------------:::::::::::::::///////////////++++++++++oymmmmmmmmmmmmmmmmmmhsosssssssssssssssssssyyyyyyyyyyyhhhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ``````````.oso.....omm-.-------------::::::::::::::///////////////+++++++++++++ydmmmmmmmmmmmmmmmmmdysssssssssyyyyyyyyyyyyyyyyydmmmmmmdhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ ````````````-+oss+...-mmmy--------------:::::::::::::://////////////+++++oooossssssshdmmmmmmmmmmmmmmmmmdhhdddddmmmmmmmmmmmmmmmddmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+/:--.````````````:osssso...+mmmms-------------::::::::::::://++osyyhhyyhhhhhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddmdddddddddddddddddddddddddddddddddddd
+ooooooo+//:---.:+osssss+...:mmmmmy-----------::::/++ossyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhdmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+ossssssssssssssssssssss+...-mmmmmmdso+osssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhdmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+//++++++ooooosssssssssso-..+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+....-----::::://++osssss:.-smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyysooooooosssssyyhhhhdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+---------------------:-----:+osso++/::::////////////++ooo++++++////++++++++++++oooooooooosssssyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooossssyhhdddddddddhhdddmmmmmmdddddddddddddmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmdddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyhhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhddmmmmmmmmmmmmmmmddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyhmmmmmmmmmmmmmmmmddddddhhhhhddmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyydmmmmmmmmdddddhhhhhhhhhhhhhdmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyhhhhdmmmmmmdhhhhhhhhhhhhhhhhhhhhhddddmmmmmmmmmmmmmmmmddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyhddmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhddddddddddmmmmmmmmddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyhdmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyhmmmmdhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++osysooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ossyhyo++++++oooooooooooooooooooooooooooooyhsoooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+yyyyyo++++++++++++++ooooooooooooooooooooooymdyssoooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+yyys+++++++++++++++++++++++oooooooooooooooodmmmdhysooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+yys+/////++++++++++++++++++++++++ooooooooooodmmmmmmdsooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+yy+//////////////+++++++++++++++++++++++++++odmmmmmmmdyooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+o+//////////////////////+++++++++++++++++++++ommmmmmmmmmdyso+ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////+++++++++++++++++ymmmmmdmmmmmmdys+++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++ossoo+ohmmmmmmmdhs++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////++++++++++ohmmmmmmmmmdyoo++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////++oydmmmmmmmmmdhyso++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------::::::::::::::::::////////////////////////////oshmmmmmmmmmmmdhys+++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------:::::::::::::::://////////////////////////+odmmmmmmmmmmmmmmhyso++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////ohmmmmmmmmmmmmmmmmdyoooooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://////////////////+oyhddmmmmmmmmmmmmmdysssoooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::::://///////////////++oosshdmmmmmmmmmmmmddhysooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////+++oydmmmmmmmmmmmmmmmdysooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////+++++ohmmmmmmmmmmmmmmmmmhssooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////+++++++oydmmmmmmmmmmmmmmmmmhysoooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////+++++++++oshmmmmmmmmmmmmmmmmmdhysssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````:+:.....-o+.-------------:::::::::::::::///////////////++++++++++++oymmmmmmmmmmmmmmmmmmmhssssssssssssssyyysyyyyyyyyyddmdmdddhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ``````````.oso-....ymm-.-------------::::::::::::::///////////////+++++++++++++oosdmmmmmmmmmmmmmmmmmmmhhdddmmmmmmmmmmmmmmmddddmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+`` ````````````-oosso...:mmmy--------------:::::::::::::://////+++++++ooooosssssssyyyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhdddddmmddddddddddddddddddddddddddddddddddd
+//::-..`````````./osssso...+mmmmy-------------::::::::::://++ossyhhhhhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhdmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+oooooooo++/::::/+osssss+...:mmmmmh:----------://+ossyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhdmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+oooooosssssssssssssssss/....mmmmmmmhsssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+:::////+++++oossssssssso-..+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+........-----:://++oooo+-.-+mmmmmmmddhhhhhhhhhhhhhdddmmmmmddhyssoo+++++++oooossssyyyyhhhhhhmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+----------------------------:/++/:::::::::::::////////+++++++//////++++++++++++++oooooooooohmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmdddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++oooooooooooooohdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddhhhhhhhhhdmmmmmmmmmmmmmmdddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooossssssssssssyyyyyhhhhhhhdmmmmmmmmmmmmddddhdhhhhhhhhhhhhhhhhhhddddddddmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyydmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyydmmmdhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhddddmmmmmmmmmmmmmmmdddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddmmmmmmdddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+++++++o++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+//++syyo/++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+syyyyys//////////++++++++++++++++++++++++ymhoooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+yyyso+//////////////////+++++++++++++++++odmmhysso+++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+yys/::://////////////////////+++++++++++++oymmmmddhyo++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+yy/:::::::::::////////////////////++++++++++ommmmmmmmdyso++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
++/:::::::::::::::::::////////////////////////smmmmmmmmmmmmhsoo++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------::::::::::::::::::::////////////////////hddddhhdmmmmmmmdhyssoo++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------::::::::::::::::::////////////////++++//+oydmmmmmmmmmddhhys++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------:::::::::::::::://///////////////////++ymmmmmmmmmmmmmmdyso+++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////ohmmmmmmmmmmmmmmmmddhyoooo+ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://////////////+shdmmmmmmmmmmmmmmmmmmhyyyssssoooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////+osyhddmmmmmmmmmmmmmmmmmmmmddhhyssooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::::::://///////////++++++osyhmmmmmmmmmmmmmmmmmmmmmhysooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++oydmmmmmmmmmmmmmmmmmmmmmdysssossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////+++++++oyhdmmmmmmmmmmmmmmmmmmmmdhyssssssssssssssssssssyyyyyyyyyhhddhdhhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++osydmmmmmmmmmmmmmmmmmmmmmddhhhhhhhyyhhhhhhhhhhhhhhhhhmmmmmmmdhyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++ooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhdhhhhhhhhhhddddddddddddddddddddddddd
+ `````````./o-.......-o+--------------::::::::::::::///////////////+++++++++++++++oooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhddmmmmmmmmmmmmmmddddddddddddddddddddddddd
+ ```````````./oo+.......omm/-------------::::::::::::::///////////////+++++ooooooosssssssssyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+.```````````````:+osss:......dmmd/------------::::::::::::://////+oosssssyhhdddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhdmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ooo+/::--.````-+osssss/.....:mmmmmo----------:::::::::::/+ossyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ossssssssssoosssssssss-......dmmmmmh/:::::::/+oosyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+//+++++oooosssssssssss.......ymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+...------::://++osssss-...---dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhysssoosssssssyyyyhhhhhdddddddmmmmmmmmmmmmmmmmmmmmmdhhyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmddddddddmmmmmmmmmmmmmmdddddddddddddddddddddd
+------------------:::--------/syyyso++:////////////+oosyyyysso+++++++++++++++++++ooooooooooosssssssyydmmmmmmmmdddhyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhdddmmmmmmmmmmmmdddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssssssssssssssyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhddmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++oooooooooooooooooyyyhdddmdhhyyyhhhddmmmmmmmmmmmmmmmmmmmmmmdddddddhhhhhhhhhhhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddmmmmmmmmmdddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssydmmmmmmmdddddddhhhhhhhhhhhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssyyyyssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+///++oss////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+oosssyyo/////////////////////++++++++++++hhs+++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+yyyyo+/:::::::////////////////////+++++++hmmdys++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+sss/:::::::::::::::::////////////////////+hmmmmmdhyo++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+ss+---:::::::::::::::::::://///////////////+smmmmmmmdhhysso+++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::-----------:::::::::::::::::://////////////ymmmmmmmmmmmmddhyysso++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////yddhsooydmmmmmmmmmmmmmdhyo++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://///////////+sdmmmmmmmmmmmmmmmdhysooooooo+++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------:::::::::::::::::::://////////+shdmmmmmmmmmmmmmmmmmmmddhyssssssssooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------::::::::::::::::::::://///////+osdmmmmmmmmmmmmmmmmmmmmmmmmmmddddhhyysooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::::::::::::::://///////++osydddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhysoooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++oshmmmmmmmmmmmmmmmmmmmmmmmmmmdhssssssssssyyddhhyysssyyyyyyyyyyhhdhdhyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++oshhdmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhmmmmmmdhyyhhhhhhhhhmmmmmmmdhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++osyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++oooyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhddmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ `````````.:-.........-:--------------::::::::::::::///////////////+++++++++++++++oooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ```````````-+oo-.......-dm+-------------:::::::::::::://////////////+++oooooossssssssyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+.``````````````.:ooss+......./mmmo------------:::::::::::::///////+osssssyhhdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+oo++//::-....-/oosssso.......ymmmmy:---------:::::::::::/++oossydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ooooossssssssssssssss/.......ommmmmmo/:::::/+++oosyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+::////++++ooossssssss:.......:mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmdddddddddddddddddddddd
+.......----:::/++ooo+:....---:mmmmmmmmddhhhhhhddddddmmmmmmmmmmmmdhyssoooooooossssssyyyyyyyyhhhhhdddmmmmmmmmmmmmmmmdhhyyyyyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmdddhhdddmmmmmmmmmmmmmmmddddddddddddddddddddddd
+------------------------------:++++/:::::::::////////++osssssoo++++++++++++++++++oooooooooooooosssssssyhhhhhhhyyyyyyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmmdhhhhdmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooossssssssssssssssssyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooossssyyyyysssssssyyyhhddmmmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhhhddddddddmmmmmmddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssyhhdmddhhhhdddmmmmmmmmmmmmmmddddhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssshmmmmmmmmmmmmmmmmmmmmmmddddhhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssyhdmmmmmmmdddhhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+:::::::::::::::::::::::::::::::////////////////////////////////////////////////////////////////////////////////////////++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooossssssssssssss
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://////////////////////////////////////////////////////////+++++++++++++++++++++++++++++++++oooooooooooooooooooooooooooooosssssssssssss
+------::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://///////////////////////////////////////////////++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssss
+---------------:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://////////////////////////////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooossssssssss
+---------------------:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::///////////////////////////////////////++++++++++++++++++++++++++++++oooooooooooooooooooooooooooosssssssss
+----------------------------:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::////////////////////////////////////+++++++++++++++++++++++++++++oooooooooooooooooooooooooooossssssss
+----------------------------------:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::///////////////////////////////////++++++++++++++++++++++++++++ooooooooooooooooooooooooooosssssss
+.....----------------------------------------------------::::::::::::::::::::::::::::::::::::::::::::::::::////////////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooooooosssssss
+............------------------------------------------------------:::::::::::::::::::::::::::::::::::::::::::///////////////////////////////+++++++++++++++++++++++++++oooooooooooooooooooooooooosssssss
+...................-------------------------------------------------------:::::::::::::::::::::::::::::::::::::///////////////////////////////++++++++++++++++++++++++++oooooooooooooooooooooooooossssss
+.........................------------------------------------------------------::::::::::::::::::::::::::::::::::://///////////////////////////++++++++++++++++++++++++++ooooooooooooooooooooooooossssss
+...............................----------------------------------------------------:::::::::::::::::::::::::::::::::////////////////////////////+++++++++++++++++++++++++ooooooooooooooooooooooooossssss
+....-:::...........................--------------------------------------------------::::::::::::::::::::::::::::::::///////////////////////////+++++++++++++++++++++++++ooooooooooooooooooooooooossssss
+:::////:................................-ss+:-...---------------------------------------::::::::::::::::::::::::::::::///////////////////////////++++++++++++++++++++++++ooooooooooooooooooooooooossssss
+///:--..```````..........................ymmhyo+/:-....------------------------------------:::::::::::::::::::::::::::://////////////////////////++++++++++++++++++++++++ooooooooooooooooooooooooossssss
+:::``````````````````....................-shmmmmmmdhso//:-...-------------------------------:::::::::::::::::::::::::::://///////////////////////++++++++++++++++++++++++oooooooooooooooooooooooosssssss
+..``````````````````````....................-hmmmmmmmmmmmmmdhyso++/::::----------------------:::::::::::::::::::::::::/ohhyo//////////////////////+++++++++++++++++++++++oooooooooooooooooooooooosssssss
+`````````````````````````````................:hdhhyssyhdmmmmmmmmmmmmmmdhsso++/////::-----::::-::::::::::::::::::::::::+hmmmmms///////////////////++++++++++++++++++++++++oooooooooooooooooooooooosssssss
+ ```````````````````````````..............-::-....:/+oydmmmmmmmmmmmmmmmmmdddddhhyyyyyyhhyyyssoo+//:::::::::::::::::+shmmmmhy+////////////////+++++++++++++++++++++++oooooooooooooooooooooooossssssss
+ `````````````````````````......................--:oymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhys+::::::::::::///+hmmmmmy+/////////+oo++++++++++++++++++++++++oooooooooooooooooooooooosssssssss
+ `````````````````````````........................-/shdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdyso//+//++//////ommmmmds+++++smmmmmmyo++++++++++++++++++++ooooooooooooooooooooooossssssssss
+ `````````````````````````..........................-::::::::/+osyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhymmmmmmmdddddmmmmmmmmmhso+++++++++++++++oossssssssooooooooooooooossssssssss
+ `````````````````````````...........................----------:/++oyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhys+++++osyhhhhddmddddddhyoooooooooossssssssssss
+ `````````````````````````..........................---------------:::/oyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdo++hmmmmmmmmmmmmmmmmmmdsooooooosssssssssssss
+ ``` `````````````````````````.........................---------------------:::/+oyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmo+ohmmmmmmmmmmmmmmmmmmmmsooooossssssssssssss
+ `--. ````````-o:``````````````.........................----:::://///+++++ooosssyyyhhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyyhmmmmmmmmmmmmmmmmmmmmmhoooosssssssssssssss
+` `.-:::`````````smd/`````````````...................-::///+osyhhhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyoosssssssssssssssss
+::---...`````.-::::::`````````dmmms.``````````............-:::/oshddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyoossssssssssssssssss
+:::::::::::::::::::::`````````mmmmmmo:--------:/++osyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyo+///oshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhysydmmmmmmmmmmmmsoosssssssssssssssssss
+......------::::::::-`````````smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhyo+//////////+osyhddmmmmmmmmmmmmmmmmhysssyhdmmmmmmmmmmmmmmhoossssssssssssssssssss
+````````````....----.`````````/dmmmddhyyyysssyyyyyhhddmmmmmmmmmmdyso+///::::://///++++++++++ooooossyhhddmmmmmddhysso++///////////////++osyhmmmmmmmmmmmmmmdsooydmmmmmmmmmmmmmmmmhysssssssssssssssssssssss
+``````````````````````````````...--..............------::////:::---------------------:::::::::::::::////////////////////////////+osyhdmmmmmmmmmmmmmmmmmdhooooddddmmmmmmmmmmdhyssssssssssssssssssssssssyy
+```````````````````````````````````````.......................----------------------::::::::::::::::::::::://///////////++osyhdmmmmmmmmmmmmmmmmmmdhysooooooooooooooosssyssoooosssssssssssssssssssssssyyy
+```````````````````````````````````........................----------------------:::::::::::::::::::::::://////////+osyhdmmmmmmmmmmmmddddhhyssooo++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyy
+..........`````````````````..............................----------------------::::::::::::::::::::o++++///////+oyhddmmmmmmmmmdhyssssoooo++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyy
+......................................................----------------------:::::::::::::::::::::::+sshmmhyssydmmmmmmmmmdhhyo++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyy
+....................................................----------------------:::::::::::::::::::::/yhhyhhmmmmmmmmmddhysoo+//++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyy
+................................................-----------------------::::::::::::::::::::::::+syhhddhhyssoo++///////++++++++++++++++++++++oooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyy
+............................................------------------------::::::::::::::::::::::::///////++++/////////////++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyy
+----....................................-------------------------::::::::::::::::::::::::////////////////////////++++++++++++++++++++++oooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyy
+------------------...................-------------------------:::::::::::::::::::::::::////////////////////////++++++++++++++++++++++oooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyy
+---------------------------------------------------------::::::::::::::::::::::::::////////////////////////+++++++++++++++++++++++oooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyh
+------------------------------------------------------:::::::::::::::::::::::::://///////////////////////+++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhh
+-------------------------------------------------::::::::::::::::::::::::::://///////////////////////+++++++++++++++++++++++oooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhh
+---------------------------------------------:::::::::::::::::::::::::::://///////////////////////++++++++++++++++++++++++oooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhh
+::::::::::::::--------------------------:::::::::::::::::::::::::::://////////////////////////++++++++++++++++++++++++oooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhh
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::///////////////////////////++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhh
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::///////////////////////////+++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhh
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::////////////////////////////+++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhh
+:::::::::::::::::::::::::::::::::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhh
+/////////:::::::::::::::::::::::::::::::::::://///////////////////////////++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhd
+//////////////////////////::::::::::::///////////////////////////////+++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhddddd
+//////////////////////////////////////////////////////////////////++++++++++++++++++++++++++ooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhddddddd
+////////////////////////////////////////////////////////////++++++++++++++++++++++++++++ooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddd
+///////////////////////////////////////////////////////++++++++++++++++++++++++++++oooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddd
+++++/////////////////////////////////////////////+++++++++++++++++++++++++++++oooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddd
+++++++++++++++//////////////////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+++++++++++++++++++++++++++++++++++///++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooooooossssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddmm
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssymmdhyyssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssshmmmmmdyssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssshhmmmmmhysyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+--::/ooo:----------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssyhmmmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+ssssssss:---------------::::::::::::::::/yyo////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssyhmmmmdyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+sso+++/:......--------------::::::::::::/mmmdhysooo++++/++/++//////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssymmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+++:...............-------------::::::::::ohddmmmmmmddddhhhhhhhhhhhhhhhyyyssooooooooooossyyyyyyhhhhhyyyyysssoossssssssssssssssshmmmmmmdhhyyyyyyhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------:::::::://smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhyyyyyyyssssssssymmmmmmmmmmmmmmmmmdhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::oyso/:::+oyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::::/+osyhddmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhddddmmmmmmmmmmmddddddddddddddddddddddd
+ ```````````...........--------------::::::::::::::://///+oooosssoooooosssyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhddmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++oooooosyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhdmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++ooooooooossyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````-::...........//-------------:::::::::::::://////////////++ooossssssyyyhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+-..```````````.-/ooo-.........:dds------------::::::::::::://///////++ossyhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ooooo++///::/+ooosss:.........+mmmh+---------:::::::::/+ossyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+oooooooooossssssssss+.........ommmmmdysssssssssyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+..---:::://++o+ooooo-........./mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddhdddddddddddddmmmmmmmmmmmmmmmmmmmmmmmddddhhhyyyyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmdhdmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+...........----:::::......-----syyysyyssoooossssssyyyhhddmmmmmddhyyssoooooo++oooooooossssssssyyyyyyyyyhhhhhhhhyyyyysssyyyyyyyyyyyyyyyhhhddmmmmmmmmmmmmmmmmdhhdddddddmmmmmmmddddddddddddddddddddddddddddd
+---------------------------------:::::::::::::::::///////++++++++++++++++++++++++ooooooooooooooooossssssssssssssssssyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyhhdmmmmmmmmmmmmmmmmmmmddddhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyhhdmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyhdmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssddddhhhyyyhdmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssyyyyhmmmmmmmmmmmmddhhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssydddmmmmmmddddhhhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooosssssssssssssssyyyhhhhhhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssssssssssymmmdhhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssydmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssyhmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssdmmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssshdmmmdyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssssydmmmmdyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssymmmmmmhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssshmmmmmmmhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssshmmmmmmmmmdhhhhyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```..--...........-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooosssssssssssssssssssssssssssssssyhdmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
++++ooooo..............-------------::::::::::::::::::::///////////////////+++++++++++++osyhhdmmmmmmmmmmmmmmmmmmmmmmmmddhhysssssssyyyhhmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+ooooooo+.````............------------::::hdhs+//////////////++++oossyyssssssssssyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhddddmmmmmmdddddddddddddddddddddddd
+//---:-.````````............-------------dmmmmmmddhdhhhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhdddmmmmmmmmmmmmmmmddddddddddddddddddddd
+`` ```````````...........-----------/syyhmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhdmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............----------::::+so+///////+oosyhdmmmmmmmmmmddhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhdmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ````````````............-------------:::::::::::::://///++oooo++//+++++++++++++ooosssyyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ````````````.``............-------------::::::::::::::///////////////+++oosssssyyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+-..````````````.:/+:...........:o/------------::::::::::::://////////++ossyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+oooo++///::::/+oooso...........dmmy:---------::::::::/++ssyhhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+oooooooooossssssssso...........mmmmmdssooooosssyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyyhddmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+...----::/+++++oooo+..........-dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddhhyyyyyyyyyyyyyyyyyhhdmmmmmmmmmmmmmmmmdhhdddddddddddddddddddddddddddddddddddddddddd
+...........-------:-......-----/sssssyssoooooooossyyyhhhddmmmmddhhyssssooooooooooossssssssyyyyyyyyyyyyyyyyyyyyyyyyssssyyyyyyyyyyyyyyyhhhddmmmmmmmmmmmmmmmmdhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+------------------------------------::::::::::::::///////++++++++++++++++++++++++ooooooooooooooooossssssssssssssssssyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyhddmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhhdmmmmmmmmmmmmmmddddhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhddmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssssssyssssssyyyyhdmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssydmmmmmmdddmmmmmmddhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssssssssssyhhhhhhmmmmmmdddhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssyhdddddddhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssydmddhyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssymmmmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssshddmmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssssssssssssshdmmmdhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssyhmmmmdyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssssssymmmmmyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssymmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssshmmmmmdhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssshmmmmmmdyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssyhmmmmmmmddhyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssshmmmmmmmmmmmdhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyhddmmmmmmmmmmddddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooooooooooooosssyyyyyyyyyyysssssssssssyyyyyhhddmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++oooossyhhddmmmmmmmmmmmmmmmmmmmdhyssssssyyyhhhdddmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhddmmmmddddddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////+++++++++++ooosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhddmmmmmmmmmmmmmddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++ooosssyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhddmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+.....-.````````````...........--------------::::::::::::::://///+oosyyhhhhhhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhdmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+++++ooo/ ```````````............-------------:::::::::::::+osyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+++++ooo: ````````````............--------ommdhyssssyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+.`..---``````````````............--------smmmmmmmmmmmmmdddddddddmmmmmmmdddhhyyyyhhhhhhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+-.``````````````...`..............-------:sysssyysoooo+++++++++ooossssssysyyhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+ooo+//::-..-::/+ooo-...........:ys/--------:::::::::/+osyhhdddddddhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmdddddddddddddddddddddddddddd
+++ooooooooossssssss:...........ommmdhs+::://+osyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+.....---://++++++++:..........-ommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddhhyyyyyyyyyyyyyyyyyyyhdmmmmmmmmmmmmmmmmdhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+..............-----.......-----:+oooossoo+++ooooooossyyyhhddddddhhyysssoooooooooossssssyyyyyyyyyyyyyyyyyyyyyyyyyssssssyyyyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddd
+-------------------------------------::::::::::::::////////++++++++++++++++++++++ooooooooooooooooossssssssssssssssssyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyhdmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyhdmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyhdmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhdmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooossssssssssssssydddddddddmmmmmmdhhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssyyyyyhhmmmmmmddhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooosssssssssssssssssyhdddddddhhhhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyydddhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyydmmmmdhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssyhdmmmmmhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssyyydmmmmdyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssydmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssymmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssymmmmdhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssssssshmmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssdmmmmmdyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssssydmmmmmmhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssssssydmmmmmmddhyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssyhmmmmmmmmmmdhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyhdmmmmmmmmmmmddhhhhhhyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyhddmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooooooooooooooooosssyyyyyyssssssssssssyyyyyyyyhhddmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++oooooooooooosyhddmmmmmmmmmmmmdhyyssssssyyyyyyhhhdddmmmmmmmmmmmmmmmdhhhhhhhhhhhhdmmmmmmdddddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooosyhdmmmmmmmmmmmmmmmmmmmmmmmdhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhdmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++ossyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhddmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////+++++++++++syhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////++++++osyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ````````````............-------------::::::::::::::////////++++oossyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///+ooyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+---..```````````````..............------------::::::::::::/+oshhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddd
+oooooo+::::-.```.................------------::::::::/++shdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhddddddddddddddddddddddddddddddddddddd
+ooosssooosssssooso+.............+so+/+++++ssyhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyhhddmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+-:/+++/://++++oosso...........--mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddhyyyyyyyyyyyyyyyyhddmmmmmmmmmmmmmmmmmhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+.....-.....----:///.......------mmhysyyysshmddysyyyhhhhddddmmmmmmddhhyyyysssssssyyyhhhhdddddddddddddhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyhhhddmmmmmmmmmmmmmmmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddd
+--------------------------------:::::::::::///:::////////++++++++++++++++++++++++ooooooooooossssssssssssssssssssssssyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmddddhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyyhdmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyhhdmmmmmmmmmmmddddhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyhddmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyydmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooosssssssssssssssyhhhhhhhhdmmmmmmddhyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssssyyhdddmmmmmmdddhhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooosssssssssssssssssshddmmmmmddhhhyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyhyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyymmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyydmmmmhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyydddmmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyhmmmmdhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssyyydmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssydmmmdyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssydmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssymmmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssssssshmmmmmmhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssshmmmmmmhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssssshmmmmmmdhhyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssssssyhmmmmmmmmmddhyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyhdmmmmmmmmmmmdhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyhdmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyhddmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyhhdmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooosyhddmmmmmmmddhyssssssssyyyyyyyhddmmmmmmmmmmmmmmmmmhhhhhhhhhhhddmmmmmmmmmdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooooosyhdmmmmmmmmmmmmmmmmmmmdhyyyyhhddmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhdmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooossyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhddmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oshddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++oydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++ooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///////////////++++oosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+..``````````````````..............------------:::::::::::::///////////++ossyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddd
+ooo++//::::-..```................------------:::::::::/osyhhhddhhhyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+oooooooooosssssoo+..............-+++//+++++++oosyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+-----::://+++ossss:...........--smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhhhyyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmdhhhhhhhhhhddddddddddddddddddddddddddddddddd
++/::-......--::+ss/.......------ymmmhyssssoossssyyyhhhhdmmmmmmmmmmmmmmmddyyyyyyhhhhdddddmmmmmmmmmmddddddhhhhhhyyyyyyyyyyyyyyyyyyyyhhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddd
+sssso+-----------:--------------sdo::::::::::::/++osyhmmmmmmmmddhysssoo++++++++oooooooooosssssssssssssssssssssssssssyyyyyyyyyyhdmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+ssssss/-------------------------------:::::oydmmmmmmmmmmmdhs+////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyyhdmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+:+oooo:--------------------------:::::::::smmmmmmmddhhyso/////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhhdmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+::::/:::::::::::::::::::::::::::::::::::::+mmmdysoo++///////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyyhdmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::/oo+///////////+++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhmmmmmmmddhhhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooooossssssssssssssssyhhhhdmmmmmmmmdhhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooossssssssssssssssyyhddmmmmmmdddhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssyhddmmdddhhhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyddddhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyhdmmmhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyymdddmmmdyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyhdmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyhdmmmdyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyhmmmdyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssydmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssymmmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssymmmmmmhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssssssshmmmmmmdyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssshmmmmmmmhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssssshmmmmmmmmdhhhyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssyhdmmmmmmmmmddhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyhdmmmmmmmmmmdddhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyhdmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyhddmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyhhdmmmmmmmmmmmmmmhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooosyhhdmmmmmmmmdhyssssssssyyyyyhhdmmmmmmmmmmmmmmmmmmmhhhhhhhhhdmmmmmmmmmmmmmddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooooooshdmmmmmmmmmmmmmmmmmmmdhyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++ooooooosydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++oohmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++ooosydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhddhdddddddddddddddddddddddddddddddd
+/::--..`````````````..............------------::::::::::/++ooooo+++/////++oossyyyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooo+/////:................------------:::/++osyhdmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+/++++ooooooosssss+..............-hmdhhhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhddddmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+........--:/+ossso............--:mmmmmmdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddhhyyyyyyyyyyyyhhddmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhddddddddddddddddddddddddddddddddd
+............-:/oss-.......------+mmmhs++////+++++ooooosssyyyyyyyhmmmmmmmmmmmmmmmmdhhhddddddddddddddhhhhhhyyyyyyyyyysssyyyyyyyyhhdddmmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+----------------/+--------------+md/::--:::::::::::://////////ohmmmmmmmmmmmmhysooooooooooooossssssssssssssssssssssssyyyyyyyddmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------------------------:/:---:::::::::::::///////++sdmmmmmmmmmmmhs++++ooooooooooooooooosssssssssssssssssssyyyyhdmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+//:------------------------------::::::::::::::://////++oydmmmmmdddhyyso+++++ooooooooooooooooosssssssssssssssssssyyyhdmmmmmmmmdddhhyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+sso+/::::::::::::::::::::::::::::::::::::::::///osssshhdmmmmdhysoo++++++++ooooooooooooooooosssssssssssssssssssyyyhdmmmmmmddhhhhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+yyyys/::::::::::::::::::::::::::::::::::::///oydmmmmmmmmmmyo++++++++++++ooooooooooooooooosssssssssssssssyhyyhdmmmmmmmdhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+syyyy+:::::::::::::::::::::::::::::::::////ommmmmmmmmmdyo+++++++++++++ooooooooooooooooossssssssssssssyydmmmmmmmmmdhhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+/+oso//////////:::::::::::::::::///////////hmmmmdhyso+++++++++++++oooooooooooooooooossssssssssssssssyddmmmmmddhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////smmhyo++++++++++++++oooooooooooooooooosssssssssssssssssssyyyhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+///////////////////////////////////////////+++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyhddddhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyhdmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyddhhmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssyyhddmmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyhhdmmmdyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyhmmmmyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssdmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssydmmmmdhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssymmmmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssssssssssssymmmmmmmyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssssssssymmmmmmmhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssssydmmmmmmmddhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssssssyhdmmmmmmmmmmddhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyhdmmmmmmmmmmmddhhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyhmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyhdmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyhdmmmmmmmmmmmmmdhhhhhhhhhhhddddddmmmdddddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++oooooooooooooooosyyhhdddddhhyssssssssssyyyyyyyhhdmmmmmmmmmmmmmmmmmhhhhhhhdmmmmmmmmmmmmmmmddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooossydmmmmmmmmmmmmmmmmdhyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmhhhhdmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooydmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+``` ```````````````............-------------::::::::::::::///////////////+++++++++oooosssydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhddddddddddddddddddddddddddddddddddddd
++//::--......```````..............------------:::::::::/+oossssooo++////++oosyyyyhhhdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+ooooooooooooooo++:...............-:::::----://+oosyyhddmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+/////++ooooosssss+..............-mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+.........-:/ossss/............---mmmmmmdddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddhhhhyyyyyhhhddmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+............-:+sso........------:mmmmyo///////++++ooooossssyysssssssssshhddmmmmmmmmmmmmmmmmmdddddddhhhhhhyyyyyyyyyysssyyyyyhddmmmmmmmmmmmmmmmmdddddddddddhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+---------------+s+--------------:mmh/:--::::::::::::///////////////+oydmmmmmmmmmmmmmmmdhysssssssssssssssssssssssssssyyyyhdmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+---------------------------------hs---::::::::::::://///////////++smmmmmmmmmmmmmmmdhsooooooooooossssssssssssssssssyyyhdmmmmmmmmmddhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////+oshmmmmmmmmmmdhyssooooooooooooossssssssssssssssyyyhhdmmmmmmdddhhyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////+oydmmmmmmmmmhysooooooooooooooossssssssssssssyyyhddmmmmmmmdhhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////++shmmmmmmmmhyoooooooooooooooooosssssssssssssshdmmmmmmmmddhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+//:::::::::::::::::::::::::::::::::::::////////////+/+++oymmmmmmmhso++ooooooooooooooooossssssssssssssdmmmmmmmmdyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+so+////////////:::::::::::::::::////////////////+syyyyhdmmmmdhyso+oooooooooooooooooosssssssssssssssssyhhhhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+yyso//////////////////////////////////////////+sdmmmmmmmmmdyso+oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+yyyy+///////////////////////////////////////+ymmmmmmmmmdyoooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
+yyyyo++++///////////////////////////////++++dmmmmmmmdyo+ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
++oso++++++++++++++++++++++++++++++++++++++++dmmmdhsoooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++sdhysoooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyddddhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyhmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssyhhhdmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyhhhdmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyhdmmmdyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssshmmmmyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssssssssssssshmmmmhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssdmmmmmhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssdmmmmmmyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssdmmmmmmhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssssydmmmmmmdhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssssyhdmmmmmmmmddhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssyydmmmmmmmmmmmmdhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyhddmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyhddmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyhhddmmmmmmmmmmmmdhhhhhhhhhddddmmmmmmdddhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyhddmmmmmmmmmmmmmhhhhhhhdmmmmmmmmmmmmmmmdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooooooooossyyhddddddddhyyyssssssssyyyyyyhdmmmmmmmmmmmmmmmmmmmhhhdmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooosyhmmmmmmmmmmmmmmmmmdhhyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooohmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooooosdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+`` ```````````````............-------------::::::::::::::///////////////++++++++++++ooossssshmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmddddddddddddddddddddddddddddd
+//::---.......``````..............------------::::::::::/+oooooo++////////++++oosssyyhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhddddhhddddddddddddddddddddddddddddd
+ooooooooooooooo+/-...............-::///::---:///+ossyhddmmmmmmmmmmddhyssyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
++++oooooooossssss/..............-mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+.......--:/osssss:............---dmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+...........-/osss/........-------ymmmmho++++++++oooooossssyyyyyyhhhhhhdddddhdhdddmmmmmmmmmmmmmmmmmmmmmdddhhhhyyyyyyyyyyyhhddmmmmmmmmmmmmmmddddddddddddhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+--------------+ss+---------------mmmd/::::::::::::::///////////+++++++++oooooooshmmmmmmmmmmmmmmhysssssssssssssssssssyydmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+---------------+s:---------------dmy:-::::::::::::://////////////++++++++oosydmmmmmmmmmmmmmmhysosssssssssssssssyyyydmmmmmmmmmddhyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+----------------:----------------+s::::::::::::://////////////+++++++oshddmmmmmmmmmmmmdhhyssoossssssssssssyyhhddmmmmmmmddhhyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////+++++++shdmmmmmmmmmmmmdhyssoooosssssssssssyhdddmmmmmmdddhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////++++++++odmmmmmmmmmmmdysssoooooossssssssssssymmmmmmmmdhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////++++++++oymmmmmmmmmmhsoooooooooosssssssssssssssyhhhhhhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////++++++++++sydmmmmmmddhyoooooooooosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++shdmmmmmdhysoooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++oydmmmmmdysoooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////+++++++++oyhhhyhmmmmmmhoooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+yso+++++++++++++++++++++++++++++++++++++++++++++smmmmmmmmmmdyoooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+hhyo++++++++++++++++++++++++++++++++++++++++++shmmmmmmmmdhysooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhho++++++++++++++++++++++++++++++++++++++++osmmmmmmmmhssoooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yhyoooooooooooooo++++++++++++++++++++++oooooommmmmmhyooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+osooooooooooooooooooooooooooooooooooooooooooodmmdhsoooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+oooooooooooooooooooooooooooooooooooooooooooooshysoosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssyhdddhyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssyhhdmmdhyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssshhhhdmmmdyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssyhdmmmmmmhyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssssssssyyhdmmdhyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooossssssssssssssssssssydmmmdyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssssydmmmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooossssssssssssssssydmmmmmmdhhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssshmmmmmmmmmmddhyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssshdmmmmmmmmmmmmdhhhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyhdddmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhddhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyhhdmmmmmmmmmmmmmmddhhhhhhhhhhddmmmmmmmmmdddhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyhdmmmmmmmmmmmmmhhhhhhhdmmmmmmmmmmmmmmmddddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooossssssssssssssssssssssyyyyyyyyyyhddmmmmmmmmmmmmmhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooosyyhhddmmmmdddhhyyssssssssyyyyhhhdmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooyhdmmmmmmmmmmmmmmmmddhyyssyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooosdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooooooosdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++++++++oooossssymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+//:::---.....```````..............------------:::::::::::/++++++//////////++++++++oossyyhhhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhdddddmmmddddddddddddddddddddddddddddddddd
+ooooooooooooooo+/-...............--:::::::---::/++ossyhddmmmmmmmmdhyso+/+osyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+oooooooooossssssso..............-mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+....----:/+ssssss:............---mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+..........-:ossss-........-------ymmmmmyo++ooooosssyyyhhhddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhddmmmmmmmmmmmmmddddddddmmmmmmmddhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+-------------/sss/---------------ymmmy/:::::::::::////////+++++++++++oossssoooossyyhdmmmmmmmmmmmmmmmhyssssssssssyyhdmmmmmmmmmmddhhyyyyyyyhhhhhdhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------:ss/---------------mmmo-::::::::::::://////////////++++++++++++++ooosdmmmmmmmmmmmmmdysssssssyyhdmmmmmmmmmmdhhyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+---------------/+----------------sdo:::::::::::://////////////+++++++++++++++oosydmmmmmmmmmmmddyssssssyhdmmmmmmmmmdddhyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::/+::::::::::///////////////+++++++++++++osyhhdmmmmmmmmmmmdhysssssssssdmmmmmmmdhhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++oydmmmmmmmmmmmmmdhysssssssssssssyhhhhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////++++++++++++osdmmmmmmmmmmmmmmdsosssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////++++++++++++++osdmmmmmmmmmmddhysssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oohmmmmmmmmmdhyssossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++oooymmmmmmmmmhsssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++oooooymmmmmmmmhyooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oooooosydmmmmmdhysossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooossssoshdmmmmdhysssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++oooooodmmmmmmmmmmdyssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+soooooooooooooooo++++++++++++++++++++++oooooooooohmmmmmmmmmdysssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hyoooooooooooooooooooooooooooooooooooooooooooooshmmmmmmmddyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhooooooooooooooooooooooooooooooooooooooooooooymmmmmmmdyysssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hysoooooooooooooooooooooooooooooooooooooooooosdmmmmmhssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooosssssdmmmhssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssydhsssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssyhhhyssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssdmmmmdyyssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooosssssssssssssyyhhmmmdhysssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssyhhhmmmmmdhyssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssssssssyyyymmmmhssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooosssssssssssssssdmmmmhyysyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossssssssssssssdmmmmmhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssshmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssymmmmmmmhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooossssssssssssssydmmmmmmmmmdhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssyddmmmmmmmmmmmddhhhhyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssyyhhdmmmmmmmmmmmmmdddhhyyhhhhhhhhhhhhddmmmmmmmddddhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyhddmmmmmmmmmmmmmmddhhhhhhhhdmmmmmmmmmmmmmmmdhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyhdmmmmmmmmmmmmmdhhhdmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooooosssyyyysssssssssssssssyyyyyyyyhhhdmmmmmmmmmmmmmdhhmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooooooosyhhdddmmmddddhhyssssssssyyyyyhhddmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooshmmmmmmmmmmmmmmmmmmhyssssyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooosdmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooosmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+//::----.......`````..............------------::::::::::://///////////////+++++++++++oossyyhhhdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmdddddddddddddddddddddddddd
+ooooooooooooooo+/:...............-:////::----:://++ossyhdmmmmmddhysoo////++oossyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhddddddddddddddddddddddddddddddddddddddddd
+oooooooooossssssso............../mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhdddddddddddddddddddddddddddddddd
+.-----:::/ossssss+............--/mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+..........-/sssss:........-------dmmmmmysoooossssyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddmmmmmmmmmmdhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+------------:osss:---------------hmmmm+::::::::::////////+++++++++ossyhhhhhyyyyhhddddmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmddhyyyyyyyyyyhhhhhhhdmmmmmdhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+--------------+ss/---------------mmmh/::::::::::::://////////////++++++++++++++oooooosdmmmmmmmmmmmmmmdddmmmmmmmmmddhhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+--------------:oo:---------------hmy:::::::::::://////////////+++++++++++++++ooooooshmmmmmmmmmmmmmdhysdmmmmmdddyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::+s/:::::::::///////////////++++++++++++++oooooooshmmmmmmmmmmmmdhysssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++oooooosydmmmmmmmmmmmmhysssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooosyhmmmmmmmmmmmmmdyssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++ooooshdmmmmmmmmmmmmmdyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++ooooohdmmmmmmmmmmmmddhysssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++oooooosmmmmmmmmmmmmdyssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooosmmmmmmmmmmdysssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooyhmmmmmmmmdhssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooydmmmmmmmdyyssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooosdmmmmmmdyssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooossssssdmmmmmmhssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+oooooooooooooooooooooooooooooooooooooooooooooooooosdmmmmdmmmmmdhsssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+oooooooooooooooooooooooooooooooooooooooooooooooooohmmmmmmmmmdhssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooosssshmmmmmmmmdysssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hssssssssssssssoooooooooooooooooooooooooosssssssdmmmmmmmdysssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ysssssssssssssssssssssssssssssssssssssssssssssshmmmmmdhyssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssdmmmdhyssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssshmmhyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssyhhhhyssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooossssssymmmmmmhsssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssyhdmmmmhysssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssyhhhmmmmmmdhysssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssyyyyyhmmmmdyssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssymmmmmmhssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssdmmmmmmhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssshmmmmmmmdhhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssyhmmmmmmmmmmddddhhyyyyyyyyyyyyhhhhhhhhhhhhddddddddddhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssyydmmmmmmmmmmmmmmmddhhyyyyyyhhhhhhhhhdmmmmmmmmmmmmmmdhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssyhhdmmmmmmmmmmmmmmmmddhhhhhhhhdmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyhhddmmmmmmmmmmmmmmmdhhhdmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyhdmmmmmmmmmmmmmmmdhhhhdddmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooosyhdmmmmmmddhysssssssssyyyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooosydmmmmmmmmmmmmmmmdyyyyyyyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooshmmmmmmmmmmmmmmmmmmmmmdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+/::---.......```````..............------------:::::::::::::///////////////++++++++++++++oosssyyyhhhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ooooooooooooooo+/:...............-://::------::::://+ossyhhhhhyyso+//////+++++++ossyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhdmmmmmmmmmmmmmmmdddddddddddddddddddddddddd
+ooooooooosssssssss:.............smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhdmmmmmmdddddddddddddddddddddddddddddddddd
+--::::///+osssssso-...........--smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhddddddddddddddddddddddddddddddddd
+..........:+sssss/........------:mmmmmmhsssssyyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+------------/ssss/---------------dmmmms::::::::////////++++ooosssyhddmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhddhhhhhhhhddhhddhhhhhmmmmmmmmmdhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+-------------:oss+---------------mmmm+::::::::::::://////////////++++++++++++++oooossssyhmmmmmmmmmmmmmmmmmddhhyssssyyyyyyyyyyyyyyyyyyyyhhhhdmmmmmdhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+--------------:ss/---------------mmd/::::::::::://////////////+++++++++++++++oooooooooydmmmmmmmmmmmmmmdhsssssssssyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::++::::::::::::::::smo:::::::::///////////////++++++++++++++ooooooooooshmmmmmmmmmmmmmmhyssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::/:::::::///////////////+++++++++++++++ooooooooooshmmmmmmmmmmmmmdysssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooosdmmmmmmmmmmmmdyssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++ooooooooossyhdmmmmmmmmmmmdhysssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooyhhdmmmmmmmmmmmdhhyssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++oooooooooohmmmmmmmmmmmmmmdyssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++oooooooooooshmmmmmmmmmmmmmhysssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooymmmmmmmmmmmdhyssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooshmmmmmmmmmdhysssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooymmmmmmmmmhyssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooosydmmmmmmmhyssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssyhmmmmmmdhssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+oooooooooooooooooooooooooooooooooooooooooooooooooooshdddhydmmmmmdhysssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooosssssshmmmmmmmmmmmhyssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssmmmmmmmmmmhyssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssydmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssdmmmmmhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyydmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyhmdhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooossyyyyyssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++ooooooooooooooooooooooydmmmddhsssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++oooooooooooooooooooosyhdmmmmmdhssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++oooooooooooooooooooohddhmmmmmmmdhyssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooossyyyyyydmmmmdhhyssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssydmmmmmmdhysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhddddddddhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooosssssssssshmmmmmmmmddhhhyyyyyyyyyyyyyyyyyyhhhhhhhhddmmmmmmmmmmmmddhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooosssssssssssshmmmmmmmmmmmmmmmmdhhhhhhyyyyyhhhhhhddmmmmmmmmmmmmmmmmmdhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooooooossssssssssssssyhdddmmmmmmmmmmmmmmmmmdddhhhhhhhddmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssyyyhhhddmmmmmmmmmmmmmmmmmddhhhhhhdddmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooooooosssssssssssssssssssyyyyyyyyyhdmmmmmmmmmmmmmmmmmdddhhddmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooossyddmmmmmddhyyssssssssyyyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddd
+``` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooosyhmmmmmmmmmmmmmmmdhhyyyyhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+////:::--------..```..............------------:::::::::::::///////////////+++++++++++++oosssyyyhhhhhdmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ooooooooooooooooo+:.............:+osooo++//////++ooosyyhddddddhhyso+/////++++++osyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhdmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+oooooooooosssssssso.............mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+..-----::/+sssssss:...........--hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhddddddddddddddddddddddddddddddddddddddddd
+..........-/ssssso........------/mmmmmmsooooooosssyyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddd
+------------:sssso---------------mmmmm+:::::::::::////////+++++ossyyhdmmmdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhyyhhdddddmmmmmmmmmmmmmmmddddmmmmmmmmmdhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+-------------:osso---------------mmmd/::::::::::::://////////////++++++++++++++ooooosssssyhmmmmmmmmmmmmmmmmhsssssssyyyyyyyyyyyyyyyyyyyyhhhhmmmmmmdhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+--------------:ss+--------------/mmd/::::::::::://////////////+++++++++++++++oooooooooosydmmmmmmmmmmmmmmdhyssssssyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::++::::::::::::::::ymo:::::::::///////////////++++++++++++++ooooooooooooydmmmmmmmmmmmmmmdhysssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::/:::::::///////////////+++++++++++++++oooooooooooosdmmmmmmmmmmmmmmhyssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooooosdmmmmmmmmmmmmmdhsssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++ooooooooooooosyhmmmmmmmmmmmmdhyssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooosyhhdmmmmmmmmmmmdhysssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooyhdmmmmmmmmmmmmmhyyssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++oooooooooooooshmmmmmmmmmmmmmmmhssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooshmmmmmmmmmmmmdhhyssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooydmmmmmmmmmmdhyssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooosshmmmmmmmmmmhysssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooosssymmmmmmmmmdysssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssydmmmmmmmdhyssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooossssssssydmmmmmmdhyssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooosssssssymmmmddmmmmmmhyysyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooosssssssssssmmmmmmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyydmmmmdyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyydmmdhyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhddyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++oooooooooooooooossyyyyysssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooooooooooooooydmmmmmdhyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++oooooooooooooooshdmmmmmmmmmdhysssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhdddmmdddhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooyhddmmmddmmmmmmdhyyysssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhdmmmmmmmmmmmmmddhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooooooossssssshdmmmmmmmdhhhhhyyyyyyyyyyyyyyyyyyyhhhhhdmmmmmmmmmmmmmmmmmmdhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooooooooossssssssssyhmmmmmmmmmmmmmmmdddddhhhhhyyyyhhhhhhhdddddmmmmmmmmmmmmmmddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooooooossssssssssssyyhdmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooooooooooooooossssssssssssssssyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmddddhhdmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooosyyhhhddddhhhyyyhhhddmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+//::---..........```..............------------:::::::::::::///////////////++++++++++++++oooooossssyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+ooooooooooooooooo+/.............:+oo+//::----:://///++ossyyhyyyso+///////++++++++oossyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+oooooooooosssssssss:...........ommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyssyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+---::::://+ossssss+-..........-+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+..........-/osssss:.......------ymmmmmmsssssssssyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhddddddmddddddddddddddddddddddddddddddddddd
+------------:ossss--------------smmmmd/:::::::::///////++++oossyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmm
+-------------:osss--------------ommmd:::::::::::::://////////////+++++ooo+++oosssssyyyyyyhhhdmmmmmmmmmmmmmmmmmhyhhddddmmmmmmmmmmmmddddddddmmmmmmmmdhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+--------------:sso:-------------ommd/::::::::::://////////////+++++++++++++++oooooooooooosydmmmmmmmmmmmmmmmdhysssyyyyyyyyyyyyyyyyyyyyhhhhhhddddddhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::oo/::::::::::::::/hm+:::::::::///////////////++++++++++++++oooooooooooooshdmmmmmmmmmmmmmmmdyyssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+:::::::::::::::::::::::::::::::::+y/::::::///////////////+++++++++++++++ooooooooooooooymmmmmmmmmmmmmmmmhyyssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooooooosdmmmmmmmmmmmmmmmhysssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++ooooooooooooooosyhmmmmmmmmmmmmmdhysssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooosydmmmmmmmmmmmmdhyysssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooosyhdmmmmmmmmmmmmdhyyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooosyhdmmmmmmmmmmmmmdysssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooosyhmmmmmmmmmmmmmmdhysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooshmmmmmmmmmmmmdhhyysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssmmmmmmmmmmmdhyysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssshmmmmmmmmmmhyssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssshmmmmmmmmddyysyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssshdmmmmmmdhhysyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssshhhhsymmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssmmmmmmmmmmmmhyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssssymmmmmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssydmmmmmmmhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyydmmmmmdyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyymmmmdyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyydmdhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhddmmmmmdddhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooossyyyyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhddddmmmmmmmmmmmmmmddhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooooosdmmmmmddhhyyyyyssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooooooooshdmdmmmmmmmmmmmmmddhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhdmmmmmmmmmmmdddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooossymmmmmmdhhmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+//::---..........```..............------------:::::::::::::///////////////++++++++++++++ooooooooosssdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+oooooooooooooooooo/:...........-/+o+///:-----:://///++ossyhhyyyso+///////+++++++++oossyyyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmhyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddd
+oooooooooossssssssso-.........:mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhysssyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+----:::://+osssssss/..........-hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhdmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+...........-+ssssso-......-----:mmmmmmhssssssssyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhdmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+-------------ossss+-------------dmmmms::::::::::///////++++oossyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhdddddmddddddddddddddddddddddddddddddddddmm
+--------------osss/-------------hmmmy-::::::::::::://////////////+++++oooooossyyyyyyyyyhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmm
+--------------:oss:-------------ymmh:::::::::::://////////////+++++++++++++++ooooooooooooooshmmmmmmmmmmmmmmmmdhyhhhhdddddddddddddhhhhhhhhdmmmmmmddhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::+s/::::::::::::::/mm/:::::::::///////////////++++++++++++++oooooooooooooooydmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+:::::::::::::::::::::::::::::::::os:::::::///////////////+++++++++++++++oooooooooooooooydmmmmmmmmmmmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooooooossdmmmmmmmmmmmmmmmmhysyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooosyhmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++ooooooooooooooooosydmmmmmmmmmmmmmddhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooosyhmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooossshdmmmmmmmmmmmmmmhyyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooosyhmmmmmmmmmmmmmmdhyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooosydmmmmmmmmmmmmddhhyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooosssshmmmmmmmmmmmdhyyysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssshmmmmmmmmmmmhysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssshmmmmmmmmmdhysyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssydmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooosssssssssddmdhhdmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooosssssssssssshmmmmmmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssssssdmmmmmmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssssshmmmmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyymmmmmmdhyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyymmmmmhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyymmmhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhdddmmmmmmmdddhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhdmmmmmmmmmmmmmmmmmddhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooyhddmdddhhhhhdddddmmmmmmddhhyyyyyyyyyyyyyyyyyyyhhhhhhdmmmmmmmmmmmmmmmmmmdhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooooooooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhhhhhhdmmmmmmmmmmmmdddddddddddddddddddddddddd
+``` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooshddmmmmmmmmddhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddhhhhmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+///:::----..--.....`..............------------:::::::::::::///////////////++++++++++++++ooooooooossyhdmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+ooooooooooooooooooo+:.........-+ossoo+//::://///++++ossyhddddhhys+///////++++++++oosssyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+ooooooooooossssssssso.........ymmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyyyhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+....----::/+ossssss+-.........+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+............:osssss:......-----smmmmmhoo++oooooossyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+--------------ossss------------/mmmmh:--::::::::::///////+++++ossyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhdmmmmmmmmmmmmmmddddddddddddddddddddddddddmm
+--------------:ssso-------------mmmd:-::::::::::::://////////////++++++++++osssssyyyyyyyyhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmm
+---------------/ss/-------------dmm/:::::::::::://////////////+++++++++++++++oooooooooooooosyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmdhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+::::::::::::::::+/::::::::::::::+mh::::::::::///////////////++++++++++++++ooooooooooooooosydmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhhhhddmmmmddhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::://:::::::///////////////+++++++++++++++oooooooooooooooshmmmmmmmmmmmmmmmmmmhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooooooooshmmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooosshdmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++ooooooooooooooooosyddmmmmmmmmmmmmmmdhhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++oooooooooooooooossydmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooosshdmmmmmmmmmmmmmmmdhyysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooyhdmmmmmmmmmmmmmmdhyysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooshmmmmmmmmmmmmmdhhyyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossshmmmmmmmmmmmmhyyyysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooosssshmmmmmmmmmmdhyssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssshmmmmmmmmddhyssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooossshdddhhhdmmmmmmdhyyysyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooosssssssssmmmmmmmmmmmmhyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooosssssssssssshmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssydmmmmmmmdyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssdmmmmmdhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyhmmmdyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyhmmhyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++oooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooooossssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooosyddmmmmdddddddddddddddhhhhyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhdddmmmmmmmdddhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhhhhhyyyyyyyyyyhhhhmmmmmmmmmmmmmmmmmmdhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++oooooooooossyddmmdhyssyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhdmmmmmmmmmmmmmmmmmmdhdddddddddddddddddddddddddd
+`` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooohyyyysssssssssssyyhhddddddmmmmmmmmmmmmmmmmmmmmmmmddhhhhddddmmmmmmmmmmmmddddddddddddddddddddddddddd
+///::----..........`..............------------:::::::::::::///////////////++++++++++++++ooooooooossyhdddmmmmmddddhyyssssssssyyyyyhhhhddmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+oooooooooooooooooooo/........./ossoo+//:::--:///+++osyhdddddddhys+///////++++++++oossyyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmdhysssyyyyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
++++ooooooooosssssssss/.......+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+......---::/+ossssss/-.......:hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddd
+............-:ossss+......----:mmmmmdo+++++++++ooossyyyhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+--------------:ssss/-----------smmmm/---:::::::::::///////++++++osyhddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmm
+---------------/sss:-----------ommm+--::::::::::::://////////////++++++++++oossssyyyyyyyyyyyyyyhhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhdmmmmmmmmmmmmmmmddddddddddddddddddddddddmmm
+----------------os+------------/dmy::::::::::::://////////////+++++++++++++++ooooooooooooooosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmm
+:::::::::::::::://::::::::::::::+h+::::::::::///////////////++++++++++++++ooooooooooooooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmdmmmdddddmmmmmmmmdhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+:::::::::::::::::::::::::::::::::/::::::::///////////////+++++++++++++++ooooooooooooooooydmmmmmmmmmmmmmmmmmmmhyyyyyyyyyyyyyyhhhhhhhhhhhhdmmmmmdhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooooosydmmmmmmmmmmmmmmmmmmdyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooosyhdmmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++ooooooooooooooossyhdmmmmmmmmmmmmmmmmdhhyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooosyhdmmmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooosshmmmmmmmmmmmmmmmmmddhyysyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooosydmmmmmmmmmmmmmmmddhyssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooshdmmmmmmmmmmmddhhyyysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooshmmmmmmmmmmmdhyysssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++oooooooooooooooossssssshmmmmmmmmmdhysssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooymmmmddmmmmmmmdhyysssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssdmmmmmmmmmmdhyssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssymmmmmmmmhyyysssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssmmmmmmdhysssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssssssssssssssssssssssssssssssssssssssshmmdhhysyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssdmdyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooooosyyysssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++ooooooshdmmmmmmmddddhhhhhhyyyyyyysssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooosyhhhhdmmmmmddmmmmmmmmmmmmdddhhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooooohdhhhysssssyhdmmmmmmmmmmmmmmmmmmmdddhhhyyyyyyyyhhhhhhhdddmmmmmmmdddhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssssyhdmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhmmmmmmmmmmmmmmmmmmddhhhdddddddddddddddddddddddddd
+``` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooossssssssssssssssssssyyhhhddddmmmmmmmmmmmmmmmmmmmmdddmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddd
++///::---.........................------------::::::::://+++//////////////++++++++++++++oooooooossyyhdddddddddhhhyssssssssssyyyyyyyyhhhdmmmmmmmmmmmmmmmmmdddddddmmmmmmmmmmmmdddddddddddddddddddddddddddd
+oooooooooooooooooooo+/......./ossoo+///::::///+ooosyyhdmmmmmmmdhys+//////+++++++ooossyyyhhhhddmmmmmmmmmmmmmmmmmmmmmdhhyssssyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmdddddddddddddddddddddddddd
+////++ooooooosssssssso:......mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhyyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+.........--::/osssss+:.......odmmmmmmdddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+............../sssss-.....----/mmmmmo+////////++++oooossyyyhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+---------------/ssso-----------mmmmo----:::::::::::://///////+++++osyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhdmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmm
+----------------+ss+-----------dmms---::::::::::::://////////////++++++++++++++oooosssssssssssyyhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhdmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmmm
+----------------/+/------------/hd:::::::::::::://////////////+++++++++++++++ooooooooooooooosyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhddddmmmmmmmmmmmddddddddddddddddddddddddmmmm
+::::::::::::::::::::::::::::::::/+:::::::::::///////////////++++++++++++++ooooooooooooooosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++oooooooooooooooshmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddhhhddddddhhdmmmmmmmmhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++ooooooooooooossydmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyyyhhhhhhhhhhdmmdddhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooosssyhdmmmmmmmmmmmmmmmmmmmmdhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooyyhhdddddmmmmmmmmmmmmmmmmmmddhhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooosdmmmmmmmmmmmmmmmmmmmmmmmdhhyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++oooooooooosydmmmmmmmmmmmmmmmmmmhyyyysssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooshmmmmmmmmmmmmmddhhyyysssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooosyysoosydmmmmmmmmmmddhyyysssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++oooooooooosmmmmmmmmmmmmmmdhhyssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooohmmmmmmmmmmdhyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooosmmmmmmmdhysssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooossdmmmdhyysssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssshmmysssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooosssssssssssyhsssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooosydmmmmmdhhyyysssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++ooooosyhhhddmmmmmmmmmmdddhhhhyyyysssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooooyhhhdhhyyyhddmmmmmmmmmmddhhhyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++ooooooooooosssssoossssssydmmmmmmmmmmmmmmmmmddhhyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssssshddmmmmmmmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhddddddhhhhhhhhhhdddddddddddddddddddddddddd
+` ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooooooossssssssssssssssyyhhhdddmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmddhhhhddddddddddddddddddddddddddd
+//::--...```````````..............------------:::::::::::::///////////////++++++++++++++oooooooooossyyhhhhhyysssssssssssssssyyyyyyyhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddd
+oooooooooooo++++////::.......-:::-:----------:://+oosyhdddddddhso+///////++++++++++oossssyyyyhhdmmmmmmmmmmmmmmmmddhysssssssyyyyyyyyyyhdmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddd
+/++++oooooooossssssssso-....ommmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmddhhyyhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddd
+........--:::/+ssssss+/...../hmmmmmmmmddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddd
+..............-/ssss+-....---:ymmmmy++++++++++++oooossyyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddd
+----------------+sss/---------ommmy:----:::::::::::://///////++++osyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmm
+-----------------ss+----------/mmm:---::::::::::::://////////////+++++++++++ossssyyyyyyyyhhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmmm
+-----------------/:------------/yo:::::::::::::://////////////+++++++++++++++ooooooooooooooossyyydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhdmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++ooooooooooooooosyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhhdddddmmmmmmmmmmddddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++ooooooooooooooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooosssydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhdddhhhhdmmmmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooosyyhhhhdddddmmmmmmmmmmmmmmmmmmmmmmmmdhhhdddmmmmmmddhhyhhhhhhhhhhhhhdddddhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhddmmmmmmddhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++oooooshmmmmmmmmmmmmmmmmmmmmddddddddhhyyyyyyyhdmmmmmmmhhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++osssooooshmmmmmmmmmmmmmmmddhhyyysssssssssyyyyyyyyymmmmmmmdyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++oosmmmmmdmmmmmmmmmddddhhyysssssssssssssyyyyyyyyyyyyyhdddhhyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooohmmmmmmmmddhhyyysssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++oooooooooymmmmmdhysssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooosmmdhsoossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooshyssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooooosyyyyysooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooydmmmmmmmmmddhyyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooosssyhdmmmdddmmmmddhhhyyyysssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooosyyyyyssssyhdmmmmmmmmmddhhyysyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooooooosssssyhmmmmmmmmmmmmmdddhhhyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssshdmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooooooossssssssssssssyyhhddddmmmmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+:--..```````````````..............------------:::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyyhhhdddmmmmmmmmmmmmmmmmdddddmmmmmmmmdddhhhhddddddddddddddddddddddddddddd
+ooooooo++//::::::-...............------------::::://+osyhhyyss+//////////++++++++++++++oossssyyyyhhddmmmmddhhyyssssssssssssyyyyyyyyyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhdddddddddddddddddddddddddddddd
+oooooooooooossssssssso+:...-oyhhyhhysssssssyhhddmmmmmmmmmmmmmmmmmddhyyyyyssyyhhhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhyyyyyyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddd
+...----:::///++osssssoo/...-dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddd
+..............-:ossss::-..--/ommmmdsooooooooooossyyhhhddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddd
+-----------------ssso---------hmmm/-----:::::::::////////+++++++osyyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmm
+-----------------/o+:---------odmo----::::::::::::://////////////++++++++oosyyhhhhhhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmm
+-------------------------------/+::::::::::::::://////////////+++++++++++++++oooooooooooooossyyyhhmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++++++oooooooooooooosyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhhdmmmmmmmmmmmmmmmmmddddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////+++++++++++++++oooooooooosyhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhdddddddmmmmmmmmmmdddddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////++++++++++++ooshdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++o++++++ossydmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddmmmmmmmmmmmmmmmddmmmmmmmdhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////+++++++ohdhhyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddhhhhhhhyyyydmmmmmmmmdddddhhhhhhhdddddhhhhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++hmmmmmmmmmmmmmmmmmmmmmdhhyyssssssyyyyhhhhhhyyyyyyyyyyyyyyyyyhmmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////+++++++++++++hmmmmmmmhhyyysssssoooossssssssssssssssssssyyyyyyyyyyyyyyyyyhdmmmmmmdhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ommdyysoooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyhddmmmmmdhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++oooooysoooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyhddmmmmmddhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyydmmmmmmmhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyydmmmmmmdhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhddddhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooooooosoooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++ooooshdmmmmmdhysooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooossssydmmmmmmdhyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++oooooooshhhddhhhddmmmmddhhyyyyssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++ooooooosssossooossyhdmmmmmmmmdddhyyssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooooooosssssydmmmmmmmmmmmmddhhhyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooosssssssssyhdmmmmmmmmmmmmmmmmdddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssyyhhddddmmmmmmmmmmmmmmmmmmddddhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+::-..```````````````..............------------:::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssssssssyyyyhhdddmmmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooo++//:::-----...............------------:::::/++osyhyyyso++/////////+++++++++++oosssyyyyyyyhhhhhhhhhyyysssssssssssssssyyyyyyyyyyyhdmmmmmmmmmmmmmmdhddddddmmmdddhhhhhhdddddddddddddddddddddddddddddd
+oooooooooooosssssssoo++/-..:osssyhhysssssssyhhdmmmmmmmmmmmmmmmmmmmddhhyyyyyhhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyysyyyyyyyyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddddddd
+..-----:::///+++osssssoo:..smmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddddd
+..............--:osss+::-.-:+ymmmdsoooooooooooosyyhdddmmmmmmmddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddd
+-----------------:os+--------:mmm+------::::::::://////++++++++++ossyyhhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddmm
+------------------------------:o+-----::::::::::::://////////////++++++++++ossyyyyhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddmmm
+---------------------------------::::::::::::::://////////////++++++++ooooooooooooooosssssyyhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////////+///++++++osyhdddddddhhhyhhdddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhdmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::////////////ommdhhyyyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhddddmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmmm
+::::::::::::::::::::::::::::::::::::::://////////////hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhddddddddddddmmmmmmddddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////++mmdddhhhyyyyhhhhddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddhhhddmmmmmmmmmmmmmmmmmmmmdddhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////+++++ohyooo+++++ooooooooosssssoooossssssyyhhhddddmmmmmddddddddddhhhhhhyyyhddmmmmmmmmmmmmmmddddddddhhhhdddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhmmmmmmmmmmmmddhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhdmmmmmmmmddhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhmmmmmmmdhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhdmmmmmmdhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhdmmmmmhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhdmmmmmdhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhddmmmmmdhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhdmmmmmmdhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhmmmmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhdmmmdhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddd
+ooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
++++++ooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddd
+++++++++++++++++++++oooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+/////////++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+/////////////////++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+////////////////////////+++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooooooooossssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::://////////////////////++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooooooooooooosssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+::::::::::::::////////////////////+++++++++++++++++++++++++++++++++++++++++oooooooooooooooooooooooooosssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+:::::::::::::::::::::////////////////////////+++++++++++++++++++++++++++++++++ooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+------:::::::::::::::::::://///////////////////////////+++++++++++++++++++++++++++ooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------:::::::::::::::::://////////////////////////////+++++++++++++++++++++++oooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+-------------------::::::::::::::::///////////////////////////////++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+.........---------------:::::::::::::::::://////////////////////////+++++++++++++++++++ooooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddd
+..............--------------::::::::::::::::::::///////////////////////++++++++++++++++++ooooooooooooooooooosssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+```...............-------------:::::::::::::::::::::////////////////////++++++++++++++++++oooossyyyyysooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddd
+`````````.............-------------::::::::::::::::::::///////////////////++++++++++++++++oooshhhhdmmmmdhysoossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddd
+`````````````............------------:::::::::::::::::::://////////////////++++++++++++++++ooooooosydmmmmmmmdhyssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````............-------------::::::::::::::::://///////////////++++++++++++++++ooooooshyyyyyyyhdmmmmmdhhhyyysssssssssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddd
+ ```````````...........--------------:::::::::::::::////////////////++++++++++++++++oooooooooooooooosyydmmmmmmmmddhhyysssyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ```````````............-------------:::::::::::::::///////////////+++++++++++++++oooooooooooooooooossssyhmmmmmmmmmmmmdhhyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddd
+ ````````````............-------------::::::::::::::///////////////+++++++++++++++ooooooooooooooooossssssssyhdmmmmmmmmmmmmmmmmddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddd
+ ```````````````............-------------::::::::::::::///////////////++++++++++++++ooooooooooooooooosssssssssssssyhddddmmmmmmmmmmmmmmmmmmdddddhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddd
+/::-..``````````````..............------------:::::::::::::///////////////++++++++++++++ooooooooooooooooossssssssssssssssssyyyyhhddmmmmmmmmmmmmmmmmmmdhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddd
+oooooooo++/::::-:--..............------------::://+oosyhhhhysso++////////+++++oosssyyyyhhhhhhhhddddddhhhhhyyyyyssssssssssssyyyyyyyyyyhdmmmmmmmmmmmmmmmhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddd
+ooooooooooooossssssso++/:..+sssyhhhysssyyhhhdmmmmmmmmmmmmmmmmmmmmmmmmmddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddhyyyyyyyyyyyyyyhdmmmmmmmmmmmmmmmmmmhhhddddddddddhhhhhdddddddddddddddddddddddddddddddd
+.....----::://+++ossssooo.:mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhhhddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddd
+...............---+oo+::-.-/+ymmdoo+++++++++ooosyyhdmmmmmmmdddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmddddddddddddddddddddddddddddddd
+------------------------------/+:-------:::::::::////+ooo++++++++++osshhdddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddddmm
+--------------------------------------::::::::::::://mmmmmmmmmdhyhddmmmmmmmmdhhyyyhddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddddmmm
+---------------------------------:::::::::::::::////smmmddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdmmmmmmmmmmmmmmmmmmmmmmdddddddddddddddddddddmmmm
+:::::::::::::::::::::::::::::::::::::::::::::///////oysoooooooossyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmdhhhddmmmmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmm
+::::::::::::::::::::::::::::::::::::::::::///////////////++++++++++oooshhddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhhhdddmmmmmmmmmmmmmmmmdddddddddddddddddmmmmmmmmm
+:::::::::::::::::::::::::::::::::::::::////////////////+++++++++++++++oooooooooooooosyhdmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmhhhdddddddddmmmmmmmmmmdddddddddddddddddmmmmmmmmmmm
+///////////////:::::::::::::::::///////////////////+++++++++++++++oooooooooooooooooosssssyhhdddmmmmmmmmmmmmmmmmmmmmmmmddhhhhhhddddmmmmmmmmmmmmmmmmmmmdhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmm
+///////////////////////////////////////////////++++++++++++++++oooooooooooooooooossssssssssssyyyyhhhhddddddddddddhhhhhyyyyhhhhhddmmmmmmmmmmmmmmmmdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmm
+////////////////////////////////////////////++++++++++++++++ooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhdmmmmmmmmmmmmmddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmm
++++++++++///////////////////////////////++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhddmmmmmmmmmmmddhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhdmmmmmmmmmdddhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmm
+++++++++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhdmmmmmmmddhhhhhhhhhhhddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmm
+oo++++++++++++++++++++++++++++++++++++++++++ooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhmmmmmmmdhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooo++++++++++++++++++++++ooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhdmmmmmdhhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhdmmmmdhhhhhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ooooooooooooooooooooooooooooooooooooooooooooooooooosssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhdmmmmmdhhhhhhhdddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssoooooooooooooooooooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhdmmmmmdhhhhhddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+sssssssssssssssoooooooooooooooooooooooooossssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhmmmmmmhhhhdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhdmmmmmmdhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhdmmmmmdddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ssssssssssssssssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyysssssssssssssssssssssssssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyssssssssssssssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhyyyyyyyyyyyyyhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddddddddddddddddddddddddddddddddddddddddddddddmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
diff --git a/p5js/console_animations/fire.txt b/p5js/console_animations/fire.txt
new file mode 100644
index 0000000..9da0696
--- /dev/null
+++ b/p5js/console_animations/fire.txt
@@ -0,0 +1,3600 @@
+
+
+
+
+
+
+
+
+
+
+ `
+ `
+ ```
+ `/` `` `+o:`
+ ``-h` `````` ``+hy.`````
+ ```+d.````````````.odh-...```
+ ````:hm-`````.....-+ydmh---...` ``
+ ````````````smm+`````....+hhdmm+.--...```` ` ` `.``
+ `````````````ymmh..`...../dddmmd-.:-..-.````` ````` ``
+ ````````````...ymdd+-...---+mmmmmh:-:-..::.````` ``` `
+ ` ```````````........+yoyy:------/dmmmdo/::-..:/.```` ` `` `
+ ````````````..........-----o/:::::::ymmmmso:/:--:+-.` ```` `
+ ` ``````````````...`.........-----:::::::///+mmmmmmy+/:::/:-`` ```` `
+ ```````````````.`...............----:::://///+++++dmmmmmmdo/:::::.` ``````
+ `.-``````````.........----.......---:::/oo///++++++ymmmmmmmh//:::-.`` `````` `
+ ``` `````-:..................-------------::::/ydyhs++////ommmmmmmd/:--::.``` `` ``.``` `
+ ``````````-o++-----------------::-------:://:/shdmmmhsoo+odmmmmmmmmo/////-..```` ````` `````` ```
+ `` ````` ```..-yhh/::::::::::::::::::::::://////+yddmmmmddhhmmmmmmmmmms++++/:-.``````` ```` ````````````` `
+ `` ```````...-/hddhys+:::/:///////////////////oyhmmmmmmmmmmmmmmmmmmmmo+++++/:.```````````` ``` ````````````` ` ``
+ ```````````..---:+hdmddho//+///////////////++/++ydddmmmmmmmmmmmmmmmmmmmooo++++:-`.`...```` `````````` ``` ``````````
+ ``````````..-------/ydmmdy//o++//////////////++ooshdhhmmmmmmmmmmmmmmmmmdsooo++/:-..`....``` `````````` ``` ```````````
+ `` ``````````...:::://::+ymmmdosyso+///////////////osyydmdmmmmmmmmmmmmmmmmmmsssoo+/:...``...``` ````````````` ```````````
+ ``` ` ```.`...```...-:///o+//+hdmmmddhs+//////////////////oyhdmmmmmmmmmmmmmmmmmmdsso+o/:-..``..`````` ````````````` `````````.`
+ ````````````....--::+yh:::ydmmmmo//o+/::::/::::-::://///+sydmmmmmmmmmmmmdmmmmd/:::/--.``````````` ```````````` `````````.`
+ ```````````` ````````..-:----::::/sms//+dmmmmms//+o++///+//////////++++oshdmmmmmmmdmddhmmmmmy//:::---.........` ````````` `` ``````````````````` ``
+ ``````````` ` ` `````..---:+ooo++o++ydm+++smmmmmms///osoo++/////////++osysoydmdmmmdddhhyyhmmmmhhso///:------...` ``````````` `.```````````````````````
+ ````````````` ` ````.....--/+sssyyhhdmmmo++ymmmmmms+//oyyso++os+/+++/++syhssdmddmmmdhhhyysymmmmysso//:-.....```` `..` `````.````````````````````
+ ````````````` ` ``````...--:/+ooshdmmmmmmsoyhmmmmmmh+//ohdhyo++hhyossooysshdhhhhdmmmhdhsoo+oyosy////---/:...````` ```` ` ` `` `````.`` `````````````````
+ ```````````````` ` ``````..-//++oossdmmmmmmmdmmmmmmmdmmd+/odmmmdyyhhdydhsooyoyyysoosmmmsy+:-...-:/+///++-../s+:````````` ` ``````` `````.` `````````````````
+ ``````````` `` `` ```````.-://++soohmmmmmmmmmmmmmmmyhdddhyhmddddddhhd+/::+s///++oohmmmsyo:::://:/::-----...-:-...` ``````` `` `````.`` ``.`````````````
+ ``````````` `` ````````.--::+s++oso::/+syyyssooo/::---.+yyhyyyyo/++//:--.....-/hymmsss.``` `--.` `` `.. ``` `.```.````...````````````
+ ``````...` `` ````..-//..```` `:- `o/sdyys:`` `.-so+ddhyy- .-..` `` `````..``...`````````````
+ `````````` ```` ``````````...-:. `+: -``-+-sdhs/. .os-+-+yo::s-.``..--.....` `` `````````````````````````` `
+ ````` ```````````.....--:- .oo.````..`.`/-`.-:sdy+.` `..--.`..--.....```` `--..`` ` `````````````````````` `
+ `````````` ```````````.....`.-- .sso///+o/--.--``.+yds:.` ` ..``` ``....``````````
+ `````````` ```````````.....``-- `osyysooyo+oooooyhmdh+::.` ``......``````
+ ````````` ````````````..-///-- `` ``.:hdddddmmddmhsymmmoo--yo... `.......`````
+ ```````` ````````````..`-+o/+/``.``.:+ohmddmdhsdddmy/dmm+:+.`oy-+/` `.......```````
+ ` ```````` ``````````` `.:ossy+-.:---::/hd/::--h+smy--y/.:::-sh:ss:.`````.. ````` ``` ` `....`.....```
+ ````.`````````` ..:+sy+s+----:/:-/s///.`` .ss.:+/.:/++smhhhysssyys+:. ```` ` `` `..` `...``
+ ```.`````````` `../+so+o:::..::.-.-:::: -s+:+ssyy//osyo:-..-/o/--` ````` `` ```..``
+ ``` ````````` `..:oo/` ` `-/:--:/+/: ::o+oyo/-+oooo+::+/.` ``..`` `` ```````
+ ```` `..````` `..:/ .-.//.`-+oo+. oso+ooo+oooo++oo: .. ` `.` ` ````````
+ ``` ``` ``` .-://.```//: -//++:-`.:---:.` .-: `.` `` ```````
+ ``````` `````` ...+s+////+` .-... `-.` `.` ``.--`..`...` ```````````
+ ```````` ```` `````` ` ...-/+++:-:. `.`` ``` ` `::/-.````` ` ```````````
+ `` ```...---.`.` ```` `` `````````
+ ` ````
+ `
+ ````
+
+
+
+
+
+
+
+
+ `.`` `
+ `::-.
+ -o+:.` `` ``
+ ```` `oss+:````` ``
+ ``````/yyys/`````` `
+ ``````.yhhhh-``````` `
+ `` ``````````.ohhddh.``.``.` `
+ ```````````....+hddddo``..``..` `
+ ````````.`......oddddyy-.....-.``````` ``` ` ````
+ ````````````.`..........ohddsydh-...-:-```` ````` `.``` ` ```
+ ````````````.............:/ydhdmd/--.-/:.```` `````` ` ```
+ ` ````````````....---------::+//ydmmm/::-.::-`````` ````` ```
+ ````````````........----:::::/o+sdhyhmmmms+:---::.````` ````` ```
+ ```````````........----::://+ohhsdmmmmmmmmdy+:-----.`` ````` ``
+ ````````````````...`........---:ohosydmmhsdmmmmmmmmyh+/:----..` ````` ```
+ `````````````.``.............----::/ymmmmmmdsdmmmmmmmdsy+//::::-`` ` ``````` `` ``
+ ``.````````........-----......---::://hmmmmmdhdmmmmmmmmdy++////:-``` ``` ```````` ``` ``
+ ```````.-................------------::::://odmmmmddmmmmmmmmms///:::::..`` ``````` ``.``````````````
+ ```````````......--------------:------:::://:://+odmmmmmmmmmmmmmmy+++///:::--..````````` `````````````````````` ``
+ `````` ````...---::::::::::::::::::::::////+/::++sdmmmmmmmmmmmmmmmdsooo++///:-..```` ```` ```` `````````````` `````
+ ````````````...-----::::::::::::/://////////+/+///+oyhdmmmmmmmmmmmmmmmssooo++++:....`.````` ``` `````````````` ``````````
+ ```````````...-----::::::::////////////////++////oooosymmmmmmmmmmmmmmmyssoo++++:......```` `````````````` ```````````
+ `````` ```..-----.-:/+///////////+/////////++++o/+ysssshmmmmmmmmmmmmmmmyyssooo++--.......``` `````````````` ```````````
+ `` `````````````..:////::/oy+//////////o////////+////o/ohyssydmmmmmmmmmmmmmmmhyysooo/:--.......``` ````````````` ```````````
+ ``` ```````````...-:/ss/shhyhs/////////+o+//////////////ydyyyhmmmmmmmmmmmmmmmdysssoo+/-..``..`````` ```..```````` ````````..`
+ ```````.......---:yh:dmmddy:::::::::os+//::::::::///ohdhyyhmmmmmmmmmmmmmmmdyyso///:.```````````` `` ````````````` ````......`
+ ```````````` ```````...-//:/+/:::+dd/dmmmmd/////:::/oys++/////////++shhhhydmmmmdmmmddmmmmmmmmdyo/+/:--........` ````````````` `````````````````````````
+ ` ``````````` ` ` ``````..--:/+oshds+/oddsmmmmmmy+++/:/++shho+////++//+++syhhhyhdmmmddddhhhmmmmmmmmyyh+:::----...` ```````````` `.```.```````````````````
+ ````````````` ` `````....-:/++osmmmdosmmdmmmmmmmdoo//hddddhs+++++++/++++syyyyyyymmmdhyyhyyhmmmdhyyo+s+:-.-..```` `..` ``````` `.```.````..``````````````
+ ````````````` ` ``````...-::/+//+mmmyydmmmmmmmmmmmmd+/ommmmmmys++++++sssssssssyssmmmddhhysosyysso+/::-/dy---.```` ```` ``````` `.```.````..````````````.`
+ ```````````````` ` ``````....://++++dh+hmmmmmmmmmmmmmmmmddmmmmmmmdsoyoshysssoooo+yydmmmmdoy+-..-/+oo+++/-.:/so:-.``````` ` ```````` `..``.`` `..``````````````
+ ``````````` `` `` ```````....-:+o++ds+ddmmmmmmmmmmdhdmdddhdddmmmmdddh+/::::://++osydmmmdyhs//////::-----...--:--.````````` ``` `..`..`````..`````````````
+ ``````````` `` ````````..-:++++s+:-:++syysssoo+//::::--:ymmdh/o++/:----.....-/hhhmddms.`````.-.`` ``.. ``` `..`..```.....```````````
+ ``````...` `` ````..-:.```` .-` `.```` /sdhy:``` `` `+hy+yhyhd-` `-..` ````` ````..........```````````
+ `````````` ```` ``````````....` -/. `-/:--..```.ysds/.`` `o+` `:/o:/so+os-.``.-:--....`` `` `````````````````...``````````
+ ````` ````````````.....--- :+:-..-/oo/+--```-yhyy+-```` ```.``..`..--.....`````` `:--.`` `` ````````....``````````` ````
+ `````````` ```````````....``..- `o+/ooooss-/-+`./hmdyo-```-.` ` .```` `..........``````
+ `````````` ```````````.....``-- :ssyhhyyo:+oysdmmmmy+.``++-. ``..........`````
+ ````````` ````````````..-://-- `` ``..yddmmmmdmmmddmmmmh//-.-y:/. ``..........``````
+ ```````` `````````````.`-+o/++``.`.:/+sdmmmmhhmmdmmmmmd+/:...so.o. ``..........`````
+ ` ```````` ``````````` `.:ossy+-.--.-::/hd/::+md/smdssd/-://:yy-s+:.`````.. ````` ``` `` `...........`````
+ ````..````````` `./+ss+s+----///-/y///:o. .os-+o+.://+ymhhhysossys+:. ```` ` `` `... `....``
+ `````````````` `../+so+o:::.-/:.--:::+/ .so:+soys-/osys:...-+o/--` ````` ``` `....``
+ ``` ````````` `..:oo:` ` `-/:--:/+// ::o+os+/-+oooo+::+/.` ``..`` `` ````.`` `
+ ```` `..````` `.-:/ .-./+.`-+oo+. osooooo/+ooo++oo/ .. ` `.` ` ````````
+ `` ``` ``` .:://.```//: -++oo/-.-/---:-. .-: `.` ``` `````````
+ ``````` `````` -..+so////+` -:-.-` .:-. ..` ``.--`..`...` ``````.`````
+ ```````` ```` `````` ` ` .-.-+++o/:/. `..`. ``` ` `://-.````` `````````````
+ `` ````..-----..` ````` ` `` ``````````
+ ` ````
+ `
+ ```
+
+
+
+
+
+
+ `
+ ``
+ ` `
+ ``
+ ..` ``` ``
+ ` .:-``````` ``
+ ``` .+/.`````` `
+ ``````` ``-``.os/`````.` `
+ ``````````````/-``oys.```..` `
+ ```````.+o+-```.`//.`+hh:```.-```` `
+ ````````.sdmd+..--:s/.:hh:``..-.``````` `` ` ```
+ ` ````````````....sdmmdy//+:hs-sdy-````.-```` ````` `.``` ` ```
+ ` `````````````.....ohmmmhhhhodhodd+......-````` `````` ` ```
+ ` ``````````````...----ohmmmdhdddddhdd/.-....-.`````` ````` ```
+ `````````````........---::+hmmmmdmmmmddmd+-:---..-`````` ````` ```
+ ````````````.......-----:::+hmmmmmmmmmmmmdo:+/:-----.` ````` ``
+ ````````````````...`.......-----:://ymmmmmmmmmmmmmhsys/:::::-`` ` ````` ```
+ `````````````.`..............----::///+ymmmmmmmmdmmmmmmmd+//:::-.` ``` ``````` ``` ``
+ ```````````........----.......---::/o+osdmmmmmmmmdmddmmmmd++//:-...`` ````` ```````` ``````
+ ```````.................-------------:::+oosydmmmmmmmddmdymmmmd+/::-----..` `````` ``.``````````````
+ ````````-/+-..-----------------------::::/+osshdmmmmmmmmmdmmddmmmdo++/::::---.```` ``` ````````````````````` ``
+ `````` ``.:hd+--:::::::::::::::::::::::////+osysddmmmmmdmmmddmmmmmmhsoo++//:-.-.```` `` ```` `````````````` `````
+ ````````.-hdh//::::::::::::://///////////+oosyyddmmmmmmmmmddmmmmmmhsooo+++/-....`.```` `````````````` ``````````
+ `` `` ````...-/dms+/:::::://///////////////++/ooshhmddmmmmmmmmmmmmmmmmysssoo++/:......```` `````````````` ```````````
+ `````` ```..----dmds////////////////////+++++++sosydmddmmmmmmmmmmmmmmmdyyssoo++:--.......``` `````````````` ```````````
+ `` ```````````..:///smmh////////////++//////++++///sooydddhdmmmmmmmmmmmmmmyssssso+:-...`.....``` ````````````` ```````````
+ ``` ```````.```...-:+s++dmh///+///////++so+++/////////+++hdddhhdmmmmmmmmmmmmhsooooo++:-..``..`````` ````````````` ````````..`
+ ````..-:::...--:shy/hmd//::::::::::/syhy+/::::::///+oddhhyshmmmmmmmmmmmmm+/o://::::-.````````` ````````````` `````.....`
+ ```````````` ``````.---://///:::ohddshmmo/+///+//////ohhs++///////+++shdhysshmdmmmmmmmmmmmsshhhy+:/:--........` `````````````` `````````````````````````
+ ` ``````````` ` ` `````..-:://+++++/:ymmmddmmh++++++++oyhhddho+++++++/+++osyhhyssymdmmddddmmmmmhyhdhhy+/::----...` ```````````` `.```.```````````````````
+ ````````````` ` ``````...::///++///+dmmmmmmmd++++o+odmmmmmmho+++++++++++oosyhhssymmmddyyyhdmmmdysooo/hs:.-...``` `..` ``` `` `.```.````````````````````
+ ````````````` ` `````.....:::///+///ymmmmmmmmhooosooodmmmmmmmyo++++++++osssssssssdmmdyhyhyoyhssho/:---:hh/----..` ```` ` `` `.```.``````````````````.`
+ ```````````````` ` `````````.---//+++++dmmmmmmmmhyoohddmmmmmmmmmmsoyddmhyyssoooo+oshmmdhhddd/..:/+ooo//:..-:+/--...``````` ``` ``` `.```.`` ``.``````````````
+ ``````````` `` `` `````````..-:+++++++ddmmmmmmmmmyshdmmddhyhhdhyssosoo+/:::://+++oymddmmddy//////////::---.-----.````````` ```` ``.``.`````.`````````````
+ ``````````` `` ```````...-:+/++//:-:++osyssoso+/s+:::-:ssy+++/+/::------/:..-/dhdmmdds..````.--.``.. ``..` ``` `.```.````...````````````
+ ``````...` `` ````..-:--.``` `.``-s-` .y/+-`````.` `:+- .ysyddhhh:`` `.-..```` `.` `````..`.....````````````
+ `````````` ```` ````````.....-` `--``:o-` `-ys::.`` -/:.` -+/.`-/::ooy++y:.``.-:--....` ` ``````````````````````````````
+ ````` ```````````.....---- `` ``.--.:+/+.``:yho/-.` /o+:` ````.--.......```` `:--.`` `` `````````..``````````` ```
+ `````````` ```````````.....`..- `/+++/-/oso+/:/+hddso:.`/yo-` ` ..``` ``.....````````
+ ````````` ```````````.....``-- .oyso++yhysssdmmmmmdho:.ys-`` ``......``````
+ ````````` ````````````..-///-- `` `.-yhhhhdmmmmmmmmmmmdh+:--h/.`` ``.......`````
+ ```````` ```````````````-+o/++``:+ooosydmmdddmmmmdhmdmd+/--.-h:`. `.......`````
+ ` ```````` ``````````` `.:ossy+-.---:://yd/:/yms::+dyyd+-/++/ys-+/-.`````.. ````` ``` `` `....`...````
+ ````.`````````` `../osy+s+----/+/:/y//+s+. .os:os+-/+++yddhhssossys+:. `````` `` `..` `````
+ `````````````` `--/+so+o:::.-//---:::s+ -so/+soyy-/osys+-..-/o/--` `````` ``` ``````
+ ``` ````````` `` .--/oo/` . `-+/:-:/+/: ::o+os+/-+oooo+::+/.` ``-.`` `` ``````
+ ```` `..````` ``` `--// -:-++.`-oooo. osoosoo++ooo++oo/ .. ` `.` ` ` ``
+ ``` `.. ``` -//+/.```//: -ooss/:.-/--::-. .-: `.` ````` ```````
+ ``````` `````` :--oso+//+o` -::-:` .:-. ..` ``.--`..`...` ` `````````
+ ```````` ```` ```````` ``-:-:+ooo+//- `.-..` `.. ` `://-.````` ```````````
+ ``` `..`---:::-.-.` ``..` `` ```````
+ ` ``
+ `
+ ````
+
+
+
+
+
+ `
+ ``
+ `..`
+ ```-:` `
+ ````-/-
+ ````:+/` ` ``` ``
+ `````/oo. ` ``` ``
+ ``````+ss: `` ```` `..`` `
+ `````.syyo`-/:::::-`` -o+:/` `
+ ` ``..``.oyss.:ssssss+::/so+o: ``
+ ` ```..`..-+/--/yhhhhyyssysoyo``` `
+ ` ````.....-/:../hddddhyyhysys:``` `` ` ```
+ ``````````.-+:..-o/../hdmddhhhhshy+````` ```` `.``` ` `
+ ` ```````````.//oo::/yo::ohdmddhhhyhyo-``.``` ````` ``
+ ` ````````````.-:syyyssyhs++shdmdhhysyy+-....``` ````` ``
+ ```` `````````````....-/+shddddddhsshddddhyhddo-:--....`` ````` ``
+ `.-. `````````.........-+oyhddmmmdhyodddhhyodddd+//:-....` ` ````` `
+ `-::` ````````````````...`.....--/oshddddddhyddddysshmdddd+/:--....`` ````` `
+ `:++.```````````.`............---:oshdddddddhdmdhhyymmmdddo+::--....` ```````
+ -os-````````........------------:ssyddddmmdhdmdyyyddmmddds//::--.`..`` ```````` `` `
+ ````.sy:................-------------oyyhdddmmddmmdysosdmddddo/::--....-.` ``.``` `````
+ ```````/s-.....-------------:::::::::::+ssyhddmmmdmmmddyydmmmmdo++//:---:-.```` ``` ``````````````
+ ` ``` ```.-:.----::::::::::::///////////++oosydddmddmmmmmddmmmmmdsoooo+/:::-`````` `````````````` ```
+ ``````...:-----::::::::::://////++++++++oooydddmmdmmmmmmmmmmmmdsossooo+/:.``````` `` ````````````` ````` ```
+ `````.----:--:::::::///////////+++++++++++oyddddmmmmmmmmmmmmmmmsooooooo+:...`...```` `````````````` ```````````
+ ``..-:---..-::::////////o++//++++++++ooooyhdddhdmmmmmmmmmmmmmmsoooooo++-...`.....`` ````````````` ```````````
+ `` ``````````..:++::::://////+++/+yhyso+++++++++++oohddddhhdmmmmmmmmmmmmmsoo+++++:-.-.``...``` ````````````` ```````````
+ ``` `````..-.....-:oy+/:://///++++++yhdhyso++++++++//+oydhddhyhmmmmmmmmmmmmdsdh++++//:--.``.`` `` ````````````` `````````.`
+ ```...-:::-----ohhy/::::/:::://sdddddhso////::::::/oshhhyyyshmmmmmmmmmmmo/dmy:------.```` ```` ````````````` ```````...`
+ ````````` ` ````..----:::///:sdddho://+/////+ohdmmmmdyo++////////+osyhyyhhsymmmdmmmmmmmssdmds:---::-........` ```````` `````````````````````````
+ ` `````````` ` ` ````..---:////:::ddmmdo//ohoooooyhddmmmmds++++++++++++osyyhhddyymmdhyhdmmmmyhddys/so:::-------. ``````` `````````````````````````
+ ````````````` ` ```````.----:////:+dmmmhoosydydmmddmmmmmmmdo++++++oys++oossyyhdhydmmhhydddmmmhdhyo/:+dy:-------.` `..` `````.````````````````````
+ ````````````` ` ```````..-...-/////ymmmmdhyhhdddmmmmmmmmmmmmd+++++smdyssssyyyyyssdmmdyddmhoyhs+oo+//.:hho::----.` ```` ``````` `````````````````
+ ``````````````` ` `````````...:/++//ohmmmmdhyhdmmmmmmmdddhyhddhy+ohdmhysssssosysoohmmdysdmd:.-:/+++o++/-:/+/-..-..``````` `` `` `````.` `````````````````
+ ``````````` `` `` `````````..-/+++++yhddmmdhhhmmmmmmmdysssshsoooosoddyo//+::/++++oddyyshdds///+//:/++//------.--.````````` `` `````.``````````` ```````
+ ``````````` `` ```````...-://++so/--//+sssssyyhy//:---------:/yhys+/:--.--:--shhhddmdo..````...-..-- ..` ``` `````.````..`````````````
+ ``````...` `` ``....-:--.`` `:s+s/`` `` `syo:.` `..:syhddddh:``` `.--...:` `.` `````.``....`````````````
+ `````````` ```` ````````.....-` -oyhoo.`` ``` `yho-.` `.---/osso+h/-`..-:--....` ` ``````````````````````` `
+ ````` ````````````....---- .shddo/.```````` `sho.`` `````.--...-...```` .:--.`` `` `````````````````````
+ `````````` ```````````....``..- `..-hdddy/-.-:-...```-dy.`` ` ..``` ``....````````
+ ` ``````` ```````````.....``-- `/+::ddmmdyooddhooss+//do``` ``.....```````
+ ` ``````` ````````````..-///-- -`` ``..+yo+ddmmmmmmmmdmmhhy+-/y-`` `.......`````
+ ``````` ```````````````-+o/++``/+osssydmdhhdhmmmddmdmh+/-...y/`` `.......`````
+ ` ```````` ``````````` `.:ossy+-.---://+hd/:o/yds+ddyhdo-//+:oy://-.`````.. ````` ``` ```` `....`..`````
+ `````````````` `../osy+s+----+++:+s:/o/.. .oy:oso-/+++oddhdysosyys/:. ``````` ``` `..` `````
+ `````````````` `--/+so+o:::.-+/-:-:::+- -so:+osyh+/ossoo:..-/o/--` `````` ``` ``````
+ ``` ````````` `` ..-:oo/` .``:+/:-//+/: ::o+oyo/-+oooo+::+/-` ``-.`` `` ``````
+ ```` `..````` ``` `--// .:-++.`-oooo. osoosss++ooo++oo/ .. ` `.` ` ` ``
+ `` `.. ``` .//+/.```//: -ooss/:.-/---:-. .-: `.` ````` ```````
+ ``````` ` `````` :.-oso///+o` -::-:` .:-. ..` ``.--`..`...` ` `````````
+ ```````` ```` ```````` ``-:-:+ooo+//- `.-..` `.` ` `://-`````` ```````````
+ `` `.``---:::-.-.` ``..` `` ```````
+ ` ``
+ `
+ `
+
+
+ `
+ `
+ `
+ ``
+ ``
+ ```
+ ``` `
+ ``` `.``
+ ``` `---.
+ ``` `-:-/
+ ...`` ``+`
+ .+/-.` `:`
+ .os+:.` `` `
+ `-oys++-` `:.
+ `./+yyoos.`````````` `/s-
+ `````-/+yhysys...```````` `-+yh. ```
+ ` ```````.:+oyhhhhyy+-.````````+ydh-````` ``
+ ` ``````````.-:/:+shhddy/+........ohdd+.```` ``
+ ```````````````.....-/yyhhd+:s--......+syhs-.```` ``
+ ````````````........../o+hyh///sso-------:/::..```` ``
+ ```` ```````````...`.........-::/yhyo+oddd+::/::::-.--..````` `
+ `````````````.``...............-:///sddho+hmmds/s+/:::----....``` ``
+ ```````````........-------.....--:yyosddmh/+mmmmdyys//:--::--...``` ````
+ ```````.................--------.------yhysddmms+hmmmmmddos:---------.``` ```
+ ```````......-----------------:::---:::::sddyhdmmmddmmmmmmmddo:::::::::-.```` ``
+ ````````....----::::::::::::::::///::://///shdhhhdmmmmmmmmmmmdso///:/::::--````` ```
+ ```````....-:::::::::::/::/++//////////////shdhhhdmmmmmmmmmmmmh++/////:::--` `````` ` `
+ ````````..----:-:/:::////////oso/////////++//oydhhhhdmmmmmmmmmmmd+++//////:--````````` `````` `
+ ``````..-:+++---://////+sso+/+oo+++//+++++/++/ohhhyyhmmmmmmmmmmmmo+++/////:--.```````` `````` ```
+ `` ``````.....---shh//::/++///++hdhys++++++/+++/////+:/yhhysydmmmmmmmmmmms+oo+////:-..````````` ``````` `````````
+ ``` ````...-:::::::+ddhyo//+o+++++/ommmdo+++++//++//////::ohhyyydmmmmmmmmmmmmohd+/::/:-.``````` ```````````` ``````````
+ ````...-::::::::hddydddhhy+/::::/dmmddo//+////:::://///+yhyyydmmmmdhhdmmmmyhd/-----..```` ``````` `````````
+ ```````````` ```..----:/:::::/dddsshdddddhs+/+ohdmmmh+++++////////+//+syyyydmmmmdyydmmmmdhhd+----.-...```...` ``````````
+ ````````````` ` ` ````.....-:::::::sdddy++hdmmmmdddhoymmddh++++++++o+o+++++oshysydmmmmdyhmhmmmyyshd+------------.` ``` `````````````
+ ````````````` ` ```````....--/+////hmmdhyoohdmmmmmmmh+shoo++++++++omssooooosyysssmmmmdddmmsdmmhsssys:::-...--...`` `.` ``````````````` ```````
+ `````````````` ` ```````....-:oo+++ohdmmddoosdmmmmmmmmh+oo++++++++smmssyooooosooosmmddhdmmhosdso++soo:s:.....````` ``` `````` ````` ``````
+ ```````````````` ` ```````...-:+ssoosshdmmmdosydmmmmhdmmdsooo+++++sdmmmmyyo++++o+ooydmyssddd:--::+oo++o:////...```.```` ` `````` ```` `````
+ ``````````` `` `` ```````.---:/ssyyhyyddmmdsydmmmmmdyddhyhyo++/+shddmdds/:::://++osddsshdds//////++///+...`..`...` ` `````` ````` `````
+ ``````````` `` ```````.-:-:/++ssso/:://o+yhdddso+/::---...../yyyysso+:--.....-:ohshdmdo.`.``.-:-..-/- `` ``````````````` `
+ ``````...` `` ` ````...:::--..` `oohdy. ``` `yy/.``` ``-oyyhddhd:``.` `--.....:` ` ```````````````
+ `````````` ```` `````````....--. `yhdds:```` ` .h/. `/o-:+s+++h/-`..---.....` ` ````````````````
+ ````````` ``````````......--:- `yhdmyo:-`` ` `.:y-` ```.-.`.--...-...```` ./-..`` `` ````````````
+ `````````` ``````````......`.-- `.odmmhsoss-` ``-o:-y/` ` ` .```` `````````````
+ `````````` ``````````......``:- `.`/dmmdhyhdds+/+ody/`:s-` ``.`````````
+ `````````` ```````````..-:///-:`:`````...-:/dmmmmmmmmdddysy+.``y/.` ``..`.``````
+ ` ````````` ` ``.``````````...-+o/++.`/+osyyydmdyhdhdmmdhddmmd:.```s+.` ``.....`````
+ ```````.``` ````````````` `.:ossy+:.---:/:/od/:+--ys/ydsyms-:-:-/y::/-.`````.` ````` ``` ``` `...````````
+ ```....```````` ../osy+s+----///-/s://.`. .+s-+s+.//++ohdhdyssyyys/:. ``````` `` `..` ````
+ ```..````````` ` `../+so+o:::.-/:----:::. -ys:+soyy+/+o++o+-.-+o/--` `````` `` `````
+ ```` ````````` `` ..-:oo/` . `-//:-//+/: `::o+oyo/-+oooo+::+/.` ``-.`` `` `````
+ ``````..````` ``` `.-// .:./+.`-oooo. osoosss++ooo++oo: .. ` `.` ` ` `
+ ` ` ``` `.. ``` .:://.```//: -+++o:-.-:---:-` --: `.` ````` `````
+ ``````` ` `````` -..+s+////+` .--.-` .--` ..` ``.--`..`...` ` ````````
+ ```````` ```` ```````` ` .-.-/++o/:/- ..`. `` ` `://-`````` `````````
+ ```` ` ````..-----.-.` ````` `` ``````
+ ``` `
+ ` `
+ ````
+
+
+
+
+
+
+
+ `
+ ```
+
+ ``
+ ``` ``
+ ``` ``````` ` ` `
+ `````````..```` ``
+ `.-:o:``...--.`.``` `
+ ````.://sy-..--/yos+.```` `` ` `````
+ ```````````./o+shy----+ddhs-..````````````` ````` `````
+ ` ````````````..:ssshdy:::smmmdo-...``......``` ```````````..`` ```` ```
+ `` ````````````..-+ysyddhyohmmmmdhs/--....-...``` `` `````.`` `` ` ````
+ ````````````.....--/yyydmmdyhmmmmmddd+:--..--..```` ``` `````` ````
+ ``````````````........---:/yhyhmmmmdmmmmmmddd+/::-:-.....`` `````` ````` ```
+ ``````````````.``........------:/shdhdmmmmmmmmmmmmddo+/-/::-....`` ````` ```
+ `````````````````...........------::ohddddddmmmmmmmmmmmy++://:--..--`` `````` ````
+ ``` ````````````````.....--------------::+sdmddddmmmmmmmmmmmdy+://::---::-`` ```.```` `` ```` ````
+ ``````````..........---.----::---------://+smddddmmmmmmmmmmmmd+/////:::/:-``` ````..`````````````
+ ```````...........------------::::::::::://++ddddddmmmmmmddmmmd+////:--:/:-```` ```` ```..```````````````
+ ```````....------:::::::::::::::://///////++++ddddddmmmmmmmmmmmdo++++//::::-.`````` `` ```````````````````` ``````````
+ ` ````..``:-:-:/::::///////////////++++///++++o++hddddmmmmmmmmmmdmdssooo+++//:.```.```` `` ````````````` ``````````
+ ```````.`.+yys++/////////////////++++++++++oooo++shdddmmmmmmmmmdddhsssoooo++/-.``...`````` `````````````` ```````````
+ `````....ohdhs//://///////++++++++ooo+++++oooo+++yhhdmmmmmmmmmmdddssssoooo+/:-.......```` ``````````````````````````
+ `` `````..--:/ydddyooo+++++++++++++++oo+ooooooo+oos++osyhmmmmmmmmmmmddmhsooooooo+:-.........`` ````````````````````````.`
+ ```` `` `````....--:::ohddddddddhyo+++++++o+++oooooooooooooos++oosymmmmmmmmmmmmmmdoooooooo+:....``...``` `````````````````````...`
+ ```` ` ````...-:::---:ydddddddddddyoo+++o+++oooooo+ooooooo++/+ooshmmmmmmmmmmmmmmhooos+o++//-..``..`````` ``.....`````````........`
+ ` `````..--::-----/ddddddddddddyo+/++///++++o+++/++ooo+++++oshddmmmmmmmmmmdd+//+h/::::--..````....`` `...````````````........`
+ ```````````````````` ````....--:::::::+hdddhsosdddddhyso+//++++oooo++ossssooooosyhhhmmmmmmhdmmmmsyosdy/::/::::::::::--.`````````````````.....````````````````````
+ ```````````````` ` ````.....-///////oyddddyooydhdddddy+/+ooooooooo+shssssssssyhhyhdmmmmmhdmmmmdhdhddo///:////////:-.``...``````````` `..`...`...```````````````
+ ``````````.```` ` ``````..-.--+o++++/+sdddddssddyhmmmmmdsooooooo+ooodmsssooosssyyyydmmmmmmmmdmmmmhdhhs//::---::::--...---` ````````` `..`...``......````......`
+`````````...```` `` `````...-.-/ooo+ooo+hddmmdshdddhmmmmmmmsoooooyssydmmdsooooossssssddmmddmmdyddhs+osyoys///::-----......` `` ```````` `.``..````...````````....`
+``````.....`````` `` ```````..--://sso+ssoyddmmddmmmmmmmmmmmdhsoooyddmmmmmmyoooooosooooydddhdddo:://+++ooy///::::::----...``.`````````` ` `.....````...```````.....`
+``````.....`` ```` `` ```````..:-::+oo+ooooydddddmmmmmmddmmdhysysso+hsoshddmho+///++++osyddyddhh+++o+o++++o+---..-.-:-.`.````````` ```` `..`..````....````````...`
+```````...``` ` `` ```````.-.-:+++oo+//::++shhdddyo+//:::------/y+/oooooo+:---...-:odhhhdds-..``.::-..-o. `` ```` `..`..```......```````````
+````......`` `` `````````..:::--..`` ``syyhy+.` ` `..+.`` ` `` ://oyyddhsd/`````.:-...-:/```.` ```` `.``............``````````
+``````````` `````````````.....--. -hhhoyo.` ``/.`/.`` `` -smo:/oso/+d/-`.-:::-----.` `` ```````.``..````.....```````````
+ `````````` ` `.```````.......-::- ``yhho+yyo` -s+` .:.` ` `:::-:-..--...--..`````` ./---.` `` ````````......``````````````````
+ `````````` `.```````.......`./- .`oddy++shs-```.hh:` `+-` ` ` `` ..```` ` `..........``````
+ ```````..` `..```````.......`.// `..:dmdyoohdhsooohd/.``s/.` `..--.......````
+ ```````..` `..```````...-:///-:.-`````...-+ohmmmmmmmmdddd+s:.``y+.` `..---.-....`````
+ ````````.`````` ``..````````....-+s+++``::+shhhdmhyhdyydmddddmmd-.```so. `..-----....````
+ ````.....`````..``````````` `.:ossy+:.--.:/:/hd/:/--:+/yh/sds-:-:-oy-::.```.``.`` ````` ``` ```` `.---........``
+ ````......`...`````` ../osyoso:---/+/-/y///.`` .+s-+o+.//++ohhhdhyyhhyo/:. ```.```` ``` `` `... `....``
+ ``...``..`````` ` `../+so+o:::.-/:---::::. :yo:ososy//+o++oo:--+o/--` ``````` ``` `....``
+ ```````..`...` ` ..-:oo/` . `-+/:-//+/: `::o+oyo/-+oooo+:/+/.` ``-.`` `` ``````
+ `````.......` ``` `.-// .:./+.`-oooo. ssooooo++ooo++oo: .. ```.````` `` ```````
+ `` ` `````..` ``` .:://.```//: -++++:-.-:---:.` .-: `.` ````` `..`````
+ ``````` `` `````` -..+s+////+` .--.-` .--` ..` ``.--`..`...` `` ``....`````
+ ``````.. ``.` ```.```` ` .-.-/++o/:/- ..`. `` ` `://-```````` ```` ```..```````
+ ```` ``` ` ````..-----.-.` ````` `` `````` ` ``````````
+ ``` ````
+ ` `
+ ````
+
+
+
+
+ `..
+ :/.
+ -++` `````
+ .os: ``.-s+`
+ -sys. `.-shy/. ``
+ -syhs.` `````./shdhs+
+ `/hdhy+::::-:/shddhy+ ``
+ .ohddhysssyyyydmdhh/`` ``
+ `:ohddhhyhhddsdmddh/```` `
+ `./oyhdhhhhddhhmmdhs-````````` `
+ ``.-+oyhddhdmmddmmddhhs/...``````` `
+ ````..-:/ohhdddmmmmmmddhhy-......```` ` ```
+ ``````````.---:oydddmmmmmmddddd/.......```` ````` `````
+ ```````````.---.:+yhddmmmmmddddds-.....````` `````````.``` ``` ```
+ ` `````````````.---://shdmmmmhdddddh/-......````` ````.`` ` ```
+ ````````````....---::/:+yhddmmhhdddddy:-....`````` `````` ```
+ ``````````.........--::://+syhdddhhdddddh/:--:-.`````` ````` ``
+ ``````````.`````......------:::::+yhddddddhddddh+//-:--..````` ````` ```
+ ````````````````.``..........------::::/shdmmmddyddddd+//-::-......` ````` ``
+ `...`````````````......--.....----::/:://+yhmmmddhddddds//-:::--.--`` ``````` ``
+ `.::-.`````````......-------------:::::://+shdmmmdddddddy//:::::---.`` ````````` ````` ``
+ ```:+++-............-.------:-------::::::::/+ydmmmmdhdddhh:::::::-...````` ```.````````` ````
+ ``````/sso--.--------------:::///:::::::////://+oydmmmmdddddhh////::::--..``````` ````````````` ``` `
+ ``````.oys:----::::::::::/:::/+++////////++///sssydmmmmmddddhy+++++////:-.````````` ````````````` ``````````
+ ```...`.-so--:::::::::::///////++++/////++++//+yyyyddmmmmmdddhso++++++///:-.```````` ````````````` ``````````
+ ```.:++++++:--:-:/:::///////////++++///++oo+++++hhyhhdmmmmhhdddsssooo+++//:-.````.`.```` ````````````` ```````````
+ ````./osyyso:-----://///////+++//+++++/++++oooo+++hhhhhdmmmmdhmmdyhhsoy+++//:--.````...``` `````````````````````````
+ ``` ` `````````..-/oso/++/:+o//+/so+///++++//+++++++++oo++o//+hhhhhdmmmmdhmmddddysho++//::--.```...``` ````````````` ```````````
+ ``` ``````...-....:/:+ss//hy+++hdy+/+++++/++++++++++ss+++//+yhhdddmmmmdhmmddddyody+////:---``...``.`` ```````````````````````.`
+ ```````..---...-+o/oyo+hdy+/hdy/++++/:///+++////oss+/////oyshyymmmmddmmmddds/sy:---::-----..--...`` ````````````` `````.....`
+ ````````````` `` ```````..-::-:---+++syyyddd+ydddhs+++++++++oo++++oys++++++ossyssddmmmmmmmmmmy+oh/:/ys+::-:--:::-...````````` ````````````````````````````
+ ````````````` ` ` ``````...-/:::////yohhhddmdohdmmmmho+oooooooo+++oshs+++oooosssssdydmmmmmmmmmdsydh+/hmy/:---::/:.`....`````` ` `````.```````````````````
+ ````````````` ` ` ```````...-://///+++dhydddmmdshmmmmmmhssooosyo++osyyho++++oooossssyhdmmdmddmmmmdhhdoohhd/.---.---.`..-.` `.```.````````````````````
+ ``````````````` ` ``````....:-/ooso++ohdyhddmmmhmmmmmmmddhyo+sdhsoodmmmyo+++oososooooymddmmyoydhhhhyh/+yosy:---:-.-....`` ` `.```.````````````````````
+ ```````````````` `` ``````..-::/+s++++ssdddhddmmmmmmmmmmmmddyssyhyshdmdhdsso++++o+o++ohddsddh/::/soossys:-:::::-----...``````` ``` `.```.`` `````````````````
+ ```````````` `` `` ```````..--/++++ooooddddddmmmmmmmmmmmdhsosssso+++ssoo+/::::/++++yddhyydhs++++so++++y:---..-..--.`````````` ``` `````.`` ````````````````
+ ````````.`` ` `` ```````...-:///+o//:-:++hddhyys+++/::--..-::-::::/o:::::----o--+dhhy+dds.````:/:-.-++` ``. ``` `.```.````...````````````
+ ``````...`` `` `````````..--:-...`` `ohyo//-` /-` ````. `` .h:+hydmdhyd/` ``-/-...-o.```.. `` `````..`....`````````````
+ `````````` ``````````````....--. -hhys+//. +o` `..`` ````/hdo/+sys/+d/.`.-:::-.--.` `` ``````````````````````````````
+ `````````` ` ``````````......--:- `sddyyo+o- `:y:` `:-.``` ` ``-.-/-..:-...-...````` .:---.` `` `````````..```````````` `````
+ `````````` `.````````......`.-- `-dmdysoyh+::o/+h:.` ./-.` ``` ``` ..````` ` ``.....````````
+ ````````.` ```````````......`.:- `.-+mmdhyhddhdhysds-```++-` ``.........````
+ ````````.` `..````````..-:///-:```````.`.-:+hmmmmmmmmmdmdys-```y+. ``.........````
+ ````````.````` ``.``````````...-+s+++``--/yhyydmddmdshmmmmmdmmm:.```y/` ``.........````
+ `````.`..`` ``..````````` `.:ossy+:.---:::/hd/:/---/+ddohmy-:-:-yo.:-.``````.`` ````` ``` ```` ``....`......``
+ `````....````.````` ../osyoso----///:+y://.. .+s-+s+.//++ohhhdhhyhhyo/:. ```.```` ``` ` `..` `..```
+ ```..`````````` ` `../+sooo:::.-/:---::::. -so/ososy//+++oso/::+o/--` ``````` ``` `...```
+ ```` ``````..` ` ..-:oo/. . `-//:-//+/: ::o+os+/-+oooo+:/+/.` ``-.`` `` ``````
+ ``````..`..`` ``` `.-// .:./+..-oooo. ssooooo/+ooo++oo: -. ```.````` ` ``````
+ ` ` ``` `.. ``` .:://.```//: -++++:-.-:---:-` --: `.` ````` ````````
+ ``````` ` `````` -..+s+////+` .--.-` .--` ..` ``.--`..`...` `` ```````````
+ ```````` ``.` ```````` ` .-.-/++o/:/- ..`. `` ` `://-```````` `` ````````````
+ ```` `` ````..-----.-. ````` `` `` `````````
+ ``` ```
+ ` `
+ ````
+ ``..`
+ `` ````---`
+ -` .: `....//:.
+ ::` `/. ``.-----+o/.
+ .+:`.+-``.://+oss/:::oso:```
+ /o//o/-//oosyyyyo///shy/..`
+ osss+-+soosyyyhyoo+yhy+:-
+ `syy+./ossssyyhhysosysoo+.
+ `oyy+/+syysyyhhhyooo/oys/` `
+ `/sso+osyyyyhhhho-..ohyo`
+ ````./oyyhhhhhhso+shhs`` ``
+ `.:+yhhhhhhhsshhy.```` ``
+ ```:hhhddhhyohhh...``````
+ ````:hhddhhhohhho...`````
+ ```````ohmddhhsyhhh/..`````
+ ```````.ymddhhyyhhhy.```` `` `
+ ``````````````/dmhdhhyhdhh/````````` `
+ `````````````.```-hmdhhhyhddho.```````` `` ````
+ ````````````.....-sddddhyhddhs.```````` `````
+ ` `````````````.....--::+hddddhdddhs..```````` ```
+ ````````````........---/o/oymdhhhdddh:---...`````` ` `` `
+ ````````````.........--:/ssosymddhhddds::::.--..```` ````
+ ` ``````````````...`.......---::+yysyhmmdhhhdd+::::.---....` ` ``
+ ````````````````.............-:-::/ohhyhdmmdhhhdd/::::.---....` ` ````
+ ``````````........-----......-::::/+hhhdmmmdyshdd+::::------..` ```````
+ ``````````..............----.....--::::/+hhhdmmmd++hdh:-------....```` `````` `
+ ` ``````.......---------------------://///+yhhdmmmd+sddy//++/::-----..`````` ``````
+ ``` `````..------:--::::::::::::::::://++///yhdmmmmdoydddyyyyo////:::-..`````` ``````` ``` `
+ ``````:-.------:/++::::://:::::///////+++//+yhdmmmmdhsddddddhs+////:::-.`` `````` ``````` ` ` `
+ ` `````..++::-/osssso///////::::://++///+++/ooyhdmmmdddhdddmmmdyo+////+//:.````````` ``````` ` ``
+ ``````-..---yyo+shhhhys+//+++///////++++++++o+yyhhdmmdhdddddddmmmyo+s///+//:-`````````` ``````` ` ``` ```
+ ` ```````::.-://hdhhddddhs+++++++////++++ssoo+/ooyyhdydddyhhdmmddmmdo++h+/++//:-.`````..``` ```````` `` ``````````
+ ` ````.....``-o-+ssshddddddho++++++++++++++++oooo+/+syhdhshhhsyhdmmhhmmmd+odo/////:--.`.....`````` ```````````` ```````````
+ `````.........s/oyhhdddhhdh///////////+o+/////++////+ohdysoyysyydmmysmmmdhydy--:::/:..```....````` ````````` ``````````
+ ```````` `````.--..----+h/hhddddysdy//+++//////+yo/+++++o+//++ohhsyyssshsdmdyodmmddddh:--/://-.....---.`````` ````````````` ```
+ ```````` ` `````.-:--::::/dsyhdddds+ddo++++//+++o+so/+soosyo++++syysyssosyhmdhyshmmmmddh+/::++--....---.`` ```` `````````````````````
+ ` ````````` ` ````..-://:///++ddsdddddo+dmsooo+//+syh+s+++o+osho++++osssysoydmmmhyysydmmmdddhys++/.....--...``... ````````````````````````
+ ````````````` ` ````.--://:///+oddddddddo+mmyooo+/+sddhoo++++ohyyso+++++ooyssmmmddyoso+ydyyyshs...-h:..--..`....``` `````` ````````````````
+ ```````````` ` ```````..--::::///+sdddddddmdsmmdooo+sdmmdhyo++yhdhosso+++//o+++ommhodyo:..-:/o++sh:-..:/.......``````` ` `````` ```````` ```````
+ ``````````` ` ` ````````..-::://+++ohddddddmmdhmmyoohddyyysssooo+ohyso+/::::/+++ymhysdso+///++++/+y+........`..`````` `` `````` ```````````````
+ `````````` ` ```````..--:::/+/::--/+yhddhyo++/:----.:/....-/+++//:------:.-:hdhhddys-````.----:s. ``` ` ````````````````````````
+ `````````` `` ```.----...``` `-oyyy+:` .+. ```.`` ```:h-.+hhmdyhy/` `.---.-+: `.` ```````````````````` `
+ ````````` `` ```````````...` .-oyyso: -o:` ..`.` ` ``/hy++osy+:oh/. `.---.....` `:` ````````````````````
+ ````` ```` ``````.....--. ...+hyso:` .+ss- `-..` ```---:/-.-:-.....```` `/:--.` `` ```` ` `````````````
+ ```` ```` ```````...```.. ....odyho:::oyoy:` -:.. .`` ``` ..````` ` ```..`````````
+ ` ```` ```` ``````..````-. `...:mddho+shhyhh/.``.s:`` ``...```````
+ ` ```` ```` `````.-:::.:````````...-/sdmmmmmmmmmmdyo.``/s-` ``.....``````
+ ```` ```` ````...-+o/+/``..+yyyhdmmdddydmmhdmdmmm/.``+o. `......``````
+ ` `````` ````` ````` `.:osss+-..--:::/hd/:/-::::sdoody::--/y:.:-.``````.`` ````` ``` `` `...``..`````
+ ````````````` `./oss+s+----///:+y//+.. .+o-+o+./+++yhhddhyyyhyo/:. ```.``` `` `` ``.` `````
+ `````````````` `../+so+o:::.-/:---::::. .so/oooyy//++oss++/:+o/--` ``````` `` ``````
+ ``` ```````` ..-:oo/` ` `-+/:-://:: -:o+os+/-+oooo+::+/.` ``-.`` `` ``````
+ ``` ```````` ``` `.-// .-./+.`-+oo+` osooooo/+ooo++oo: -. ```.` ``` ` ``
+ `.` ``` .:://.```//: -+/++:-`-:---:.` --: `.` ````` ``````
+ ````` ````` -..+s+////+` .-.`.` .--` ..` ``.--`..`...` `` ````````
+ ```````` ```` `````` ` ` .-.-/+++/::. ..`` `` ` `://-.``````` ` ``````````
+ ` ```...----..` ```` `` ``````
+ `
+
+ `
+ `` :ssssssoo///` `
+ ` `+syyyyssoos/` .`
+ .+syyyysssyo- .-`
+ `:+sssso:sys+. -:.
+ `...``+hys/``-/:.
+ -yhys:../+-
+ .yhhyo-`-+:
+ .+hhhy:.--`
+ `-ohhhh+-`
+ `/shhhh+`
+ `-/shhho `
+ `+yhhy` ``
+ ``` ``/yhhh.
+ `..````/yhhh/
+ `..``../yhhho-`
+ ``....--+yhhhys-`
+ ````..---syhhhhhy+.`` `
+ ``````````.-:-:mdhhhhhhy-```` `` ```
+ ` ```````````.--:::ddhhhhhhho..```` `````` `````
+ ` ````````````..--:::/hmddhhhhhy:....```````` ```
+ ````````````.....-:::///omdddhshhh+-........```` ``
+ ````````````......-::::////mmddhsyhhs:-----.--..``` ````
+ `````````````````...`......-::://///dmdddhhdhy///:::.---..`` ` ``
+ `````````````.................-:////++smdddddddy++/:::----...`` ` ````
+ ```````````..-----.----........-////+++oddddddddhho+//:-::-----`` ``````
+ `````````........-:---...------------////////yhddddddddhs::----:----.``` `````` ``
+ ```.::+/........----:::::--------::--:::/++/+++/+ydddddddmmh+/::/:///::-`````` ````` `
+ ``./sssys/-------:::////::/::::::::::///+++/+so+/+hhddddddmms++oo/++++/:.``````` `````` ````` `
+ ```:yhyhhyo::++:::::////////:::///////+++++++hs+++yyhdddddmmdo+yy++o+++/-````````` ````````````` ``
+ `` ``-shhhhhysos/:::::/+++/++/:////////++++o+oydsso+syydddddmmmdshy++oo+++:.````.````` ``````` ``` ``` ```
+ ```` ``.ohhhhhhyss/::::/+++++++++////////+++oysyddsysoosydddddmmmmmmy+++o++/:.``````...```` ``````` ``` ``````````
+ ````````.+hddddhsoo////+++++++os++////////++++yyyddsyssoshdddddmmmmmmhs+++++/-.`````.--.```````` ````````````` ```````````
+ ` ````..````.:yhdddy/:////+++++++++h++////////++++sshdhoysssshdddddmmmdmmmddo+++/-.```.----...````` ````````````` ```````````
+ ````........--shdddo:::://////://::h+:///o/:::/o++ooyhs+yyoohmmmddhdmmdmmmddh/:/:..`````..-...`````` ```````````` ```````````
+ ``````` ````....------:+sdddy/:///++++//////hho++ssso/+ohs+oosysosyyhmmmmmhshmmmmmmdddy//:::--....----.``````` ````````````````````` `
+ ````````` ` ```.-:----::::+/sddddy+++/++++///+oshdysossssyyhhs++oossssyydmmmmhssymmmmmmddddy+/+/:---:::::-.``````` ````````````````````` `
+ ` ````````` ` ```..------:::/syydddddho//++o++/+shdddyssoosyyyyo+++oooossssdmmmhyysshdmmmmddhso+/--.--------...-.```` `````````````````````````
+ ````````````` ` ````.------:::/osshdddddddhysooo++smmhhdysoosddds+++ooo+osssssdmmdyooooohdyyyyhh-..-..---.........`` `` ` ``````` `````````````````
+ ```````````` ` ```````.-.----:///oysdddmmmmmmmmdoooymmyyhdsoosdmdyo+++ooo+oso++oymdsh:::---/+ossyh/-.......-......```` `` `````.` ````````````````
+ ``````````` ` ` ```````.-::---:/+//oshdmmmmmmmmmmmmmmdysysys/+oo+oho///+////++++odmmhdso+++++oo+++h+----.`.-...``.``````` ` `````.` ````````````````
+ `````````` ` ``````.-::::::/+::---/+syhhhdh+//:-:--:-.....-://+/:--------.::sdmmdmdy.``..-::--+o` ``.. `` `````.`````.`````````````
+ `````````` `` `.------..```` `.../sss` ``-- `` ```.s+/+hhdhhhd/` `.---..:+. ./:` `````.```...`````````````
+ ````````` `` ````````.....` `...-ssy:` `:+:. `` ` ``./hs/++os/:+h/. .-::--..-.` `o/` `````````````````````````
+ ````` ```` ```````....--. `....syyy:.`.so:` `.```` ``-:./o:-.:-...-..````` `/:--.` `` ``````````````````````
+ ````` ```` ```````...```.. ....+hhho--+yso:` -:.``` `` ` ``` ..``````` ``....`````````
+ ` ```` ```` ```````..````-. `...-/ddhhsshhsyy/.```s+. ` ``.......`````
+ ` ```` ```` ```````.-:::.:``````....-:+yhmmmmmmmmmmho.``.y/`` ``.......`````
+ ` ```` ```` `````...-+o/+/``.:oosyhdmdhdhyhmmhhmmmmm:.`.y/` `.......`````
+ ` `````` ````` `````` `.:osss+-..--:://hd/:/::::-+dsydy::-:yy-.+/.````````` `````` ``` ```` `....`.....```
+ ````````````` `./+ss+s+----///:+y//+-.` .+s-+o+./o+ohhhddhsyyyyo/:. ```.```` ``` `` `..` `..``
+ `````````````` `../+so+o:::.-/:---:::/: .so/osoyy//ooyso+//:+o/--` ``````` ``` `...``
+ ``` ```````` `.-:oo/` ` `-+/:-://:: -:o+oso/-+oooo+::+/.` ``..`` `` ``````
+ ``` ```````` ``` `.-// .-./+.`-+oo+. osoosso/+ooo++oo: -. ```.`` `` ` ``````
+ ` `.` ``` .:://.```//: -+++o:-`-:---:.` --: `.` ````` ````````
+ ````` ````` -..+s+////+` .-...` .--` ..` ``.--`..`...` `` ``````````
+ ```````` ```` `````` ` ` .-.-/++o/:/. `..`` `` ` `://-```````` `` ```````````
+ `` ```...----..` ````` `` `` ````````
+ ` ```
+
+ ``
+ `++``.
+ /o:.-.
+ ` -oo//:
+ ``` `ososo.
+ ``` /yyyy:`` ``` `
+ ```` -syhy+` ```
+ ```` `oyhhs``
+ `..` `/yhhy.` ` ` `
+ ```...` `/yhhy-` `` ```
+ `.``....``oyhhh:``
+ ...` `...`.syhhh/.` ``
+ ...```..-.-yhhhh+:.` `` ``
+ ..-.``----/yhhhho/-``` ```` `` `
+ `--.``.---/yhhhhs+:``````````` ``` ``
+ ``---...-:-:hhhhhy/-```````````` ``` ``
+ `````.---..--.:hyyhhhs:-..``````````` `` ``````````
+ ````````.----..-..-:yhhhhyyys:.`````````` `` ```````````` `
+ ```````````````-:::.-:-..:hhhhhhhhyo:.`````````` `` ```````````..`````````` ````
+ `..````````````.-:::::::---yhhhhhhhys+-...`...```` ``````..```````` ````
+ `....```````....-:://////::shhhhhhhyys:-...-...``` ` ```.```` ````
+ ``.-.............-:///////+//ohhhhhhhhhy/::----.....` ` `````` ````
+ ` ```..---........----:///++++++/ohhhhhhhhhhs///-/:-----. ``````` ````
+ ..```` `````````.-----.......---:////++//++/+hhhhhdhdhhh++/-:::::--.` ```````` ````````
+ .::.:/.````````````.-:--..----..---:///++++/+o++hddddddddhho++://///::-`` ```.```` ``````````````
+ `./o+os:```````````..-::------------://++++++++++yddddddddddy++///++///-````` ````..`````````````` ``
+ `-+sssy+.`..........-:::-----------:://++++os////shddddddmddh+/::::/:::-`````` ```..```````````````````
+ `./sssss/.....-------///::::::::::://+++oooyy+++oyhddddddmmddy++////:::-.....```` ` ``````.````````` ``````````
+ ``:oo/::-.::----:::::/+//:::///////+++ooossdhs+oshhmdddddmmmdddho++++//:-.``..```` ``` `````````````` ``````````
+ ``.+o-..-:s:---::::::++///////////++oooosshddhsosyydddddddmmddmmdoooo+//-.``...`.`````` ``````````````````````````
+ ``-so/+oyy:-::::::/++/////+//////++oooooshddhyssyyhddddmdmmmdmmmhosso+/:-.........`````````` ``````````````````````````
+ `` ``.+yysyyo..-::::/+++//+/////++/++oooosssydddhsssydmdddmmmmmdmmmmssss+/:-......-.-..```````` ````````````````````````.`
+ ``` ``````````..ohhhso:-:////++++//+/////syo++oooooosohddhssydmmmddmmmmmdmmmmhoso+/:......--:-..``` ```` ``````````````````......`
+ ``` ``.....`.....ohhhyo::://+++++/+o++////hhyooo+oo+o+yddhyhdmmmmmdmmmmmdmmmmdoo+//:-...-------..``````` ``.....````````.........`
+ ```.`..........-:yhdhh+-::::///::////:://shhys++++++ooddyyyhmmmmmdmddmmmmmmdd+//::-.....---:---..```..` `` `...````````````........`
+ ````````` ````.---....-----::ohdddy/////++//:/++++//++shddyooooooohhsssymmmmmdddhmmmmmmmdy//+///:---::::::--..``..``````````......```````````````````
+ ` ``````````` ` ````..-....----:o+:/hddddo+++oo+//:/+ooo++/++ydddsooossshysssydmmmmdhdhdmmmmmmdds+/+++/::::::::::--..``````````` `..`........``````````````
+ ````````````` ` `````.....----::/hhyosdddddhsooo++/:/ooooo++++shddsooosssssssyyymmmmdyhhyddmmmddsso+/-------..--:--:-.``````````` `..`...``......``........`
+ ````````````` ` ``````.-...---:://hddddddddddmyoo++//+ssyyoo++odyddooossssssssyssmmmmhyssshhyyssho-----------..-----.. ``````````` `..`..````....````.``....`
+ ```````````` ` `````.-----::://+shdddmmmmmmmmmhoshhssyhyysoohmmhdyoooosoooyoooosmmmdy+/::+s+++osh/:::+o...-:-::--....```````````` `..`..````...````````....`
+ ``````````` ` ` ``````------::/++/sdhhdmmmmmmmmmmmmmdhyyssso/+ooosdo+++o++++o++oohmmmddo+++oyy+///yo:--:o/.----.`...```````````` `..`..````....``````````.`
+ ``````````` `` ````.-::---:::+/:/+:-/osyyyhhs++//:::-....-.-:/+++/::::----..::+mmmddh:..--oy/.``:o` ./.-. ```` `..`..``.......```````````
+ `````````` `` `.-:------.```` `...../s+` .:-. ```` `./::yyyysyh:``--:s/````+. ` -:: ````` `.``............``````````
+ `````````` ``` `````........` .....+sy:../s/` ``` `-/y++/+s/:+h/.`-::/:-----.` `/.` ```````````.```......```````````
+ ````` ```` ```````......-. ...../shs::oy+. `..`` ` -....-+/:-:-...--..`````` `//:-.` ``` ````````......``````````````````
+ ``````` ````````````...```.. `..../yddsoyyo+-` -:-.``` ` ```` ..``````` `...........`````
+ ``````` ```` ```````..````-. ..--+hmddddhyso/-```+o:.`` `............````
+ ``````` `````````````.-:::.:```````...-:ysymmmmmmmmmhy/.``+o:.. `...-........````
+ `` ```` ```` ```````..`-+o/+/``..:oyyhdmdhhhsydmdmmmmmd:.`/y:.`. ``.--.--.....````
+ ` ``````` ````` ````` `.:osos+-..--:///hd/:/:://-+dhdds-::/hy::yo:.```````` ````.``````````` ``.-.........``
+ `````````````` `./+ss+s+----///:+y/+sy-` .+s:os+-/o+ydhhmdhyyyhy+/:. ``..```` `````` `... `.....`
+ `````````````` `../+so++:::.-/:---::oho -yo/oooyh//oyyo/++/:+o/--` ``````` ```` `....``
+ ``` ```````` `.-:oo/` ` `-+/:-://// ::o+oso/-+oooo+::+/.` ``...` `` ````..``
+ ``` `..````` ``` `.-// .-./+..-+oo+. osoosss++ooo++oo: .. ```.````. `` ````````
+ `` `.` ``` .:://.```//: -++oo/-.-/--::-. .-: `.` `````` `...``````
+ ``````` ````` -..+so////+` ---.-` .:-` ..` ``.--`..`...` `` ``......````
+ ```````` ```` `````` ` ` .-.-+++o/:/. `..`. ``` ` `://-```````` ```` ```......```
+ ``` ```...----... .```` ` `` ``````` ` ``````````
+ `` ```
+
+ ``
+ ` .syys:
+ `oyhy/
+ `/yhy:`
+ -yhh/`
+ `` .yhho.`` ````
+ `` ` `ohhs-`` `````
+ `.`` -yhy:`` ````
+ `...` `yhy/``` ```` ` ` `
+ `...` ` +hh:`` ````-``` `` ```
+ `...`` .yh/`---:/oss/.`
+ `....` ` `sho`-osyyyhys.````` ``
+ ......```````ohs-`+yhhhhhs````` ``
+ `.--...```````yhys.:yhhhhs``````` `` `
+ `..---....````:yhsy+/hhhhy/.`````` `` ``
+ `..-----...```+hhyyyshhhhy+.``````` `` ``
+ `..-------.```+yhhhhhhhhhy/````````` `` `` ```````
+ `` ```..-------.``..:yhhhhhhhhs.````````` `` ```````````` `
+ `` ```````.---------.....:syyhhhhho-..```````` ` ```````````..`````````` ```
+ ` ` ```````---:---:-.....--/shhhhhy+...`...````` ``````..```````` ```
+ ` ```````````.-:::--:-------/:ohhhhhho-...-..```` ` `````` ```
+ ````````````...:::/:-----::::o:ohhhhhhy::-.--..``` ` `````` ```
+ `.```````.....-::///--::::::/+++hhhhhhhs//-::-..``` `````` ```
+ `````````..`...--:///:-:::::////ohhddhhhhy/-:::-..``` ``````` ` ```
+ ```````````.........--::////:///////++yhdmmhhhhh+::::--..`` ``````` ```` `
+ ``````````...`....------:--::///:+o////+++sydmmhhhhhy///:::--.``` ```.``````````````
+ `````````````...........---:::::::////oy+//////++ymmhhhhhho/::--...````` ``..``````````````
+ ```````.........----------://////////+ohyoo+++oooymmdhhhhhho+/:::--..``````` ` ````````````` `````` `
+ `` `.```...--------::::::::::/+///////+/+sdhsooosyyhmmdddhhddhs++///:-.```.```` `` ````````````` ``````````
+ ` `......---------:::::::::/+++++//+++++sdhyssosdddmmdddddddmyo++//:-.``.`.`.``````` ````````````` ``````````
+ ` ``.--.-.-----::/::::/:::////+++++++++/+sdhyysshmmmmmddddddmmyo+++//-..........``````````` ````````````` ```````````
+ ````...-...-:-::////////://++//+o+++++oo/oydhhyyydmmmmmddddddmmyo+++//-............` ``` `````````````````````````
+ ``````` .``..-------::::/+++/////++++//++++//++s/shdhhhhhmmmmmmddddddmmhoo++//-.....----...`` `` ```````````````````````.`
+ ` ``````````:``.--:-::-:::///+++/://+++++///+++///+++yhhyhhhdmmmmmmdddmddmmdsoo+/:-....--::-.-...`````.` ````````````````.....`..`
+ ``````````.:/...---::---://////--/s+//+/:::://::/++syyyssyhdmmmmmmmddmmmmmmy+//:.......-.----...`` ``` `````````````````.......`
+ ```` ````.```..../s:---:+s+/:::/++++/::yyso+++/////++++oosyyssoyhhdmmmmmmddmmmmmmds++/:--.---.--:::-..-.`````````````````````````````````````
+ ```````` ````.```....+hs:-:+yhyyyyhhdddh/:/hhyso+/////o++oooosyyssssyyhmmmdddhddmmmmdddo+++/:---------------````````` `.```..``.```````````````
+ ` ````````` ` ```````......--/hys+shhhhddddmmmmd/:+dhyyo+////+ho+oooosyssyssyyhmmmhhhyyddmmmhyso+++:-.--.....------`````````` `.```.````.```````````````
+ ```````````` ` `````...---::::shhhdddddddddmmmmmo/ohyyso+/+soddy+oooooysyysyyyhmmmhyssoyddyo++s/s/oho---.....-....` ``````````` `.```.````..``````````````
+ ```````````` ` ```....---::/::/hhdmmdmddddmmmmmmhsshysooooshdmho+++ooossyooo+ommmms:/:::ohs++++oys:+y+-..-:----..`````` ``````` `.```.`` ``.``````````````
+ ` ````````` ` ` ``......--::+//+hhdmmmmmmmdddmmmdysssoo++/oyysyh/////////++++odmmmms/+++ooyy///////---::.::.....````````````` `.``..`````..`````````````
+ `````````` ` `.-.....---://:/+-:++osyyhhooooo:-....`..-::://+------.-...-/yddmdds:..--:+y:`` .:` ...` ``` `.``..````....```````````
+ `````````` ` `.---.-.....```` ...` `+s+-:/o.` . ` ` `-sysyhyyh:` .--:s:`` `.-` `:` ```` `````..`......```````````
+ ````````` `` ```.-......` `...` `-yy++oo..`` `- ` `-yo++s+:+h/. .::::-.---. .-` `````````````````..```````````
+ ````` ``` `````````.... ....:-:hdyoso....` `-``` `. `````.-:-.::...--..````` `/::-.` `` ````````.....````````````` `````
+ ```` ``` ```````````.. `.../-+ddhsys:---.`` ./-.```` ` ``` ..``````` `......``````````
+ `` ``` ```````````-. `.:/-odddhyhhysso-.`.o/-..` ``..........`````
+ ``` ``` `````.-:::.:```````...-ssohmmmmmmmmmmmo.``oo+:.` ``..........`````
+ ``` ```` ``````-/o///``..:syyhdmhhmhssdmdmmmmmh..`:ys:`//. ` ``..........````
+ ````` ```` ` `.:osos/-.---:///hs-ss:-:/:omddd+.::+hh/:sys/.````.`` ````.``````````` ``....`......``
+ ````````````` `./+ss+s/.---///:/o-ohs-` .+s:os+-/+ohdhhddddhhhyy/:. ``..```` `````` `... `....``
+ ````````````` `../+so++:::.-/:---:/yh+ .so:+ooyh+/sys/-::::+o/--` ``````` ``` `....``
+ `` ``````` `.-:oo/` ` `-+:--:/+/+ --o+oso/-+oooo+::+/.` ``..`` `` ````.``
+ ` ```````` ` `.-// .-./+.`-+oo+. osoosss++ooo++oo: .. ```.````` `` ````````
+ `.` ``` .:://.```//: -++oo/-.-/--::-` .-: `.` ````` `.````````
+ ``` ``` -..+so////+` ---.-` .:-` ..` ``.--`..`...` `` ````````````
+ ```` ``` ````` ` ` .-.-+++o/:/. `..`. ``` ` `://-``````` ```` ````````````
+ ```...----..` .```` ` `` ``` ` `````````
+ ` ```
+
+
+ ...` `.::`
+ `..` ````/yy:
+ `..` ```.+oooosyys``
+ `-.` ``.oyyyyyyyys``
+ `..` ``oyyhhhhhyys.`
+ `..` `syyhhhyyyyy-`
+ ...` `+yyhhhyyyyys-`
+ ...` `:yyhhhyyyyyyo`````
+ ...` `.yyhhhyyyyys:```` `
+ ..` ``+yhhhys-:o-``
+ ..` ```.yhhhy/`-+` ```` ``
+ .` `````ohhhy../- `` ``
+ ` ``````-yhhs:/+` ```` `
+ `` ```````.yhhs+o/`` ```` `
+ ``````````.shhysyo-`` `` `
+ `````````..shhyyyy:``` ` `
+ ` ````````..:shhhhhy:```` ` `` ` ```
+ ``````````.``````../shdhhhy/````` ``` `.``` `
+ ````````````........./+hdhhhh+```.``` ````` ``
+ ` ````````````...........--odhhhhs.``.``` ````` ``
+ ` ``````````````.......---------:syhhhy:-.-.```` ````` `
+ `````````.............----------::+yhhhhs:.:-..``` `````
+ ``````````............-----:::::::/ohhhhhh/----.``` `````
+ ````````````........-.......---::::::////+ohhhhhh+-----..`` ` ````
+ ````````````..``.......--......----:+////+++++ohhhhhhy:::---..`` ````````
+ `````````````..............---....-----:s+/:/oosssshhhhhh+:---...````` ````````````
+ ``````..........-------------:-----::::/y++/+oyhhhhhhhhhh/:::::--..``````` ````````````
+ `` `````....---------:::-:::::::/::::::/::+ys+/ooyddhhddddhyo+o////::-.``````` `````````````
+ `` ````...-------::::::::::://:://::////::shyo+osymdhhdmmmdyooo+//+/:--.```````` ` ````````````` `
+ ````.....-.----:::::/::::::://::////////:/ohho+osdmmddmmmmmyoss+//oo/:-.```...````` ```````` ``` ```` ````
+ ``-:/+/....-:::::::/+/://::///:://///++oo/+yho+oymmmmmmmmmmhssso++oo/:-.``......```` ```````` ``` ``````````
+ `````````./yhhh+:--:::++///////o+://+//:///++++ssysso++ohmmmmmmmmmmmdyso++oo+:.```...---.`````` `` ````````````` ```````````
+ ` ````````````-yhhhhyysso/++///////y+/+++++/::/++++++sys++oshmmmmdmmmmmmmmho++oo+/-.```........```` ``` ````````````` ```````````
+ ````````````....-ohhhhhhhhhhyyyyo/::y///+++/----:///+/+yy/:/+ommmmhddddmmmmmho////:-`````````....``` ```````````` ```````````
+ ``` `````````....-----shhhhhhhhhhhmds+::o++++o+/::::/++++++hy+/ooommmmdddhddmmmmhdhy+/:::-......--.......```````` ````````````````` `` `
+ ```````` `` ````````..--:/+:-ohhhhhhhhhhddy+/://+++oo+///+++++oo+ydysshyymmmmddhhydmmmdhdddy+++s/-......-.......``` `` ````````````````````` `
+ ` ````````` ` ```````.....----:sys/+yhhhhhhhhhdhos/:/+++ooyoos++so++o+sddhyhhyhmmmmdhyyssdmmdyhhdhosdy-...``````..-.```` `````````````````````````
+ ```````````` ` ````....---::::/yhhhhhdhhdhddhhydds/+o++ooysddyddooooohdhhhhyydmmmmhyso+oydh+/::/s:+hmh/-..```..--.` ` ``````` ````````````````
+ ```````````` ` `````...-:+::::/+yhhhhdmdmddhddddmdhyoooooooydhhdsooooohhsss+++mmmyh+::---/sh+//+oo/-:+o+-...----..`` ` ``````` ````````````````
+ ` ````````` ` ````.....-//::::oyyhhhdmmmmmdmddmddhysoo+o+yso/+s//:::::::/+++smmmyh/////++oho::::----..:----`````````` `````.` ````````````````
+ `````````` ` ``..-::---:///:::/-://osyyhhyhy+:----...-:..-:::/..-........-:hhddddo-``..--o+` ``` `.`` ` `````````````````````````
+ `````````` ``.---------...` `` `/soss` `..`` `-` ` ` `` `+oohhhdh: ....// `-` `-` `````.```..``````````
+ ````````` `` ```......--.` `/ss+y:```...```:` ``` ``-o:+o+/+h:. .----.....` `.` `````````````````````
+ ` ``` ``` `````````.... `-.syy:ss+/+o+.`.`:-.```..` ````.....--.....```` `/:--.` `` `````````````````````
+ ``` ``` ```````````.. `/-/yyho/ssyydh/..`-/-.--. ` .```````` ``....````````
+ `` ``` ```````````-. `.s-ohyyhhyhddmmh:..`+//+-` ``....````````
+ ``` ``` ``````.-:::.-``` ```..:y+hmmmmmmmmmmmm+.``-/oo.`-` `......``````
+ ``` ```` ````...-+o///``..:osshdmddmdo+yddmmddds.``.+s+`:o/:` `......``````
+ ````` ````` `` `.:+sos/-.:--:://yo:so--//:ymhhh/.-:+syo-/yo/``.```. ````` ```````` `....`..``````
+ ````````````` `.:+ss+s/----///-/+-+ss-` .+s:oo/./+shhhhyhyyyyyys+:. ```````` ``` `..` `````
+ ````````````` `../+so++:::.-/:.--:/yh+ .++:+ossyo+ooo/--..-/o/--` ``````` `` ``````
+ `` ``````` `..:oo:` ` `-+:--:/++o` --o+oso/-+oooo+::+/.` ``..`` `` ``````
+ ` ```````` ` ` `.-:/ .-./+.`-+oo+. oso+ooo++ooo++oo: .. ```.` `` ` ```
+ `.` ``` .:://.```//: -++++:-`.:---:-` .-- `.` ````` ````````
+ ````` ``` -..+so////+` .--.-` `-.` ..` ``.--`..`...` ` `````````
+ ``````` ``` ````` ` ` .-.-/++o/:/. `..`. `` ` `://-``````` `` ````````````
+ `` ```...----..` ````` `` ````````
+ ` ```
+
+ ``
+ `syyysso..
+ .oyyso+-
+ `/oso-.-
+ ./+/:`.-
+ `..+-:-
+ `s/o.`````
+ `sss`/.`.`
+ `yso.o-.-`
+ oo..o/::.
+ /- .so++-
+ -yys+. ``
+ -yyy+` ``
+ :yyy+`
+ -yyy:.
+ ` `-yy+``
+ `` `````````-yy/.-:` `
+ `````````````.-yys+oo. ``
+ ```````````````````````.-yyyyss:`` `` ````
+ ` ````````````````````.....+yyyyyy+.``` `````
+ ` ` ``````````````............-ssyhhhyyy+.``` ````` `
+ `````````````````.........------:yhhhhhhyy:-.``` ```` `
+ ```` ````````````````..........----------:yhhhhhhhh-:-..`` ````
+ ```````````````````..``..........------:::///shhhhhhhy----.``` `````
+ `````````````````.`.................----:::::/+oshhhhhyyyo--:--..`` ` ````
+ ` ``````````````........-----........----::::::///ohddhhhysy+-:::-/-.`` ```````
+ ````````...................-------------------:::::/ydmmdhs///:::--:::.```` `````` ` ```
+ `````````.....----------------------::::-:::::::::://hhdmmmdh////++/////-..`````` ``````` ````
+ ``````.:-....----::::::::::::::::/:::////////:::////+ydhdmmmmmso+ooo+++o+:-.````````` `````````````
+ ```````-+oyy/::--::::::::::::///////+////++/////:::/+++sddhmmmmmmhoossoooooo/:-.````.``` ` ````````````` `
+ `````.+syyyyyoss+/::/://///////////+++///++++++/:::+++osmddmmmmmmdsoshysoooo+:-.``.....```` ```````` ``` `` ```
+ ```````.oyyyhhyyyhhhyysoo++//////////oo++++/++++++::/++oosddmmmmmmmmdysymmmdhso:-.`....--.````` ```````` ``` ``````````
+ `` `````````..:oyyhyhhhhhhhhhhhs+++++////+ooooo++///+//::/+oosshdmmmmmmmmmmhsdmmmmdo/.``..`.---..`````` ` ````````````` ```````````
+ ``` `````````.....---+yhhhhhhhhhhhyooo++//+++oooo++o++++++::/osysohmmmmmmmmmmmmddmmmmmo+-...``....`..```` `` ````````````` ```````````
+ ````````````....:oo::+yhhhhhhhys++/os/::/+++ooo+:/+//+++hyo+ohhssdmmmdmmddmmmmmmmmmmmo::.``````......`````` ` ```````````` ```````````
+ ````````````` ``````.````..----+ysoohhhhhhhhy+//+yy+//+o+oosyo//++++ooyddhdddhhmmmmdmdddmmmmmmmmmmdyo//--.....---.``.....``````` ```````````````````` `
+ ````````````` ` ` ```````......-:::::shyyhhhhhhhhhy+oyhho/+ooooossso+ooooossddmmddhhmmmmdddhydmmmmmdddmmyhhy/:-...--...`...````` ` ````````````````````` `
+ ````````````` ` ``````.....--::///+oyhhhhhhhhhhmmshhhhy+osoooooosyo+ooossyddddhyyymmdmmhdysydmmmdyyohdsohh:...``````..-.````` `````````````````````````
+ `````````````` ` ``````.----:::://+osyhhhhhhhhhmmmhhddmdyssooossshyyoo++ssymhyyyysydmhddyysooyddds:/:---/omy-...`````.--.``` ``````` ````````````````
+ ````````.``````` `` ```....----:o+://++oshhhddmdmmmmmddmmmhhhssssyydddddo++osydyoo++shdmdsh+:/:-:/sho:+///:-:oyo:-----.-.``` `` ``````` ````````````````
+ ````````.``` `` `` ``...-:/:--o///+//+shhmmmmmmmmmmmmmmdhysssysooo++ys///:--::://+oydmmyy+://+++yh/--::----.-:----.```````` `````.` ````````````````
+ ``````````` `` ``...-://::///++//:/::/+osyyhhhyo+/::/:.../-..::/::--.........-:yhdmdds-``---os-` `. `.` ` `````````````````````
+ ``````...`` `` ````.-::////::-..``` `+so:`` .o/` `.- ```` `+sohhddy- ...:o` `:` ``.` `````.```..`````````
+ `````````` ```````````....-----` -ohs:.``./ho. ``-` `.. .`.s::++/+y:. -----.....` ` ..` ````````````````````
+ `````````` ``````````......---- .`+syd+::::sdh:```.-``-:. `-....-..--.....```` `/:--.` `` ``````````````````````
+ `````````` ```````````.....`..- `-:yyoddyssyhmds-```...-:. ` ````````` ``....`````````
+ `````````` ```````````.....``-- `/-ohhyymmmmmmmmh+-```.-/:` ``......``````
+ ````````` ```````````..-:///-:``` ``.-o/ymmddmmmmmmmmd+-```.:o- .` ``.......`````
+ `````````` `.`````````.---:+s/+/``..-+syhdmhhdh+/yddmmdhdy:```.:+. .:` `.......`````
+ ``````````` ``````````````` `./osss+-.:-.-///sy-oy::o/:ydyhh+.+/::o+--o-.``.```. ````` ``` `` `....`.....```
+ `````..```````````` `` `./oss+s+----///:/o-odd+. .+s:+o/.sso+syhyssoosyys+:. ``````` `` `..` `..```
+ ```.`````````` ` `../+so+o:::.-/:.--:+hmo .++:+osyso+ooo/-...-/o/--` `````` `` ```.```
+ ``` ``````.`` ` `..:oo/` ` `-+:--//+os` ::o+oyo/-+oooo+::+/.` ``..`` `` ``````
+ ``````..`.``` `` `.-// .-./+..:oooo. sso+++o/+ooo++oo: .. ```.` ` ` ```
+ ``` `..` ``` .:://.```//: -+/++:-..:..--.` .-- `.` ````` ````````
+ ``````` ` `````` -..+so////+` .--.-` `-.` ..` ``.--`..`...` ``````````
+ ```````` ```` `````` ` ` .-.-/++o/:/. ..`. `` ` `::/-`````` `` ````````````
+ ```` ```...----..` ````` `` ````````
+ ``` ```
+ `
+ `````
+ `
+ `
+ `.
+ ..
+ `--`
+ `.``
+ .`
+ --
+ `+-
+ .-`
+ .--.` ``
+ ./++/:- ``
+ `/oooooo- `
+ .osssoo/`
+ ` `````````:yyysso`
+ ````````````.oyyyys. `
+ ```````````````..:yyyyy/` ` `` ` ```
+ `````````````.```````...oyyyyy:````` ```` `.``` `
+ ` `````````````.........-::yyyyy+.```..`` `````` ``
+ ` ``````````````.....-------:++shhs:-..``.--`` ````` ``
+ `````````````.........--------:/syhhy::----.--:-`` ````` ``
+ ```````````.``````..........------:::://oyddho//////.:-//.`` ````` ``
+ ```````````````.`...............-----::://+oshmmhh++++++-:::/:.`` ````` `
+ `````````````````.......-.......-.---:::://++osydmmdho+oooo/+/://-.``` ``````` ``
+ `````:/.```.`.```.......----------..---:::///+++ohhdmmmho+osoo+o++++/-.```` ```````` ``````
+ ```````+s-...............----------------::::/+/++ydydmmdho+shs++++++/:..`````` ``.````````` ``
+ ``````../yo-------------:::-:::::::://::::////++++oddodmmdhhyhmmhsssoo+:--......```` `` ````````````` `
+ `````.....:yys::::::::::::////:///++++++++++++//+ooosdhodmmmmddmmmmddmdyo+/:-.``.....` ``` ````` ````````````` `````````
+ ``````..--.--+yyyyyyo///////////////+++o++oooosso+++osssyhsmmmmmmmmmmmmmmmmdh+/:....--..``` ` ````````````` ``````````
+ ``````.//---:/syyhhhhs///////+//////+ooooooooosydhyhysyhysyhmmmmmmmmmmmmmmmmdh+/:-..----...``` ````````````` ``````````
+ ````````.:..-:+yhhhhhyo+//////+/++//+oooooooooooyddddhyhhysydmmmmmmmmmmmddmmmdh+/:....-----.````` `` ` ````````````` ```````````
+ ``` ` `````````...+/:/+hhhhhhs/+++++++++++++ooooooooooooshmdddhhdhydmmmmmmmmmmmmhyymmdh+/-......---..```````` `` ````````````` ```````````
+ ``` ````````````...--:yyyyhhhhhho+++++++++++++oooooooo++oooosmmdmdddddmmmmmmmddmdmmyyshmmdo/:---...-.....````````` ``` ````.```````` ````````..`
+ ` ```````````..-----+yhhhhhhhh+/////://////++++ooo+///++oosmmdddddddmmmmmmddmdddmsosmmmmy//:::-..--.....`````````` ``` ```````````````````.....`
+ ````````````` ` ``..`````..-:::::/syhhhhhhho+++o++++/+++oo+ooso+o+++ssssmmdhdddhhmmmmmmdddddmmysymmmmh+////:-------.........``````` `````````````````````````
+ ````````````` `` ` ````````...--::+ooosyhhhhhhhs++syys+++ooosoosssoossoossssdmhhhhhyhdmmmmmdhyhmmmhsydddhys+///:-----.....-....`````` `.```..``.```````````````
+ `````````````` ` ``````..----:::+ssssyhhdmmdhhsyydds+oooossssssssssyooossshdhyyyhyydmmmmdyysydmmhsssyhs+/::---..```.``---.````````` `.```.````..``````````````
+ `````````````` ` `````..----:://+oooohhhmmmmhhhmmmmsosshhhhhyyssooossooosssddyssyyydmmdmyossoydyo///:-----s/:--.....`.--````````````` `.```.````..``````````````
+ ````````.``````` `` ``...-::-::///+++++ohhdmmmddmmmmmmdhhddhhddhyoohdhdhy+oossyhso+oshdmmmd+:::::+///++:///::+o:-------.....```` ``` `.``..` ``.``````````````
+ ````````..`` `` `` ``...-::/://///++++ohhdmdhmmmmmmmmmmmmdhyyhyo+oyysdho+//:-:://++osdmmmmy++++o+o/::::::----::-.-.```````````` ```` `..`..`````..````````````
+ ```````..`` `` ``...-:////+//++///+::/++syhhhyoo+/:/s/-.....--:////--........--oddmmmd:..---s:`````:````..` ``` `..`..```.....```````````
+ ``````...`` `` `````..--:::::-...`` .:ooo:``...:o:```` ```.` `.:hsyhhds:``...o: ``:-` ```` ``` ````..........```````````
+ `````````` `````````````...----. :/osyo//os+/o:-..` ``...` .```.:/y++os+/+:.`---/-.....` ``..` ```````````````...````````````
+ `````````` ``````````......---- `++yshyyhdddsoo+/-` ...`.` ``.....--.:-.....````` `/---.` `` ````````.....``````````
+ `````````` ``````````......`.-- .osyyshhddddhsys+:.` ..`.` ` ` .```````` `..........````
+ `````````` ``````````......``-- `-oyyyyydmmdddhhy+/.```-`.. ``..........``
+ ````````` ```````````..-:///-:``` ``-:-+hhdmmmmmmmmdhho:`...-.-. ``..........``
+ `````````` ``.`````````.---:+s/+/``..:+ooyddyhdy+oyddmmdydh+:/.`-+..` ``..........``
+ ```````.``` ``````````````` `./osss+-.:--:://sy/dh////:sdyyy+-+::-o/---.```.``.` ````` ``` `` `....`......``
+ ````...```````````` `` `./oss+s+----///:/o/hmd:` .+o-+o/-+///oyhhysoosyys/:. ``````` `` `... ....``
+ ```.``````````` ` `../+so+o:::.-/:.--:sdd+ .o+/+osys+/+oo+:-..-/o/--` `````` ``` `....``
+ ``` `````..`` ` `..:oo/` ` `-+:--//+oy` ::s+oyo/-+sooo+::+/.` ``..`` `` ``````
+ ``````..`..`` ``` `.-// .-./+..:osoo. sso++oo+oooo++oo: .. ```.` ` ` ````````
+ ``` `..` ``` .:://.``.//: -+/++:-`.:..--.` .-- `.` ````` ````````
+ ``````` ` `````` -..+so////+` .-..-` `-.` ..` ``.--`..`...` ```````````
+ ```````` ``.` `````` ` ` .-.-/++o/:/. ..`. `` ` `::/-`````` `` ````````````
+ ```` ```...----..` ````` `` `````````
+ ``` ```
+ `
+ `````
+
+
+
+
+
+
+
+
+
+
+ ``
+ `` ``
+ .`
+ `.`
+ ` `-.-``
+ `` ````.-:o:` `
+ ````````````.:syo...` ``
+ ````````````.```````./hys.-:-.` `` `.``
+ ` ``````````````..```....+hys.+/:--.```` `````
+ ` ```````````````........---.+yys-y//:::.```` ` ```
+ `````````````.......--:---:::--oyyooy/////:-.``` ```` `
+ ./:. ```.``````...........--:////::::/syhyysooho+//:-``` ````
+ `/oo-`````````````.``..`......--..----:/+++/:::+hhhhhyyydyo/+/:..`` ` ``
+ ```:so.`````````````.`.........------::::/++++///+mhhhhhyhmdo++/--..`` ` ````
+ ``..`ss.``````````........----::::---:///:odhoo+///mdhhhhyhdms+o/:---.`` ``````
+ ``-.--/y+-.................---:/::::-://+yydmh+++/:/dmdhhhhhhdh+o+++o:.`````` `````` ``
+ ``./:-/:+yo:-...--------------:/+//:/:/++hdddmsoooo//hddmdhhhhddooyyhh+-..```````` ``````` ```
+ ```.+o///.:yyo/::-:::::::::::::+++++///+yddmmmmysoooosyhhddhhhhhhsoohhhs:-..```````` `````````````
+ ``.-/ssoo:-+yo:::::::::::::::/+ooooo//+osdmmmmmhyysoyhhhhhdhhhhhysoohdhs/:-.---...``` ````````````` `
+ ````.:+syyys+:yy/::::::::::////+oooooo+++ooymmmdddhhhhhhdhhddhhhhsosssymds/:-.:/-....``` ```````` ``` `` ```
+ ````../syyyyysyy+::::::////////ooooooo+++ooohmmdddhdddhhmddmdhhhhsossymmms/:-.:/:......`` ```````` ``` ``````````
+ ` ``````..:oyyhhhhhhho:////////////ooooooo+++oooosdddddddmmddmmmmdhhhhyosshmmmo/:..:/:.....```` ``` ````````````` ```````````
+ `` ````......:oyhhhhhhs//://////////+oooooo//++ooooohdddhdddmmdmmmmdhhhhhosshmmyo+:--::-.--.```````` ` ````````````` ```````````
+ ````````.......--:yhhhhhy:::::/:::::::++oooo///+/+o+++ohddhhhddmmmmdmdyyhhds++smms/:..-::-........```````````` ```````````` ```````````
+ ``````` ``````````....-----:yhhhhhho////+++++//+oossoo++++++oooo+ohhhhyhymmmmhhhhyhhmdoosmmd+---:/::-...--.``````````````` ````````````````` `
+ ````````` ` ``````````..------:+yhhhddhho+++ooosssosyyyoo+++ooo+oooooohhhhyyyhmmmhyyyyyhmmyoohmds:://::::-..-.```...```````` `````````````````````
+ ` `````````` ` ````````...-:::///:oyhhhdhhmhoooossosdhhhhso++++ooo+oo+oooyyyyyssymmmyssossydmmsoohho//::---.```..``.-.``` `````````````````````````
+ ` ``````````` ` ````.`..----:///++/+hhhhdhhdmhsssssooyhhyyso++++oooo++++oossssosshmmmysoooossoo/::://---s:---.`````..`` ` ``````` `````````````````
+ ` `````````` ` ```.---::::::///////ydddhhhdmmdssssoooyhhhysoooyhhhy+++oo+ooo++++dmmmddo/:---://::-////:::-........``````` `````.` ````````````````
+ ``````````` ` ` ``.....---::://+/::/shmmhhhhhmmdyyyyyyhyhhyo//oyyddo/://://///++hmmdmdmy/+++/::::--::..--..``..` ````````` `````.` ````````````````
+ ``````````` `` ````..-----:::://:::-://osysossoooo+::-..--.--:///////-...-...-shdmmmmd+.--.-```` :` ``` `` `````````````````````````
+ `````````` `` ```````..----..``` -++`.//:/os+-`. -` ``.``` ` ``-hyhmmddo:`...:` -.` ``.` `````.```...````````
+ `````````` ``` ``````````.---` `/+o`.-:syyys:..---``...` ` ``..ys+shy//s:....--......` ``..` ``````````````````````
+ ````` ````````````.....--. `+os:---odhyyo+///:.`... `````.-.-/:-.....``` `:---.` `` `````````````````````
+ ``` ````````````...```.. +syyoooshhyyyso+::-.``` `.` ` ````````` ``...`````````
+ ``` ````````````..`.``-. `:shddhyyhhhhhhyo+/:..`.``-` ``...````````
+ ```` ``` ``````..-:::.- `` `---.+hmmmdmmmmmmmhyys:.``--:`` `......``````
+ ``` ````````````...-+o/+/``...-:+ohddmds/:odhmmmhdh+-```./..` `......``````
+ `````` ````````````` `./osos/-.:--:///yhyds/+h/:ohhsy+---:-::----```.``.` ````` ``````` `....`..`````
+ `````````````` `./oss+s/----///:/oshhho. .+s/+o/.:///+yhhhyooosso/:. ``````` `` ``.` `````
+ ````````````` `../+so++:::.-/:.--/yhho .ooo+osyy/:oooo+:..-/o/--` ````` `` ``````
+ ``` ```````` ` `..:oo/` . `-+::-//osy` ::s+oyo/-+sooo+::+/.` ``..`` `` ``````
+ ` ```````` ``` `.-// .-./+..:oooo. sso+oos+ooso++oo: .. ```.` ` ` ``
+ ` `.. ``` .:://.``.//: -+/++:-`.:---:.` .-: `.` ````` ```````
+ ````` ````` -..+so////+` .--.-` `-.` ..` ``.--`..`...` ````````
+ ``````` ```` `````` ` ` --.-+++o/::. ..`. `` ` `::/-`````` `` ``````````
+ `` ```...----..` ````` `` ```````
+ ` ``
+
+ ``
+
+
+
+
+
+
+
+
+
+
+ `
+ `` `
+ ````
+ -``.`
+ ` ..`...`
+ `` `` ``````-..----- `
+ ```.```````````./o++//++`` `
+ ```````...----```````:osssoo++-`. `` ````
+ ` ````````-----:::-..``-ssyyysooo- `` `````
+ `-: ` ` ```````..``.::o+++++/-...:yyyyyssoo/`````` ```
+ ``.:+o...` ``````````.....-/+ydddhs+/---:yyyyyysoso..`..`` ``` `
+ `..-/+o+..`` `` ````.``````...--.-:/ohmmmdy++//::syyyyyysso:-.-..``` ````
+ .-/+oos`.```````````````.``.`....--.--/+shmmmmhsoso::+yyyyyyss+::.--..``` ` ``
+ `-/ooss+..``````````````.`......-:----/ohdmmmmdyyys//+yyhyyyso//:----...`` ````
+ ``./+osys-.```````````......------::/osyhddmmmmdhhhyooooyhhhyyyo+++::-:+/-`` ````
+ ```-+ossys-.................-----:////ydmmmmmmmmdhyyyysoyyyyyhdhyyo++/:s+.````` `````` `
+ `..:ossyyo-.....-------------::://++++odmmmmmmmddyyhyysyyhhhhddhhohhy+y:.....````` ```` ` ``
+ ```.:+syyyyo------::::::::::::::/+++ooooohddddmmmmhhhhyshhhhhhhmdysddhhh/:--::.`````` ``````` `````
+ `````-/osyyyy+---::::::::::://///+ooooooooosyhddmmmdhhhyyhhhhhhhdhysdmdmy/::-/+-....`` ``````` ``` `
+ ````.-//:oyyyy::-:::::::////////+ooooooooooooshdmmmmdhhyyhhhhhhhhmyydmmms//:-:+:.....``` ``````` `` ``
+ ```...-/:+yyhho--:///////+++///+oosssoo+ooooossdmmmmmddhyyhdhhyhhdhydmdh+//:--/-......``` ``````` `` ``````````
+ ` ` `````.....:oyhhhy/::///+oooooooooooosysso++ooo+osddmdmmmmmdhddhhyydddyhhhy///:..::......```` ```` ````````````` ```````````
+ `` ` `````........-+yhhhh+/////ooooooooooooooooss+++++++sdddddmmmmdhdmmhsymmmyhhho+//:-.-:..-...``.````````` ````````````` ```````````
+ `````````.....-.--/yhhhh+:::::+++oo++++++++//+os:///+++sdhhddddmmmyyhhy+ymmmdhhys:--------.....`.--.```````` ``` ``````````` ```````````
+ ```````` ````````...--------/yhhhhs////+oooooooooo+//+++os/+++++oohyyyyyhdmmhsyysssmmmmhhhyo:---::---...---..-:.`````````` `````````````````
+ ````````` ` `````````.--::::::::+hhhhhy++//oosssooooooo+++++osoo+oooooossyyyyhmmdyyysysdmmmdshhys+/:/:----....``.--.````````` ````````````````````
+ ` `````````` ` ``````..---::///////yhhhhhho++/oosssoooosyo+++++oosoosooo++oosyyyhmmdsssoosydmmdsshhy//::--..```````.-.``` `````````````````````````
+ ````````````` ` ````..-::--:::/++++shhhhhhhs+o+osssso+ohddyooo++ooooossoso+ooosyhdmmdssoso+sssoo/:://---+:--..``````.`` `` `````` `````````````````
+ ` `````````` ` ``....-----:///++//yhhhdmdhyoooosssssydmmdysssyhhhhsoooyso+oo++ohmmmh++::----://:---//:....``````````````` ``````` ````````````````
+ ``````````` ` ` ``.....----:/://+++hyhdmmmmmdhysyddddddyhdysoosy+sdo///+/:://++ohmmmdyo:////++//:------..````..` ````````` ``````` ````````````````
+ ``````````` `` ```...-.---::::///:/-://osyyssoshhys+:-.----://::/::::---..--.-ohdmmmds-`...---.` -. .` `````````````````````````
+ `````````` `` ````...---::--.```` `:-` `..`:ssso/:-.-......` ```.ysymmdd+:````.-.` --` `.`` `````.```..````````
+ `````````` ``` ````````..----` `//` `..` .yysso++:-....` ``.yo+yhs//o:.`..-:-.....` `..` ````````````````````
+ ````` ````````````....---- :+-`--.``/yysssoo:---.` `.-.``.:--/:-.....``` `:::-.` ` `````````````````````
+ ````` ```````````....``... -o+---:+ooyyyssoo/---.` ..` ` ..``````` ```...````````
+ ` ```` ```````````.....``-. `.-ossshhhyhhddhhysso/-`` ++.` ``......``````
+ ` ```` ```` ```````..-:::.- ` `:/-./yddhhdmmmmmmmdd+/.```o..` `.......`````
+ ``` ````````````...-+o/+/``.``.:oyhmmmdhohhshhmmddy/-```--..` . `.......`````
+ `````` ````````````` `./osos+-.:--//++dyohhhmh:-+mdyh+---:-:--::-``..``.` ````` ```` `` `....`..`````
+ `````````````` `./oss+s+----/++:+yyhdds. .+ho+o/.:///+syhhhyoosyo/:. ``````` `` ``.` `````
+ `````````````` `../+so++:::.-/:-:-/yhh+ .++/+osyy::ooosso:.-/o/--` ````` `` ``````
+ ``` ```````` ` `..:oo/` . `-+:--//++/ ::s+oyo/-+sooo+::+/.` ``..`` `` ``````
+ ` ```````` ``` `.-// .-./+..:oooo. sso+oos+ooso++oo: .. ```.` ` ` ``
+ `` `.. ``` .:://.``.//: -+/++:-`.:---:.` .-: `.` ```` ````````
+ ````` ````` ...+so//:/+` .-...` `-.` ..` ``.--`..`...` `````````
+ ``````` ```` `````` ` ` ...-/+++:-:. `.`` `` ` `::/-`````` ` ````````````
+ `` ` ```...---...` ```` `` ````````
+ ` ```
+
+ ``
+
+
+
+
+
+
+
+
+ ` ```` :o/ `
+ `......` .oso: `-`
+ `---....` `+sss+.::` `
+ `-------.` /sssso//:` `
+ .--:/---.` `osssso+/:.
+ -oydo----.```` -ssssso+/:`
+ `:yhdy:-:--``````+ssssso+/:`
+ `:ydmd/-::-.````.syyssso/-` `
+ `````:ydmdy:://-....:syysso/-` `
+ `.. ```````./sdmmds+oo/--/++ssys+-.``` ` ````
+ `-/- ` ````````./yhddddhhh/+sos+-/yyo...``` `` `````
+ `-:` `````````````:yhddddddhooyyys//yyy/....`````` ``` `
+ `-:. `````````````..-/ohhdddmdysyyyyys+yyyy+-....`..``` `` `
+ .-::- `````````````.``.``......-/+yhhhdmdhsyyyyyysyyyyy+:::-.-:-``` ` ``
+ `/++/:``````````````````.`..........-/+ohysyhdhyhsyyyyyyyyyhy+:::.-+/.``` ` ``
+ .oso+/.````````````````......----.---+shhs++ohyyysyyhyyyyhhhdy//:-:o+-..`` ````
+ `.+syso/.``````.`..``...-...---------:yddhs/+odhyssyyyhhhhhhhdds+/-/yo--..`` ````
+ ``:syyss+:-.-........-----------------+yso+++oddhysyyyyyyyyyyhdhyy/+yo-..`````` ````` `
+ ```./osyyys+/:---------:::/+/:::/::::::/++++oooddhhyyyyyyyyyyyhmhhyyoys/--....`````` ````` ` ``
+ ````...-oyyyys:--:::://+o+/ooo//+o+//////++ooosodddhdhhhhhhhhyyhmmdhhyyys/::--..`````` ``````` `````
+ ````....-syyyy:::::///+ooooooo++ooo+//////+osoooddhymmdddmhhhyyhmmmhhhhho//::-..`...``` ``````` ````` `
+ ````...-/syyyy/:/:////ooooosso+oooo+/////++oosooysshhmmmmmmdhyyhdmmhhhhy+///:-........```` ``````` `` ``
+ ````....-+yyyhy+:--///+ssssossssssso+///++++oossoo+ohhdmmmmmddyyhddmddhhs+///:--........``` ```````` ``` ``````````
+ ``` ` ``...-...-:yyhhhs////+++sssssossssso+++/+++++ooosoo+oyhhdmmmmhdhhhddmmmdh+++//:-..-......```` ``` ````````````` ```````````
+ ```` ``````````..-------/yhhhs+////++ossssooosso++++////++oooo++++oyyhmmmmdddhhmmmmmmhyo+//::-:----..`````````````` ````````````` ```````````
+ `````````..-:::/:--/yyyyy+//////:+ooo+/++o///+///////+ooo+++///sdmmmmdhddhhmmmmmhhy/-----::-.`````..-:--` ````` `` ``````````` ```````````
+ ````````````` ``` `````...--:::///:::/yyhhhy/////+/+sss+/+oysooo+++syo+oooooo+//+ohmmmmddhssymmmmmhhhy/-------.......``..-``````````` `````````````````
+ ````````````` ` ` `````.----://///////yhhhhs+++++++osso+/+ydhyo++++shyooooosso++osdmmmmmdhooshmmmmhhhhs:::::---....````...`````````` `````````````````````
+ ``````````````` ` ````.-::---///++/+ooyhhhho+++++sosyyo+ohmmdysooosyyysooosyso+oosddmmmdhysosydmmmyyyys//------.``````...```` `````````````````````````
+ ``````````````` ` ``....-----:/++oosyhdddmddysoosyysshhhdmmmdhyysshhyyo+ooysoooooyddmmmyyysoosyyso/+///--......```````.`` ```` `````` ````````````````
+ ```````````````` `` ``.....---::/+o+oosyhmmmmmmmdyyyydddddmmmmmddyyysyyhhooooso+oo+ooshmmdoo/:--:///:::://:-```````````````` `` `````` ````````````````
+ ````````.``` `` `` ``..-..--://///+oooyhddmmmmmmmmmmmmmmmddddhyhooo++///:::::::/+/++oddmmso/////oo+::---:-.-.````..` ````````` ``````` ````````````````
+ ``````````` ` `` ```....--//++//+oo++/:://oyhyyooosysoo+//-.-:--------..........--ohhmmh+-....---.` `-. `.` `````````````````````
+```````...`` `` ````...-://///:-.```` .--.` :s+++/--` `.` ` ``/yshdyh+:` ...--`` `:` ..` `````.```...````````
+ `````````` `````````......----:. ---.` +sooo+:.. `.` ``` `..+s+oys:+s:.`..---.....` .-.` ````````````````````
+ ``````````` `````````....--.--:- ` `----..:sssso+/-.`.--`` `...` `.-.`./--::...-..``` .//:..` ` `````` ```````````````
+ `````````` `.```````.......`.-- ` `---/osssssyssso+/oo/.``--. `` ..``````` ``....````````
+ `````````` ``````````.......`.:- `.`:/+oydyyhdddhhhhyys/.`:/- ``......``````
+ ````````.` `..```````...-:///-:``` `.--../++yhdmmmmmmmmhs+-.`.-.. ` `.......`````
+ ``````.``` ` ``..````````..-.:os+++.`---:+syhhshds+hdydmmmmds/.```-..-. `. `.......`````
+ ```````.``` ```.`````````` `./ossyo:.::-////hyshhhmm+:dmdhh+.--:--.-::-.`..``.` ````` ```` `` `....`....```
+ `````...```````````` `` `./osyos+:---///:/+/shhs. .+s-+o/.:///+oyhhhhyssys+:. ``````` `` ``.` `.```
+ ```..`````````` `` `../+so+o:::..::.---:+o: -+::+osyh//ooosys+--+o/--` ````` `` ``````
+ ```` `````...` `` `..:oo/` ` `-/:--/++/: ::s+oyo/-+sooo+:/+/.` ``..`` `` ``````
+ ``````..`..`` ``` `..:/ .-.//..:oooo. sso+oos+ooso++oo: -. ```.` ` ` ``
+ ` ` ``` `..` ``` .:://.```//: -+/++:-`.:---:.` .-: `.` ````` ````````
+ ``````` `` `````` -..+s+/::/+` .-...` `-.` ..` ``.--`..`...` `````````
+ ```````` ``.` ```````` ` ...-/+++:-:. `.`` `` ` `::/-`````` ```````````
+ ```` `` ```...---...` ```` `` ````````
+ ``` ``
+ `
+ ````
+ `...---.``
+ `...---...
+ `..-----..`
+ `..------.`
+ ..------.`
+ `.------.` ..`
+ `..-----.. ` `//.
+ ..----... -``:+.
+ `.--::.`.` /. `-.
+ .-/o+.``` +.
+ .:shy- `o- ``
+ -/ydh/` `` `/s/ ``
+ :+hdy- ````o-``-/ss+` ` `
+ `-oyh+`````:s+`/sssso` `
+ `-/os:````/sss//ossss/.`
+ `.:os-```./syysoossssso/` `
+ ```.:oo.````-syyyssossssss:`` `` ```
+ ``````./:.```.-+ssssssssssss-``` ``` `.``` ` `
+ ` ```````--.```..-+sssssssssyss:-.``` ``` ````` ``
+ ` ```````````--.....-:+ossssssyyyyso+:-.`````` ``` ``
+ `````````````........--:/oossyyyyyyyysso+++:-.``` ````` `
+ ` ```` `````.``````..........----::/+osyyyyyyyyyysssso/-.```` ````` `
+ -` ``````````````.-..`..............-----:://+osyyyyyhyyyyyyys:--.```` ` ```
+ `` ```````````````-:-......--....----::--:/+//+oyhhhddmyyhhyyys:---..``` ` ````` `
+ ````````.``````````.//:...----:-----:::/++//:+oosydddmmmmhyhhyyyo:::--...`` ```````` ``` `
+ `````.-:..........:+/:-.----::-----://+++oo+:+oosdmmmmmmdyyhhyyo:---.....```` ``.`````````
+ ````````-+:.....---:+++::---::/:::::::/+oooooo//oosdmmmmmmmdyyhhyo/:::----..`````` `````````````
+ ````...```:/..---:::/oo+////:://////////+ooosoo+/+sshmmmmmmmmhhhhyso////::--.```.``` ````````````` `
+ ```````-:``./+---:::::///++///////////////oosoooo+++osymmmmmmmmdhhhhhh+++///:--.....``` ````````````` ```` ```
+ ````....:.--/+--:-::::////+++////////////++osooo++++ssydmmmmmmdmdhhhdmy+++///:--.-....```` ````````````` ``````````
+ ```......-+++/o:---:////////++//////////++++ossyo+/oossyhmmmmmmdddhhhdmhy+++/::...-.....``` ` ````````````` ```````````
+ ``` ``........-sssoo//:::////////++++/+++////+++++ossoo+ssssyydmmmmmddhhhhmmhyo++//-----...-.````` `````````` ````````````` ```````````
+ ```` `` ````...----../yyyyy////////+++/+++++osso+///++++++ooo++osssydmmmmmmdhhhhdmdhhoo+//:::--....``..``.`` `````` ````````````` ```````````
+ ``````..---------:yyyyy/:::::/::::://///soo/+//+ssy+/++oo++++oohmmmmmmmdyyyydmdyys//:----..``````.....` ``````````````````````` ```````````
+ ````````````` ``` `````....-:---:///:syyyy/////+/////+///+yhys+o++oyyhs+oooooo++osdmmmmmmmdysyddmmhyyo/::::--........``````````````````````````````````````` ``
+ ````````````` ` ` `````..-..--:://+soshhhy+++++ooo++ossoshmmdhyooosyyhyooosyyyssyydmmdmmddhhshdmmmdyys/::::::/:-...````...``````````` `````.```````````````````
+ ````````````` ` ` `````......-:/+++syyhddhs+++ossyyshdmmmmmmddhsooyyyyysyyyhhhhdddddmdmdddyyyymmmmhyso//:------.``````.-.````````` `.```.```````````````````
+ `````````````` ` ```......--://++ooyydddhhyossyyydmmmmmmmmmmdhssshyyhhhysosyhhddddhmmmhhdhssyhhyso+/:-------..```````.`` ````` `.```.````````````````````
+ ```````````````` `` ``......-:::::/+oooyydddhmddddhyhmmmmmmmmmmddysyyshhhyysoooossossssdmdoooo/-:oso+++:::........``.``````` ```` `` `.```.` `````````````````
+ ````````.``` `` `` ``.....-:////:/+oosyyddhhmmmmmmmmmmmmmdddhyys+++ossoo+/:::::/+++oshmddyooo+/++++///-------..``..` ````````` ``` `.```.`` ``.`````````````
+```````````` ` `` ```....-://++//++++//--:/oyyyssooyhyso/:::-...-///+//:----.....:+hhhdhho:....-.....` ` `..` ``` `.``..````...````````````
+```````...` `` `````..-//:://:..``` `-- +soo:` .-..`.-..:-. `/hsoyhoy+:``..-.``````` `.-.` `` `````..`.....````````````
+ `````````` `````````.....------. .-- `osso/. -/+/::-.-:-` ``:yo/oys:/y:.`-----.....` .-.` ````````````````.```````````
+ `````````` `````````....-..--:- `--:///+ossso/--/+o+//--:-.` `....:--::...-..```` `//:..` ```````````....```````````
+ `````````` `````````.......`.-- ../yhs:/ssyssssoooo/:.--- `` ..``````` `......`````````
+ `````````` ``````````.......``-- `` ``/ydho+yhdhhhhyyy+-..-.` ``..........``
+ ````````.` `..```````...-:///-:``` `..`.-/yyydmmmmmmmhoo+-``.:..` ``..........``
+ `````````` ` ``.`````````....:os+++.`:::::+oydddhsodmdmmmmds//-```-:.-. ` ``..........``
+ ```````.``` `````````````` `./ossy+:.:--::-:y+:+oomm+/mmdys-.--:--``-:-.``.``..` ````. ```````` ``....`.....```
+ `````...```````````` ` `./osyos+:--.:::-:/-://s. .+s/++/.:////+syhhhhssys+:. ```````` ``` `` `..` `...``
+ ```..`````````` `` `../+so+o:::`.::.-.-::+: -o::+osyh+/ooosss+--+o/--` ``````` `` `...``
+ ``` ``````.`` `` `..:oo/` ` `-/:--/+o/: ::s+oyo/-+soss+:/+/.` ``..`` `` ``````
+ ``````..````` ``` `..:/ .-.//..:osso. sso+oos+ooso++oo: -. ```.`` `` ` `````
+ ` ` ``` `..` ``` .:::/.``.//: -+/++:-`.:---:.` .-: `.` ````` ````````
+ ``````` `` `````` ...+o+/::/+` .-...` `-.` ..` ``.--`..`...` ``````````
+ ```````` ``.` ```````` ` ...-/+++:-:. `.`` `` ` `::/-`````` ``` ````````````
+ ```` `` ` ```.....-...` ```` `` ` ````````
+ ``` ```
+ `
+ ````
+
+
+
+
+ `-:::-
+ `-/+++o/
+ `:+oo++o+` `
+ `:ooooooo:
+ -/osooooo. `
+ `:+ossssso`
+ `:+++ssssso-`` `` ``
+ -oooosssssso+/::+o+. ``
+ `/ssoossssssssssosss+-..`` `
+ `+ssooossssssssssssss+//+.
+ ``.....:+ossssssssssssooo/`
+ ` ```````.:osssssssssssooo:` `
+ `````````````.+sossssssssooo+` `` ```
+ `````````````.`````.+o+sssyssssooo:` ``` `.``` ` ``
+ ` ``````````````.......--:syhhsssooo+-``` ````` ` ``
+ ` `````````...........--....../yhdyyysoo+-.``` ``` ``
+ `````````````..------..---:::----/yddyyyso/-.-.``` ````` ``
+ ` `````..``````....--::::------:++/::/oydmhhyyo/:.--..```` ````` `
+ ` `````````````..`.........-:::://:--::/++++oyhhdmmmyys++----..```` `````
+ `` `````````````````.......-......-::////:::/++ooshdddmmmhyys+-::--....` ``````` `
+ ````````````````````.......---------..-://::+/::/+syyhhhdmmmhyyyo:::::---.`` ```````` ```` `
+ `````````..................-------------:////oo///osysshhhmmmhyyys:::----..`````` ```.````````` ``
+ `````./:.........--------------::::::-::://+++ooooossoohdddmmmhyyyy+//::::--......`` `````````````
+ ````...os/-....----:::::::::///:://///::///++oosoosssssyhdddmmmhhhhhyo+++///:-...--.``` ````````````` `` `
+ ``````...oso-...--:::::::::::///////+//////++++ooooosyyyyyhdddmmdhhhhhhyo++++//:-......``` ````````````` ```` ```
+ ```.....-sso------:-::::///////////+oo+////+++ooooooyyyyhdddhdmmhhhhhhhhyoo+++/:-........``` ````````````` ``````````
+ ```.....-:sss:-:-----://////////+//+sss+//+++++oos++osyydmmdhhdmdhhhhhdmdhooo++/:---....-..`` ``` `````````````` ```````````
+ ``` ` `````......-:+sss:://:/::://////+++++++osso+++++++oooo//+oshmmmmhhdmdhhdmdmmmdsooo++/:::-...--..```` `````````` ````````````` ```````````
+ ```` ` ``````.--..--:/+sss/////////++++++++++++osss+o++oo++oooooo+ossdmmmdhhmdhhdmmmmmdsoo++/:--//-....`..`````````````` ````````````` ```````````
+ `````...----://+syyys////:/+ooo/::////+sssssos++os//+ohddhhhhosdmmdyhddhhhmmmmmdy+/::--.-//:`````..`````` `````````````````````` ```````````
+ `````````````` `` ````....----:/+osysyyyo////+ssss+++sssssyyyyss+++soo+odddhhdmdhdmmmddhddhyhmmmmdhy+//::--/++-.....``````````````````````````````````````````
+ `````````````` ` ` `````......-::/+osyoyyyyso+osyyyyssyhysyyhhyyysooshhysyhddhhdddddmmmmmddddhdmmmmdhyo//::///++:-..`````..``````````` `.```.```````````````````
+ `````````````` ` `````....--:///osyysoyyyhhhyysyyhhsyhssyyhhoyhyyhdhhyhhyhhyydddddddmmmmdddhhmmmmhyy+///:-----.```` `...````````` `.```.````.```````````````
+``````````````` ` `````...-:::+o+syyyyosyhdmmdyyyyddsyhhyhddyoshhydmdhdhhyssosyhdhhhdmmdddhhsyyssso+/:---------.``` `.`` ````````` `.```.````..``````````````
+``````.``..`````` `` ```....-:///++ossyyyysoyhdmmmhhyhmmyyhmddmhyysyhhdmdmhysssooooossohmmdsooso:::/s+o/:::-..---...`.``````` `` `` `.```.` ``.``````````````
+ `````.....`` `` `` ``.....-/++++++oyyyyyysyhdmmmmmmdmmddddhhhhyyooyyyhdyo/::::///+ooydmmdhooso/+++o+//:::------.`..` ````````` ``` `.```.`` ``..````````````
+```````...`` ` `` ``.....-/+++++++ooo++:-::oyyyssoshs+//:-../o+////+oo+/:---.....-+hdddddo+:-..``...-`` `...` ``` `..`..```....````````````
+````......`` ``` ````..-://:::/:..``` `.` `/so:.` .+/:.``--`` `:dyydmhhs/.`...````..`` .... `` ````...`.....````````````
+``````````` `````````.....------:. .-.-:--oso+-` /+/-. `-`` ` `:oy+yds//h/-`--:---....` ---` ``````````````````````````````
+ ``````````` ````````.....-----:- `-ooo/:ossso-``.:+o:.` ..`` ` `.````.---/:...-...```` `++:-.. `` ````````....```````````
+ `````````` `.``````....---...-- `/syysshyyyso++oss:`` ...` ` ..``````` `......`````````
+ ```````..` `````````....-.....:- .osydhddddddyyhdy:.`.::-` ``..........``
+ ```````..` `..``````....-:///-:``` ``.`.-oyyhmmmmmmdhdmd+.``//:`` ``.........```
+ ````````.``` ` ``..```````.....:os+++.`-..-:++ohhyyy+dmmmmmdhsh+.```-.` `` ` ``..........``
+ `````....`````.``````````` `./ossyo:.:-..--:+y:-+hdmsymmyys:.--:-.```...``.``.. ````.````````` ``....`.....```
+ ````.....````````````` `./oss+s+::-.:::-:+.:/yo. .os-/o/.:/+//oosyhhhysys+:. ``````````````` `..` `....``
+ ``...`````````` `` `../+so+o:::`.::.-.-::o/ -o/:+osyho/osssss/--+o/--` `````` ``` `....``
+ ```` ``````.`` `` `..:oo:` ` `-/:--/+o/: ::s+oys/-+soso+:/+/.` ``..`` `` ``````
+ ``````..`.``` ``` `..:/ .-.//..:osso. sso+oos+ooso++oo: -. ```.`` `` `` `````
+ ` ` ``` `..` ``` .:://.``.//: -+/++:-..:..--.` .-: `.` ````` ````````
+ ``````` `` `````` -..+o+/::/+` .-..-` `-.` ..` ``.--`..`...` ``````````
+ ```````` ``.` ```.```` ` .-.-/+++:-:. `.`. `` ` `::/-`````` ``` ````````````
+ ```` `` ` ` ```...---...` ````` `` ````````
+ ``` ```
+ `
+ ````
+
+ `.`
+ .::.`
+ ``-/-`
+ ````` `....````
+ ..` `:+:/:..`
+ ` `` `/oo+o+/-``
+ `.``:+osoooo+//```````
+ `.`/ossssssooo..://-. `
+ `.-osssssssso+oo+/-`
+ .+ssssssssoooo+/. ``
+ `/ssssssssooooo/` ``
+ ```+sssssssso+++o- `
+ ` ``` ````ossss+-:///++:`
+ `` ``````.-..ossss/````.-.`
+ `` `````-++/osssss:` `
+ `` ````````:ooossssss:`` `` `
+ ```````````````````/s+ossssss:````` ``` `.``` `
+ ` ````````````.```.../so+ssssss:```.``` ````` ``
+ ` ````````.``............+so+sssyss/.``.`````` ``` ``
+ ````````````.....--...-:::::oosossshss+:-.-.````` ````` `
+ ````````````...-----:---:++++oyooosssyssso:.--..```` ```` `
+ ``````````````````..``...----:::--+oooyy+++osyyyyso/----...`` `````
+ ```````` ``````````````.`............---:///::/osshy+//+yyyyyyo/-::---..``` ``````
+ `.....``````````````........----.....---:/+/:::ossssoo++syyyyys/:::::--..``` ```````` `` `
+ `.:/+:.``....................-----...---::++::/oooooo/:/yyyssss/:::----..`````` ``.`````````
+ ```:+o/.``.......-----------------------:///+/+oossss+//+dyyyyyyo///::::--......``` `````````````
+ ``````-/+.``....----:::::::::::::::/:::::::/+/+o+ooossys+++oddhyyyyy++++///::-.....```` ````````````` `
+ ```````:+/.`...--::::::::::::::::///////////++oooooossyhh+++oddhyyyyyo++++///:-----.````` ````````````` ` ``
+ ````````-+/-------:-:/:::::://///////////////ooooooossyhdy+oosmdhyyyyyyoo+++///:--//:...```` ````````````` ``````````
+ ``````````./++//:-----/++////////////++///////+oossooosshddysyyymddhdhyyyyoo+++//:-:++:.....`` ` ````````` ``` ```````````
+ ``` ```````....--+sss+/:/::+ooo++////++//oss+//////+ossysoossyhmddhyyddddhhdyyysoo++//:-/++:`.....```` ` ````````````` ```````````
+ ``` ````````..:+++:-/syyyo////+ossso+++++++osssso///+ooosyhyoossshhmmmmdddddhhmdyyyo++//:--//+:...```.```` ``` ````````````` ```````````
+ ````````-::+ssooosyyyyo/////ooo+:/+ooooooooo///:+yhyssoo++o+ohdmmmmdhdmmhdmmyyyyo/--..:///:````````````` ```` `````````````` ```````````
+ ```````````` `` ``````....+++sssss+yyyyhs+++ossso/ossyyhyo+o+oyyshdhhyyyso+o+ohmmmmmdmmmmhhmmhhhyyso+oyho+/:......``````````````````````````````````````` `
+ ````````````` ` ` ``````...-/ooosyy+/oyyhhhyossyyys+ysyhddyoos+sdddddhyyhhysoooohhdmmddmmmdyymmdhhyyssyhdds+:--...`` ```````````` ````````````````````````
+ ````````````` ` ``````..-:/+osssyyo++oyhhhdhsshhyooyhhdhhhsyhsshddmdhoyhysooooohyhddhmmddhyydmmhyooosoo+/---.````` `..` ``` ``` `````.```````````````````
+ ````````````` ` ``````.---:/o+ssyyyyoosyhhdhyyhmyssyyddddhhhhssydmmmysyysoooooyysydhmmdhhysyyso//:--....--:--.``` ```` ``````` ``````````````````````````
+ ```````````````` `` `````.-:/::///+ooyyhhyoyhhddyyymdyyyssydmhhhhyyyhdmmhsosooooo+o+syhmdh+o+/::///:/:-::....-..-.``````` ` ` `````.` ````````````````
+ ```````````` `` `` ````..-/+////++ooosymhydmdmmmmdmhhdhysyyddhhyoyyyhdyyo/::::///++sdmmyyooo+/++//:::---..--.`....` ``````` `````.`` ``.`````````````
+ ``````````` `` ``````-/+/////++o+//--::oshhhhhyo/:----..-+o:-//+so+/:---.....-+ddmm+ys+:....-...-` ..`` ``` `````.````..`````````````
+```````...`` `` ``````.------:.``` .-+++oo:` `:+/` ```.-` -ohymmyhy/``-.--```.. `...`` `````..`....```````````
+ `````````` ``````````........--. :/ssyys+- `+o+:`` `... `` -:soshs++h/.`----......` ---.`` ``````````````````````````
+ ` `````` ``````````......--:- ./oddmddyo:..:+oos:` ..-` `` ``````.--::.....```` .+o+:-.` `` ``````````````````````
+ `````````` ``````````......`.-- /:ymmmmmdhyossyho.` .:-. ` ` ...````` ``....`````````
+ `````````` ```````````.....``-- .-/hmmmmmmddmmdh/-..`++.` ``......``````
+ `````````` ````````````.-:///-:``` ``...:oyhmmmmmmddmmds/-.``/: ` ` `.......`````
+ ```````` `.`````````....:os+o+.`-...-/:sdhsdhosdmmmdhdy+-.````` ` `.......`````
+ ``````````` ````````````` `./oysyo:.:-..:sohd+:s/ohysmdssy-`--:-.```..`...``.. ````. ``````` ``....`...````
+ ` ````.``````````` ` `./osyos+::--://-/s:/oo/. .os-+o/.:/+//+ooyyhyssss+:. ``````` `` `..` `````
+ `````````````` ` `../+so+o:::.-/:.---:/s/ -o+:+osyh+/oyysso:--+o/--` `````` `` ``````
+ ``` ````````` ` `..:oo/` . `-/:--/++// ::s+oys/-+soss+::+/.` ``..`` `` ``````
+ ``````.`````` ` ` `..:/ .-.//..:osso. sso+oss+ooso++oo: .. ```.` ` ` ``` `
+ ``` `..` ``` .:://.``.//: -+/++/:..:..--.` .-: `.` ````` ````````
+ ``````` `` `````` -..+s+/::/+` .--.-` `-.` ..` ```--`..`...` `````````
+ ```````` ``.` ```````` ` .-.-/+++/:/. ..`. `` ` `::/-`````` `` ```````````
+ ```` `` ` ````...----...` ````` `` ````````
+ `` ```
+ `
+ ````
+ -:/++//.
+ :++++/+.
+ `/+ooo++..:.
+ -ooooo+-:+.
+ `.+ooooo:+o.
+ `.+ossso+oo.
+ .+ssssooo+`
+ .osssssss+` `
+ :osssssso/ `` `
+ `+osssssso:
+ `.ossssssso- ` ``
+ ``+ossssssso` ``
+ ` ````ossssssss+``
+ ```` ``.```/ssssssss+``
+ `..```.----/ssssssss+.`
+ ``-:---:////:ossssssso:`` `
+ `````````::://///++sysssssso+.`` ``` `` ```
+ ```````````-////++++++sssssssoo:```` ` ``` `.``` ` `
+ `````````````.//+++++++:+ssssssso/`..```` ````` ` ``
+ ` ```````````.....:++++++oo::osssssso:...```` ``` ``
+ ````````````.......-::/+oooooo::osssssss:.--..``` ````` `
+ ```````````......---:///+oooooo::osssssss/-::-..``` ```` `
+ ````````````````...`......---:++++oooss+::osyyyyyso::::-..``` ` ```
+ ``````````````.`..............-:/++o+oossss///ossyyyyys:::::--..```-. ```````
+ ``` ```````````````.......-----.......-/++oooosssso///oysyyyyys////::--.```-/- ```````` ``` `
+ ```````````.................--------.---/+ooooooooo+:::/syyyssss//::::--.``./+/`` ``.`````````
+ ```````````......-----------------------:+ossoossooo+////oyyyyyyy+///::::---/+++.``` `````````````
+ ````..`````...-----::::::::::::::::::::::+osssoossssooss++osyyyyyys+++////:-/+o++.```` ````````````` `
+ ``````.--```...---::::::::::::::///////////+osssoossssssyysooyshyyyyyo+++////+++++/.```` ````````````` ` ``
+ ``....`.-::-....--:-://///://///////++///////oossooosyssssyyyooyydhyyyyso+++//+o+///:...```` ````````````` ``````````
+ ``.::/..-/++/-------:/+o++///++////+oo++/++o++sssooossssyhhyysoyydmhhyyyso+++/oo+//:......``` ````````````` ```````````
+ `` `` .`-/+/../osss/::::://+soo+/+sss+///oso++/oyyosso+oosssyhddhysshhdmmhysyyso+++ooo/:.``......``` ````````````` ```````````
+ ``` `````...//---/syyyo//////+sso++sssssoosys++++shdyyoo++oosssyddhhysdmddmmhysyyysoohdds-.....``..```` ` ````````````` ```````````
+ `````..:/:++++syyy+/:///+oo/:+ooooo++yy+/+/+ssyyo++++++++++hhhyshmmshmmhysyyyssydmh+-..````````````` ` `` `````````````` ```````````
+ ````````` `` `````...--:++osss/syy+///++sso//osooo//+ys++o++sssooooooooshyyhyddddmdsymmmhyyyyyyydyo::--......``````````````````````````````````````` ``
+ ```````````` ` ```..--:::/osyyy/+yho+++osyssosssoo+++sysooooosssoooosysshhhhyddmdhdhyydmmhyyyyysoyo+/:----..`` ````````````` `````.```````````````````
+ ````````````` ` ``...----:/+oyyy++yhhysooyhsssysso/+++yyyysssssssooosyysshhhhyhdmdhhyyyhmmdyssso+/+///::-.```` `..` ``` ``` `````.```````````````````
+ `````````````` ` `````....----:+++shhssoyhhhddhhysyyyssoooyhyddsssssso++osyyssyysyyhmmdhyyssyysyo:/:-....:::::-.`` ```` `` ``` `````.````````````````````
+ ```````````````` ` `````.:::::://+oooyhhsshdddmmmmhyyyyymmdhhhhdhyyysyso+++osoosoo+sydmmdooo+/:////:--:-.........````````` ` `````.` ````````````````
+ ``````````` `` `` `````.:/::///++oosoydosdmmmmmmmmdyhydmdhddhysoo++ssyho:::::/+/++ydmmddooso++++///---...-.......` ``````` .` `````.`` ``.`````````````
+ ``````````` `` `````.::/:::://+++::..-:oyddhso++/:----.:o+/----//:/+/-----...-:hdmmhds+:.--.:...` `...` `` `````.````...````````````
+ ``````..`` `` `````....----.`` `/yhs/` .:++/- .--` ` `+hhdddhh+``...:...` .-..`` `````..`....````````` `
+ `````````` ``````````........-. -yhhs/-`.``.:+oo++. `--. `` `-sosyo:/d/-`.--:-.....` -::..` ````````````````````````
+ ` ```````` ``````````......---- `+hddhsoosyysssss+.`````-:: `` ``.--:-.....```` `/os/:-`` ` ``````````.```````````
+ ` ```````` ``````````......`.-- `.shdddddddddddhh+:--.`./:` ` ...````` ``....`````````
+ `````````` ``````````......``-- ``-ddmmmmddmmmmdy+:-.``-- `. ``......``````
+ ````````` ````````````..-///-: `` ``..--/ohmmmmmmmmmmdy+-.````` ` `.......`````
+ ```````` ```````````````-+o/++.`-.``:+shmhyydhhdmmmmmds:.```` ` `.......`````
+ ``````````` ``````````` `./oysyo:.:-..:o/sd//ooohy+mdyhy:.--:-.```..`...``.. ````. ``````` `....`..`````
+ ` ``````````````` `./osy+s+:--.:/:-:o://:-. .oy-+o/.:/+/+ooosyyssoso+:. ``````` `` ``.` `````
+ `````````````` `../+so++:::.-/:.---::/. :s+:+osyh+/syyyyo:--+o/--` `````` `` ``````
+ ``` ````````` ` `..:oo/` . `-/:--/++/: `::s+oys/-+soss+::+/.` ``..`` `` ``````
+ ``````.`````` ` `..:/ .--//..:osso. sso+oos+ooso++oo: .. ` `.` ` ` `
+ `` `.` ``` .:://.``.//: -+/++/:..:..-:.` .-: `.` ````` ``````
+ ``````` `````` -..+s+/://+` .--.-` `-.` ..` ```--`..`...` ` `````````
+ ```````` ``` ```````` ` --.-+++o/:/. ..`.` `` ` `::/-`````` ```````````
+ ``` ````..-----.-.` ````` `` ````````
+ `` `
+
+ ``
+ ```:-`/-
+ `--:/.`+.
+ -//+/`.+`
+ `://:` -/
+ `.` +-
+ `.` `+`
+ `--` `/
+ `-::.` .
+ .///-`
+ . -/+/:`
+ ``` -+++/`
+ .-- :+//+`` `
+ -:- -/.-o/-`
+ ``` :/-````-./oo+.
+ `.--::` ``///::::-/oooo-
+ `-::::. `-//////:-+ooo+:
+ `.:::/:.`.///////-.ooo++/ `
+ `.:////-..-::////.`oooooo. ```
+ ` .:////:--`.:///:..ossooo/````` ```
+ ````````:///+/:::-///:-.+sssssso.```` ` ``
+ ` `````````````-/++++////+:-...+sssssss:...``` -` ``
+ `````````````...../++++++++/:-.../sssssss+.-..``` `:- ``
+ ``````````````...../++++++++++/:--:sssssss/.---.``` .::` `
+ ````````````.``......````..../++++++++++++:::ossssss/----...`` -::- ``
+ ````````````...................:++oooooo+++/:::+ssssss:-----...```:/-` ````
+ ````````````.`.........................:+ooo+++++++:---:ssssss:-/-.....``:/:`` ```
+ ```````````......-----------------------:oooooo+++++/:::+sssssso/o+--....://.``` ``
+ ``````````...---::::::::::::::::::::::::/ooo+oooo+++////oyyyyyyssso:::--/++-````` `
+ `````````...----:///::::://::::::/:::::://+ooo+oooo++///+syyhyyyyyyo/::::++:```````` `
+ ````.```...----:://///::/oo+/::::/::::////+oo++sosooo+/++osshhyyyyys//:/+o/.````````` ````
+ ```.--...-------:////+///+sss+/////:://+//++oooosoosoosooosyyyhhhyyyy+//ooo/```````````` `````` `
+ ` ```.-/+:--::::::::/++++++oosso//////////oo+++osoydhhhysyysoyhdyhhhyyyys//ooo/..``````````` ``````` `
+ `` `````.---+oo:::+///////+sssssssss/////+/////+++++hdhyddhmdyhhyshddsydhyyyyyy++oo+h+.`````````` `````````` ````````
+ ```..---../oo:-/o+:::///ooooooooo+::::/+/::::::/++hdddddhdmhhhyyddh+sdhyyyyy+/:++//:.`````` `` ```````` ````````
+ ```````` ` ````..------:+o/:oyysss//+sssssssyho+/://+////+://++yddddhhdmhhhhddmy+sddyhhss//:/+/:--..`````` `` ``````````
+ `````````` ` ```.....-::::+ssoyyyhhhs+osssssysyyyso++++++++o//+++shhhyhhdhhhhhddmsosymdmdsy+/::++/:--....`` ``` ````````````
+ ````````````` ` `......-:/+//+syshhhhhhhyyyyyyyyyyyhyso++oosooo+//++sysssyhhosdddmddyosydmmdyo+/:-:::----.``` `.` `````````````
+ ````````````` ` ````.....--:++++oyhssyhhhhdmhyyyyhdmdhhhs++oshsyssso//++oo+ooss+oyydmdhyooshsso:--.`.........`` ``` `````` ````` ``
+ ````````````` ` `````.----:///+oosyhsyyddddmmmdmmdmmmmdhhyysyhyhddhhhs+++o+++//++sydmdsso-::+-:/---.--````.```````` `` `````` ```` `
+ ``````````` `` ` `````-::://///+osssyoydmmmmmmmmmmmdmmmdhdddyo+o++//ohs/:::::////syhmmmyo+:+/o:::--..`.:-```````` `` .` `````` `````
+ ``````````` `` `````.--:--:://+++/:..-/yhhhyyyoo///::/+++o+-.-.-.://::--.....--sydmmdh+..-.-...` `-.` ```````````````
+ `````````` `` ````.....----.`` :o/::::-.-:/-:////o+.` `.` .. ` :syddsoh/```..:```` -.```` ````````````````
+ `````````` ``` ````````....---` `oo++///+ooys+++++y/.``` ` .- .o+sy+-/h/.`..-:..`..`` -:-..` `````````````````
+ ` ````` ``````````......---- ``+shhhyyhhhyyssoss:-.```` ``` `.--:-.....```` `/ss+/:.` ```````````
+ ``````` ``````````......`.-- `.odmddhddhhhyssy/-.```` ` ....```` `````````````
+ ```````` ```````````.....``-- ``:dmmmdmmmddhhs/-..``` `` ````````````
+ ``````` ````````````..-///-: `` `.---/+odmmmmmmmmddy:..``` ` ``.`````````
+ ```````` ```````````````-+o/++``-..:syyyddhdmhymmmmmmmmy.``` ` ````````````
+ ` ```````` ``````````` `./ossy+-.:-..---yd++/:+hhodh+sy:.--:-.```..`...```. ````. ``````` `````````````
+ ``````````````` `./osy+s+---.:/:-/s://.-.`.oy-+o/.:/+/+ooosyssooso+:. ``````` `` ```` `````
+ `````````````` `../+so++:::.-/:.---::/. :s+:+osyy//syyss+---+o/--` `````` ` ``````
+ ``` ```````` ` `..:oo:` . `-/:--/++/: ::s+oys/-+soss+::+/.` ``..`` ` ```
+ ```` `.`````` ` `..:/ .--//..:osso. sso+oss+ooso++oo: .. ` `.` `
+ ` `.` ``` .:://.``.//: -+/++/:..:..-:.` .-: `.` ````` ````
+ ``````` `````` -..+s+/://+` .--.-` `-.` ..` ```--`..`...` ``````
+ ```````` ``` ```````` ` ----+++o/:/. ....` `` ` `::/-`````` ` ```````
+ `` ````..-----.-.` ```.` `` ````
+ `
+
+ `
+
+
+
+
+
+ .
+ `.-` ..
+ .--:.` `:+o:
+ --::-... `+ooo+`
+ .::/:---. :oooo+`
+ .::/:::::` .+oooo+` `
+ `.:///:::::` `:ooooo/ `
+ `-:////:///.`` `+ooooo-
+ .://///////...`` .+ooooo.
+ .://///////..-.```+ooooo``
+ .-////+/////---````ooooo+``
+ `:///////////::-```-ooooo+```` ` `
+ ````.//////++//////-```:ooooo+`````` ```
+ `````//////++++++++:``.:osooo+-.`.``` ````
+ ` ````````-/+///++++++++/...:ssssoo++...``` ``
+ ` ````````````/++////++++++/:.-/sssssooo+-.```` ``
+ ````````````....-++//+/++///+/:--/ssssssoso:-..``` ``
+ ``````````````````.....:+/:+++//+++:---/sssssssso---..``` ``
+ ````````````.``......``....../+//+///+oo/:::/sssssssso---...`` ` ```
+ ```````````....`...............-/::::++ooo+/::/sssssssso:----...`` ` ````
+ ````````````.........................-----:/++oo+:---ossssssso---....``````` `````
+ ``````````.......------:----------------:::-/+ooooo+:::+ssssssso::----....````` ```
+ ``````````..-----://///+o+::::::::::::::/+/:::oyysooo+/+osyhysss+///:::--..`````` ``````` ```
+ `````````...----::/ooooooo+/:::::::::::/+syy//+yhhysss++ossddysss++//::::-.````````` ``````` `
+ ````````....--::::/+osoosso+/:::::::::://+yyysssyhdhyssoossymhsyys+++//++::-`````````` ``````` ` `
+ `````````.------+o:/+ossssss+///://::::////+ohhyhhhhhdhysssssdmhyyyy+++///ooo+.``````.```` `````` `` `` ```
+ ```..`````..-/:/+sss//+osssss++///////:://////+hhyhdhhddhdyyyysddhyyyyo+++//+oo+/.`````..```` ```````` ``` ``````````
+ ` ```....```..-/osyyyys/+ossssss++////////:::////+ohyydhhhhhdmhyyydhyhyyhhooo+/ooo++-``````````` ````````````` ```````````
+ ```.........:+syyyyyyyoooooo+o//+::::::/:::--::/+++ssyyhhyhdmmdyydyohdydmyo+/:/++/::.````````` ````````` ``````````
+ ``````` ```...----:--/osyyyyyydssssso/+///:::::/+//+::+//++o+oooshshhdmmhdhyosmdmmds+///+o+:::-..`````` ``` ````````````` `
+ ````````` ` ``````.::::-::://+oosyhdhyhhyo+++//++///+++oo/+ssooooooossyssyhdmddhhssdmmmhhyso+++o/::---..`` ``` `````````````````
+ `````````` ` ``````-:////:///++oo+ydmdydddyosy/+ss+o++ooss/sssso+oooooosoosyhmdhhhyshmmdsosso++/:---....`` `.` ````````````````````````
+ ````````````` ` ```...:///++o+//+syhsymmmdddmdmmh/+yysyhsoyosossssosooo+++oooyyhmmdhhs+shss+--......-...````` ``` ``````` ``````` `` ````
+ ```````````` ` ````..-.-:::/+oosso+ohdhymmmmmmmmmmmosyyhmdyyssshhhssos+++++////osdmmyoo/--/-//---.--..```````````` `````` ``````` ```
+ ``````````` ` ` `````.---:::://+osyyoohddhdmmmmmmmmmmdhsyhdhoooo+//+o/:+:::::///+ydmmdss+////::----.`.-..``````` `` ` `````` ``````` ` ```
+ ``````````` ` ````.------://////:..-+osyyhhyhys+/:::--:+/-------:---:-.....-:ohmmmds+....`-.`` ` -` ``` ````````````````
+ `````````` `` ```..------.` `/-.-osssyo:-..```-:-.` . `+sdddyyy/``..`-`` `` -````` ``````````````````
+ `````````` ``` ````````....-.` `+/+yddhhyo+/-.`.:-`` `` .oosho:/y/.`...-..`..`` `:--..` ````````````````````
+ ````` ```````````.....---. .`+oydmdhhssso-.--``` ``` `-.-::.....```` `+so++/-`` ``````````````
+ `````` ```````````.....`..- ``./sdmmddhddh:-:-.`` `` ` ....```` ````.`````````
+ `` ```` ``` ```````.....``-. `-.-shdmmmdmmms/:-.```` ``..`````````
+ `` ```` ``` ``````..-://.: ` ``.-::+shmmddmmmmmmds:-```` ` ``..``.``````
+ ` ```` ```` ` ````````-+o/+/``-..:+++odhhydydmmmmmmmh+-``` `. ``.....``````
+ ` `````` ``````````` `.:ossy+-.:-..--:yd/:::oyyydhydh+.--:-.``...-.`.```. ````. ```````` `````````````
+ ````````````` `./osy+s+---.://-/s://-:``-oy:+o/.:///+sysyysoooso/:. ``````` ``` `` ```` `````
+ ````````````` `../+so++-::.-/:.--:::/- :s+:+osyh//oyyys+---+o/--` `````` `` ``````
+ ``` ```````` ` `..:oo:` .``-/:--/++/: ::sooyo+-+soss+::+/.` ``..`` ` ``````
+ `` ```````` ` `..:/ .--/+..:osso. ssoooss+oosooooo: .. ` `.`` ` `
+ ` `.` ``` .:///.``.//: -+/++/:..:..-:-` .-: `.` ````` `````
+ ````` `````` -..+s+/://+` .--.-` `-.` ..` ```--`..`...` ````````
+ ``````` ``` ```````` ` ----+++o/:/. ....` `` ` `::/-`````` ` `````````
+ `` ````.------.-.` .``.` `` ```````
+
+
+
+ `-::::--` /+/`
+ .-:::::--` /o+:`
+ `.-::/:::::. /o+/:.
+ `.-:::/:::::. /oo+/.
+ `-:::/::::::- `+oo++.
+ `--::/::::::- .+ooo+.
+ .-:::::::::- -oooo+`
+ `.::::::::: `-/+o/
+ ::::::-:: ` `-+.
+ -::::---:` `.//`
+ ----.` `` ````+o/` `` `
+ `` `--`:oo/.`` `
+ ``.+/.+oo/:.`
+ `` `````````/oo+ooo+/-``
+ ``` `````````+oooooo+//.`
+ ``` ``````...+oooooo++/-``
+ ` ````````....+ooooooo+/-``` ``
+ ```````````.`````..::-ooooooooo+-``` ```
+ ```````````.......-+ooooooooooo+:.```` `````
+ ``````````......-::-+oooooooooo++-.``` ```
+ ` ```````````......--:::-/ooooooooo++/-..``` ``
+ ````````````..........---::::-ooooooooo+/.--..``` ` ``
+ ``````````````........---:////:/osssssso::.---.```` ` ` ```
+ ```````````...``````......--::+++/++ossssssso::----...`` ` ````
+ ```````````````.................--::/oo++oosssssyyso::-----...`` `````
+ ``````.-.````.......-..............----::/oo+sysssoosyhso:-----...``````` `````
+ ````-//-....--...--/-.-----------/+//::/+ssosyysssoyddss+:::::---....````` ```` `
+ `` ```.+o:.----:----:+------------:+osssoooyysyyhsssshddyss////::/+o+-```````` ``````` ```
+ ` ````.+o+----::----::--::::::::::::/osyhhyhhyhhhyssyhddyss+////:osso/.` `````` ``````` ``
+ `````..-os+---::::::::::::::::::::::/++++syyyhhhddhysydhdyyyo+////+sss+.`````````` ``````` ` ``
+ `` ```....:oo:-:::::::::::::::::::::::/oo+o//+++yhdmmdhssdddhyyyo+////sso+.``````.```` ``````` `` `` ```
+ ``````` ```..-::+so://:::::::::::::::/::::/oooo+o+++++oyddmddysdddddhyhyo///ooo+:`````...```` ```````` ``` ``````````
+ ` ```````````..-::/ssoso:://::://:::::///:::osso++++++sooyddddhyshhdddhhdhyo++ooo+/.``````````` ````````````` `````````
+ ````.....```.-.----/s+os+/:--:::----:////--:oooos+++oos++oyyyyssoyyyhmhhhhssooo+/:+o+-```````` ````````` ``````````
+ ` ` ```.--..-...-//:--::ooydhhhsoo/:::::/o/++:::+ssohso+ossooosoosssyyhyhmmmhhyssso+/:osss-.`...`` ```` ```````````
+ ``` ``` ```.---------:oo::::oddmmmmmhyo::://+s++o++/sssoyyoosyssoossohdddhhyydmmdyyyssoo++osss:--..` ```` ```````````````````
+ ```````` ` ````.--:://--::yyo://smmmmmmmho/::///+yyysssssosoyyooysso+ooohmmmddyyyhmmmyosso+/+/:--...``` `.` ````````````````````````
+ ` ````````` ` ````.---://+/:::+yyssoymmmmmmmd+/::/++sddhhyydhsooss+oooo+++oyddmmhhysoshso/.--//-..-..`````` ``` ``````` ````````````````
+ ` ````````` ` ```..----////++//syyyhdmmmmmmmmy/::/+shdhhydddysooo+//++/:///yhmmdyoo/--:::---:--:-.```````````` `````` ```````````````
+ ` ```````` ` `````..-----::/:/o++ohyhhmmmmmmmmmds+ooyhhyo++//+/+o+:::::::://ohmmdhos+//:::----/...-:.``````` ``` `````` ``````` ``````
+ `````````` ` ````..----:::/:::-`.-:+syyhddyhhso+++//+:-.---:--/-----.....-:shmmhyo+--..```` . .. `````````````````` ``` `
+ `````````` `.......--`` ``-/hhoyhyys+://:`` `.osddmdhs+....``` `` -` ````````````````````
+ ````````` `` ``````......` .:+yhsyhddho://-.` ` `oosyhs+:o/-`...-..`...` `-....` ````````````````````
+ `` ```` `````........ ` `:osyshhdmdo:/:--. `` `.:.-::.....```` .oso+++:.` `` `````````````
+ ``` ``` ```````..```.. ``-/+soydddmdo::::-. ` .....```` ``````````````
+ `` ``` `````..````-. `.-/++sshmmmmms////-```` ```.`````````
+ ``` `` `````.-:::.: ` `..-+yddddmmmmmmmho///.``` ` ``..``.``````
+ ``` ``` ``````-+o/+/``.```.-/hmhsoydmddmmmmmdo/.`` .` ``.....``````
+ ````` ``` `.:osss+-.--..--:hd/-/oooyhdyhddo.--:-.``..--``.```.` ````. ```````` ``.``````````
+ ````````````` `.:+ss+s/---.:/:-/s//++:``:sy:+o/.:///oyyyyyoooooo/:. ``````` ``` ```` `````
+ ````````` `../+so++-::.-/:.---::+: :so/ossyh//oosyyo-.-+o/--` `````` ` ``````
+ `` ``````` `..:oo:` .``-/:--//+:- ::sooyo+-+soss+::+/.` ``..`` ` ``````
+ ` ```````` `..:/ .-.//..:osso. ssoooss+oosooooo: .. ` `.`` `` `
+ `.` ``` .:://.`..//: -+/++/:..:..-:.` .-: `.` ``` ` ``````
+ ``` ```` -..+s+/::/+` .--.-` `-.` ..` ```--`..`.`.` ````````
+ `` `` `````` ` ` .-.-/+++/:/. ..`.` `` ` `::/-`````` ` `````````
+ ```...----...` .```` ` `` ```````
+ `
+
+
+
+
+ `.
+ `.`-+:
+ :/:+++:`
+ `-++/+o++/
+ `-/+o+++o+++.
+ :++oo++oo+++-
+ /oooo++oo+++-
+ /oooo+ooo+++-
+ /oooo+ooo+++- `
+ /oooooooo+++` `
+ :ooooooo+++/
+ `` ```.-.```/oooooo+/+-
+ ``````-++-``-ooooo+///`
+ ` ```..--:sy+..:oooo+.`--
+ ``````..--::ydo+/ooooo/` ``
+ ````````````--:::/odoooooooo/`` `` ```
+ ```````````.-:///+yhoooooooo/``````` `````
+ ` ````````````...-:/+++ddsooooooo/.``````` ```
+ ````````````........-::/++ohdysoooooo/-..`..``` ``
+ ```````````..........-::/++oyddssooooo/:--.-..``` ` ``
+ ``````````````````.```......-.--://++osdmyssssss+:::.--..``` ` ``
+ ``````````````.`............../+:--::/ooosddysssssso:::.---...`` ````
+ ``.`````````........----....-:/++/--:/+oooshdysssssss+::-----...`` ````
+ `````....................------://++++--:+++oooydyssssssso-----.....`````` ````` `
+ ````````......------------------:oo+oooso+osoooosshyssssyyss/::-----::.``````` ```` `
+ `````````...----::::::::::::::::::osssossssosyysssssyyyssyyhyys///::://:-.` ````` ``````` ```
+ ` ```````...---:::::::::://////////ssssssossoshhhhysysyyhdhhdhyy++///::::-.`` `````` ``````` ``
+ `` ```````..--:-:-:/::///////////////ossssssooo+shddhysssydmmhhddyhso+/////::://.``.````` ``````` `` ``
+ ``` ```..---/s+//++ooooo+//////////+sysyyssssoshdddsooyhmmmdhddhmdyo+oo++//+ooo:`....``` ``````` `` ` ````
+ ` ```````..-:://ssssyyysyss++//////////sssysssssosddhhyoohhmmddhddhmmhyyyys+/+oooo+.`...```` ```````` ``` `````````
+ ``` ````....``...--:///syyymmhyyso+++/////////+ssssysoooydhhhysyhhdmdhydddmmhyyyyss+osooo+```````` ````````````` ``````````
+ ``.--......---/////oyyymmmmmdso/::::://////:://oyoosydhhhsooyhhddhhhdmmmdyyysoo+sssooo.``````` ````````` ``````````
+ ````````` ``.---------:::/sssssyddmmmmmdyo+///////++++//:/ossyyydhysoosydddhyhhdmmmmhyyyosssssso/:....``` ``` ````````````
+ ``````````` ` ``.----:::::::/+syyyydmmmmhdmho+//++++++hysoo+/+ohhysyhysoosyhdddhhhyhmmmdhyyyssyysoo+::--..` ```` ```````````````````
+ ````````````` ` ``.---://+/////oyhhhddmmmmdhmdhy//+++o+ymmmhy+++ohysssyysooshmdmdyyhsydmmdhssys+oo/:....```` `.` ````````````````````````
+ ````````````` ` ``````.-:::///+///++syhhdmmmmmmhmmmho++++shddhmhyys+oysossysysshddmmhhys+oyhso/:/+++/--...`````` `` ``````` ````````````````
+ ````````````` ` `````..--::::////++++yhddmmmmmmmdmmmmhss+syhdyhddhyo+osoooooo/++syhmdhso/--:+/:--:/-:::.```````````` `````` ````````` ``````
+ ``````````` ` ` `````.----::////++ossyhmmmmmmmmmmmmmmddhhhdho+o+/+////::::::::/+yhmmhhoos+/://:---:-..-/.``````` `` `````` ```````` ``````
+ ``````````` `` ```.-----::///++/::.-:/oyhhhhhhyo++so+:---:----------....-...-+ohmmhy++:-...`.` `` .. `````````````````` `` `
+ ``````.``` `` ```...-..--::.``` ```:++o+:-:+:-..`.-` ` ` `-+odmmdho+....``` ` `` ` ````````````````````
+ `````````` ``` ``````.......--` .-`/ooo+//++:-...--` .` -+/oyys+:o/-`...-..`..`` .....`` ````````````````````
+ ` ````` ```````````.....---. ./:./ooosyo++:---::. ``./..-:-.....```` -oo++++/-` ``````````````
+ ```````` ```````````.....`..- `-+/-+ooyddo++/::::-. -.....``` ```..`````````
+ ````````` ```````````.....``-. .:+o+-+shmmdyoo+++o+:.`` ``...````````
+ ```````` ````````````..-///-: `` `./shhhhmmmmmmmdyyooo+-.`` ` ``.....``````
+ ```````` ``````````````.-+s/++``-```.:ohdysddyydmmmdmmy:.`````- ` ``.....``````
+ `````````` ``````````` `./oysy+:---..-:/dd+oo+shhdmmmmmy+--:-/-`..-.``.```. ````. ``````` ``..``..`````
+ ``````````````` ../oyyos+---.///-+y/+s/-.`/hhoyhs:/++/shyyyy+oooo+/:. ``````` `` ```` `````
+ `````````````` `../+so++-::.-+:.--::/+: /yo/ossyh+/oshdho---+o/--` `````` `` ``````
+ ``` ````````` ..-:oo/. .``:+/:-/++/: `::sooyo/-+soss+::o/.` ``..`` ` ``````
+ `````.`````` ` `.-// .:-++..:osso. ssoooos+oosooooo: .. ` `.` ` ` `
+ `` `.. ``` .////.`..//: -+++o/:.-:..-:-` .-: `.` ``` ` ``````
+ ``````` `````` -.-oso+//++` .--.-` `--` ..` ```--`..`.`.` `````````
+ ```````` ``` `````` ` ` ----+ooo+:/- ..`.` `` ` `::/-`````` ` `````````
+ ``` ````.----:-.-.` ..``` ` `` ```````
+ ``
+
+ ``
+ `-:++/.
+ ---+++/.
+ `/-.++++-
+ `` -/``/+++/
+ `- `-/:`-++++/`
+ :` `-:-.:++++/-`
+ -- .-`./++o++.
+ .:` ./++oo+/`
+ `/:` `/++ooo+: ` `
+ `//+.` `-++ooo++`
+ `:/oo/.` ./+ooooo+: ``
+ `://yy+.`-/++oooo+/` ``
+ ``://ohy+//++ooooo+: `
+ ``://+hhyoso+oooo+/. `
+ ````-:/+yddhdooooo+:-`
+ `````-::+sdddmyoooo+.` `
+ ``````````.-:/+dmdmhoooo/``` ` `` ` `````
+ ```````````````..-:+hmmmhoooo:.``````` ``` `.``` `` ``
+ ` `````````````.....-+smmmhoooo+-.````.``` ```````` ` ``
+ ` `````````````....:///+osdmmhooooo:-..``..``` ````` ``
+ ````````----.......--+oooossymmyooooo+----.-..``` ``` ````` ``
+ ``````````/++o++/------+oosssssdmyoossoo/:::.--..```` `` ````` ``
+ `````````````...../++ooo/-:---+ossssssddssssssso//:----..```` `````` `
+ ``````````````.`.......-+oooo+/:::+ossssssdhsssssssso/:-::--...``` ``````` `
+ ````````````......-------/ooo+///::+osssssshyhhhysssss+:-:::--::-.````` ` ````````` ```` ``
+ `````````...............-----/oooo++++/+oossssshddddhyyssso:------:oo++:.````` ```.````````` ```
+ ````````......--------------:::+oo+/+oooo+ooosyyyddmmmdysssss/:::::-/ooooo+-````` ``````````````
+ ```````.--..----:::/+/////:::::////://+ooosoosoyhhydmmmmdyyysys+++////+oooooo+.```` ````````````` ``````````
+ ```````./oo/---:::/ooo+++/////////////+ssssooyyhhhhdmmmdhhdhyyy+++++++/osoooo+....```` `````````````` ``````````
+ `````.-/ooo-:::/oossoo+//////////////osossoyyhhhhdmmdhhymmdhhsooossso+soooo+......``` `````````````` ``````````
+ `` ```..--::+o+///+ooo+++/////////+++///ossssssyhhhhhdmdhhhdmmmmdhhhhhhyosoooo/......```` `````````````` ```````````
+ ` ``````....::///+soso++////////////++++////+oosssshhhhhhdmmdhhhmmmmmhhhhhhyssoooo:.....````````` `````````````` ```````````
+ ``` `````..``.....--/oo+/+sooo+////////////oyyoo////++ooyysyyyyhdmmmmmddmmmmmdhhhhhsyso+++/....````` ````````````` ```````````
+ ```.........----/so+++syso/:/:///::::::oys/+/:::/ohyshssssyhmmmmmmddmmdmmdhhyysyyso+++/.```````` ``` `````````````` `````````.`
+ ````````` ``........----::/ssosshdhs+/s++s///////sys+++////yhhsyhssshdmdmddhydmmddmmdhhhdyyso+++/-......` ````````````````````````````````````` ``
+ ``````````` ` `...------:::/:/syssshmdds+yydh+oso++oyyysoo++++shysyhyyyhdddddhyyddmmddmdhhddhsoo++/:---..` `````````````` `.```.```````````````````
+ ````````````` ` ``.----::::://///syysyhmmmhoydmmdyyso+yyyyyysso++osssyyyyhhddhddhyhhhdmdddhyhhhs+/:--...````` `..` `````````` `.```.````````````````````
+ ````````````` ` `````..----::///////+syhhdmmmdhyhmmmmmyyosyyydyhdyssoooossshhhhhhhmmhhhyoshdso+://++-..-....```` ``` ` ```````` `.```.`````.``````````````
+ ````````````` ` ````....----::///++++yhddhmmmmhhdmmmmmmdysyhyyddddhsooooooooo+o+syymdsos//:-+o+/::----:-.``````````` ` ` ``````` `.```.`` ``.``````````````
+ ``````````` `` ` ````.....-:::://+++oshddhmmmmmmmmmmmmmmdhhhy+osso+////:::://///+yydmdyosoo+////:::-......````..` `````` ````` `.```.`````..````````````
+ ``````````` `` ``......--:://+//::--:/oyhhdhyss+//o+:..-+/--://:-------.-...-/osmmdho+:..```.. ` ```` `..`..```.....```````````
+ ``````.``` `` ```.......---.`` `..:oo/-:--:/. ./.``````` ```./:ydhsyo/`.`````` ` `` ` ```` ````...`......```````````
+ `````````` ``` ````````..-....` `/-/o+/:oo//:` `::.` ` `-..+-+ss+::s:.`..--......` ..`..`` ````````````````...```````````
+ ````` ```````````.....---. -+:/oo+syy+:.` .::-` ` ` `.-..-:-.....```` -oso+++/-` ```````````....```````````````` `
+ ```````` ```````````.....`..- ``:+:/ooyhhho/::://:-` ``.` ` ..---.``` `......`..```````
+ ````````` ```````````.....``-. `-:/o/+oydmdhyso+ooso+-`` `.-. ``..........``````
+ ```````` ```` ```````..-///-: `` `-oyyhddmmmmmmmmhyo+/::.``./:` ``..........``````
+ ``````` ```````````````-+o/++``-```./sddmmmdysdmmmmdhoo/.```-. ``..........`````
+ ` ``````` ``````````` `./ossy+----..-:+hy+o/:+hhhmmmmmds:::-/.`....``.```` ````` ``````` ``....`......```
+ `````````````` ../osy+s+---./+/-/s://--``:hdyhhy:+++/syyyyo+osoo+/:. ``````` `` `..` `....``
+ ````````````` `../+so++-::-:+/.--::/o: /hy+ossyh+/ohmmd+---+o/--` `````` ``` `....``
+ ``` ```````` ..-:oo/` `.``:+/:-//+/: ::sooyo/-+sosso:/o/.` ``..`` `` ````.``
+ ``` `.`````` ` `.-// .:-++..:osso. ssoosos+oosooooo: .. ` `.` ` ` ````````
+ ` `.` ``` .//+/.`..//: -++oo/:.-:-.-:-` .-: `.` ``` ` ``````````
+ ````` `````` -.-oyo+//+o` ---.-` `--. ..` ```--`..`.`.` ````````````
+ ``````` ``` `````` ` ``---:+ooo+//- `.-`.` `` ` `::/-`````` ``` ````````````
+ `` ````.--:::-.-.` ..`.` ` `` ``` `````````
+ ```
+
+
+ `://.
+ ` `/:`
+ `. `/+.
+ `:+:
+ ` `:++`
+ .` ```-++-
+ -. ``..--/+/`
+ `.::` ``.-::/+///`
+ -//.`-.-/////-.`
+ `::-./://+/:.
+ ``-+oo++/.` ``
+ -+hy++:` `
+ ` `.odh+++-
+ `` ````-hdho++/
+ `````````:hmhoo++`
+ ``````````/dmyoo++.`
+ `````````````.omdoooo+-``` ` `` ` ```
+ `````..`````.`..:+ydsooooo/```````` ``` `.``` ` `
+ `.```````.-..```..:/+++sooooooo+-.````````` ``````` ` `
+ ` `-/-````..----....-/+/-:ooooooo+:..```....``` `````` ````` ``
+ ` ````:+/.``.-::::-.-------:oooooooo/---...-++:---.```````` ````` `
+ ````````..`...:/::/-------:::oooooooo+:::-.--:+++++++/-.```` `````
+ `````````.```..-/::/:----://::+oooooooo/:::.---++oo++++++```` `````
+ ```````````.........../:://::::/ooo+/ooossooo+/::-----+ooo+++++````` ```````
+ ```````````..`.....-......-::/+::////ooo/osssddhso+::-::--+ooo+++++.``` ```````` ```
+ `````````````...................---:::///+ooo/ooosdhmho+:------:o+++++++.``` ````````````
+ ``````.........------------------:::+o++osssossssshmmyo/:::::--++++++++````` ```````` ````
+ `````...----:---::::---::::::::::///+ooosyyyyssssommmmh++/////::::/+++-.```` ````````````` `
+ ` ````...--//-:/---:::::::::::::://////+oosdddhdysyyymmmmmh+++////:::--:```.`````` `````````````` ` ``
+ `````....-.:++://::::::::::::::::://///+++sydmmdddhyhhmmmmmdyso+++o+::-.``......``` ````````` ``` ````` ````
+ ```..---...:o+:++::::::::::/ooo+/////+osooyddmmmmmmdddmmmmmdosso++o+/:-.`..`.....``` ````````` ``` ``````````
+ ```..-::----/oo/oo::////:::++yys+////++osoohdddmmmmmmmmmmmmmhoo++++++/:.``````...```` ````````````` ```````````
+ ```````````..-::--::yyo+os//oo+//:/ssyo::///++osoooyddddmmmmmmmmmmmmhs+++++oo/:.```````````` ````````````` ```````````
+ ```````````...--//--/dhyssso/ss+/::/sso:::/+:/+oooooohddhddmmmmmmmmdmmdy+//oo+:-.``````` ```` ````````````` ```````````
+ ``````````..-/-:/oso/sddyysssyy+/+/:oyyy+//oo++oooossoyhhyhhdddhhdmmdddmdhoohyo/---.........`` ```````` `````````````````````````` `
+ ` `````.....--+ooooshyhdhyyssydh+/+++yyyhhoosyoossosssoyhyyhhhhdyhddmmhhdddyshddy+:-----....` ``````` `````````````````````````
+ ` ``` ``.....----::/sssssyhdhhyyyyydds/+++yyyhhyhdhsssoohyo+yysyhyyddhhdydmdysddyssso+/-....`````` `.. `````````````````````````
+ ```````` ``````....--:::::/oyssyyymhdmdmdmmdy///+yysyyhmmhysyosys+oysooosymmhhhssyddyo+::-.........````` ``` ```````` `````````````````
+ ``````` ` ``````....--://///syhdhyymmmmmmmmmmdo+/oysoyyddddsossss++os++++ssmmhss+//:+o/:-.....`.```````````` ` ` ` `````.` ````````````````
+ `````` ` ``````...--:::////+shdmmmmmmmmmmmmdhy+/sy+/+oo++//:/:::::////+syhmmdys+/////:::-..`...`````.`` ```` ```` `````.` ````````````````
+ `````` ```````..---::/::--::/oshhhyyyso++:--../:..--::::------.-..://+smmdhs/...```..`` ``` `````.```````````````````
+ ``````` ``````....```` ./++:/s+::.` `:` ` ` .::/+ydyoso-`````````` ` ``` `````.```..````````````
+ ` ` ` ``````````` :/++:+ho-:. `-. `-:-.+ss+-/s:.`...-......` `......` ````````````````````````` `
+ ` `` ````````.... :/++/ohs::-``.:-` ```.-:-.....```` -syyso++:` `````````````````````````
+ ` `` ```````````. :+/+oshho/:-:::--.` ..---.``` ``....`````````
+ `` `` ``````````.. `.`.:+/shhhhyo++++ooo+/.` ` ``.....```````
+ `` `` ````.-:-.- ` `:/+syhdmmmdmmmdyyyso+:-` ..` ``......``````
+ ` `` `````./+:/:``.```-oydmmdddy+hmmmdmmmmh-```` `.......`````
+ ````` ``` `.:+ooo/....`.--:sd+-:-:shdmsymmh::--..` ```.``.```` ````` ``````` `....`..``````
+ `````` ``` `.:+oo/o/.--.:/:-:s//+/.` -hh+os+-/++/+ssys++osoo+/:. ``````` `` `..` `````
+ ```` `` `..:/o+//--:.-::.-.-:+o: :hy/ossyy/+hmmmh:---/o/--` `````` `` ``````
+ `` ``` `..-++:` ` `-/:-.://:- --oooyo/-+osyyo::+/.` ``..`` `` ``````
+ `````` `..:: .-.//.`-ooo+. ssooooo/+oso++oo: .. ` `.` ` ` ```
+ `` ` ` .-://.```//: -//++:.`.:...-.` .-: `.` ``` ` ```````
+ ``` .`.+s+/::/+` ...`. `-.` ..` ```--`..`.`.` `````````
+ ` `` ````` ` ..../+++:-:. `.`` `` ` `::/-`````` `` ` `````````
+ ```.......`.` .``` `` ` ```````
+ ``
+
+
+ `..
+ `.-`
+ .--`
+ `.::.
+ `-::.
+ .:/:.
+ `-///-
+ `:/+/-
+ `./++:`
+ `-/++:.
+ .:++/::
+ `/+/.`.
+ `++:.
+ `/+/-`
+ `` .//:.
+ -:`` `:/:.
+ .+/-` .+/``..` ```
+ ```+++-`````.++`.://`` ://: ```
+ ``-++/-````-++.:/+o:` `/++- ``
+ ```````````.+o+/.```.oo/++oso-`` ./++:-:/: `
+ ` ``````````````...+oo+:-...oossssss/.`````-/++++/.`.-` ``
+ `````````````......./oooo+/--.:oshyhyso--.`..```-/-` `/+/
+ `` ``````````````......:oooooo++::/oshmmdys:--`...``` :+/
+ ````````````......````....:oohhyyysso/+ssymmmhs:--.....```` -++- `
+ ``````````....`..............-oooyddmmhyysoosshmmdy/--.......````++/` ``
+ ``````````....-..................-/oooodmmmdhyyhssshmmmho-......```.:++/. ``
+ ```````...---::..----------------:/osssymmmmdhhhhyyhmmmdy:-----....``.` `
+ ``` ````...---++:----::----::::-::::/+ossymmmmmddddmddmmmmd+::::::--..`` `
+ `` ````...----:oo:---:::::::/:::::::/+++osymmmmmdhdmmmmmmmmds/:::/::--..` `` `
+ ```.::....---::oo::::::::::/o:::::::/+o+oosdmmmmmddmmmmmmmmdy+//////:--.` ```````
+ .-.`-++/-...-:::os+::::::::/os/:::/::/+oooooydmmmmdmmmmmmmdmdhs+/////::-.`````````` ``
+ ```:/:.-+oo/--:++//sso://///::+sss::::://+++o++ohmmmddmmmmdmddddysso////::-````` ```` ````` `
+ ```````-++//+oss+:+os++sss////////+sys/::::://++o+/+sdmdhddmmmdmddmdysss+//::--.```````` ``````` ````````
+ ````````.+o++oosoo+osdhysoo/:::----/ssys::::/+//+o+//sddyyhdddmddmdddyssss+::-..```` ````` ```````
+ ````````..-:ooossssssssdmdhss//::::::/syyyso+ooo+++o+/+yhhsshhdddmmmmddhyssys+:-....`````````` ```````
+ ` `` ````....--::/osssssssssmmmdhs//::::///yyyyyyssso+++oooyyyssshhdmdddmmmddhysyhys+:......````` ` ```````````
+ ``` ``` ``...---:::///syhdmmdyhmmmmmy///::+//oyyyyyyhyss+/++oyysooooyddmdhhddmmmddyoyso/::..```` ``` `````` ````` `
+ ```````` ``````....-::://+++sdmmmmmmmmmmmy+//:/o/+yysssshmhsooo+ssysooooohddmhhossyddoo/.-.`````````` ` `````` ```` ```
+ ```````` ` ```````...-:://++ooohmmmmmmmmmhyso+//os+sysssshdmho++++sssosoooossdhhs+/::-:/:-..```````` ` `````` ``` ``
+ ``````` ```````...--://++o++sdmmmmmmmmdhhhyooooos++/+osso+:::---::::/+ossddhdy+////::::-.``````` ``` `````` ````
+ ```````` ```````....-://++/:-://oyhhhhsyo/:---...-...---:---.........-:/+ymmhdy-``````-.` ` `````` ```````
+ `````````` ``````..--````` ///+//.` `` `` ` `/:/+ymdhyo- `````..` ` ` ``````````````
+ ` ` ` ``````````..` ///oo/. `-.`` -` ` :/.-+yyo:/o-.``.....````` `.....`` `````` ``````
+ `` `` `````````.... //oyy/:``-:-` :- ```-:..-:-.....``` .yhyyo++:. `````````
+ `` ``` ```````````.. .+/yhh+/--::-``./-..-. ..---.``` ```````````
+ `` `` ```````````.. ./+ohddy+//+oo++/+++/-` ````````````
+ `` `` `````..::-.- ` `.:/+syyhhdmmmdhyyhmdh+--.` ` ` ````````````
+ ` ``` ```````./+://``.``.+ydmmmdmmh/ddyshdmmdo-`` `` ````````````
+ ````` ``` `.:+oos/..-.`.-::sd+/o:/msohddmd+----.` `.````.```` ````` `` ```````````
+ ``````` ````` `.:+os/o/---.:::-/s:/o-/. .yd/+o/.////+ossoo+osoo+/:. ``` ` ``` ````
+ ```````` `..:/o+/+---..::.-.-:+/- :s+:+ssyy+ohdmmy-..-/o/--` ``` ` ````
+ ` ``` ``.-++:` ` `-/:-.://:- --oooyo/-+ssyy+::+/.` `..` ``
+ ``````` `..:: `..:/.`-ooo+` ssoooos++oso++oo: .. ` `.`
+ `` ` ` `--:/.```//: -//++:.`.:...-.` .-: `.` ``` ``
+ ```` .`./o+/::/+` ...`. `-.` `.` ```--`..`.`.` ``````
+ `` `` ````` ..`./+/+:-:. `. ` `` ` `::/-````` ` `` `
+ `......`.` ```` ``
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ `:-:- ..
+ -:///:-`-` .` --`
+ `-:////:/.`//-``-:.
+ .-///+++:`:+/::+/-
+ ` `.///++/`-+++/+::`
+ ```````````./+++++--+++++//-` . ``
+ ``````````./+o++oo+ooo++++o+-.:` `
+ ` `````````....:oosoosyyyhysooooo+/-
+ ` ```````````...--:oyhysshhhhddhsoooo++.````
+ ```````````````....-:+osdddhhhddhdddhoooo+/..`.``
+ ```-.`````````````..-/+ooohdmmddddddmmdhsoss+---`..```
+ `````.:-``````........../+oooosydmmmddddmmddssss/---`...````
+ ````````::.`...`....--.....-oooooossdmmmddmmmddysss:---.....```
+ `````````````..-+-..........---.....:oosssssymmddmmmmddhsso:-......````` ``
+ `...```........:+-----------/:-------:+ossssymmdmmmmmmmdyys+/----....````
+ -```-/:..://:.:--/+:----::::::+/:::::::::/+o++sdmmmmmmddmddhyss+::::---..``
+ ::``.:///++++++:--o/::::::::::+o/::::::://+o++oddmmmmmdhdmddhsss+/::::---.``
+ -+-..-/+ooooooo+::++::::::::::+s+::::::://+o+++ydmmmmmdhdmmmdysss+/:::::-.`` ` `
+ `.++---/+oooooooo/://::::://:::/so:://////++o++ohdmmmmmdddmmmmhysss/:::::-.`` `` ````` `
+ ```:+/:::osssssoosyo++////////::/os//oo+///++o+ohdddddddmmddmmmmhysso//::--.`` ` ``` `
+ ````../:--/oosssssshhsss+/////////:/+/osso+////++hddhhhdddmmmdmmmmmdyss//::--.```` ` `````` ```````
+ ````...::--+ossssssssssss+::::::/:-:://sso+:--://ohhhysyhhmmmmdmmmmmmmyo+:--..``` ``` ```````
+ ``` `````...--::--/osyhhhddhsosys+//:::://:::/syss+::::+oydhhysoshmmmmdmmmmmmmmyo+:-...``````````` ````
+ ``` ```` `````..---:://:/hddmmmmmhyyyyy+//:::/++////syyso////+hhhyyssssyddmmddhhdmmmmhsso/:/:..```````` ``````````
+ ````````` `````....--:://+++ydmmmmmmddhyo+////::oo+o+//oyyss///+oyyhysssssyhymmhsosydmmmmooso///.````` ``` `` ``` ```` `
+ ```````````` ` ```````...--::/+++oyhmmmmmmmhyo+//++/:/ossho//+yyys///+ssyyssooossyyddhsosoossso:-.`````````` ` ````` ``` ```
+ ``````````` ` ````````..--::/++osyhdmmmmmmddhyo++++/osyys++syhdmh+//++++ooo++//+sdhhss+:-.-//:-...````` `` `````` ``` `
+ ``````````` ` ` ````````...--/++oosoydmmmmmmmmmdddddhhhsoo++/+sooso/::::--:://+/+yhmhhso/:::://:-.``````` ``` ` `````` ```
+ `````````` ` ``````....--://++//::/+oyhddhyo+/:-::.``.....-::-:-...-.......-/sdmddy:````.-:.` `````` ``````
+ `````````` ` ``````.`...--.```` /sy//. -` `` .::```. `.:+hdmdys- ``--.` ` ` `````````````
+ ````````` `` ````````......` oyh/:- .- -` .++:` :` `/-:+yhs//y:. `.....````` `.-...`` `````` ``````
+ `` ``` ```````......-. -syd+::-..- `- `/+/. `. .``--..-:-.....``` -yhyyso+:.` `````````
+ `` ``` ````````...```.. .syydy/:/-.``....-.:+/. `` ..---.``` ```````````
+ `` ``` ````````..````.. `-/shsmds+++++oooo+/-::.` `` ```````````
+ ``` ``` ``````..-:::.- ` `.-/sssyhyhmmmmdhddhdddy/-`` ```````````
+ ``` ```` ```````...-+o///``.`.-odmmmmmmhdmmdddmmmmd+.`` ```````````
+ ````` ```` `````` `.:osss+-.--..:::yho+symhhmdsoyh+.---.. `.``.`.```` ````` ``` ` ````````````
+ ````````````` `./+ss+s/----//:-/s/+oss.`/ho./o/.://++osss++syoso/:. ```` ` `` ``` ````
+ ````````````` `../+so++-::..::.--::/s+ :s::+osyh++yhdds-..-+o/--` ````` ````
+ ` ``````` `..:oo:` ` `-/:-.///:: --o+oys+-+ssys+::+/.` `-.`` ``
+ ```````` ` `.-// `../+.`-ooo+. ssoooss+oosooooo: .. ` `.`
+ ``` ``` `--//.```//: -//++:.`.:...-.` .-: `.` ``` ``
+ ` ```` .`.+so//:/+` ...`. `-.` `.` ```--`..`.`.` ``````
+ `` ``` ````` ` ..../+++:-:. `. ` `` ` `::/-````` ` ````
+ ` `....--...` ```` ``
+
+
+
+
+
+
+ `
+ .-. --
+ .:-` ::
+ :/-` `//-.`
+ ``` .//- `//::-`
+ `---` ./+/. `/+///:
+ `:::.`./++/.-/++++/
+ .///::/++o+//++++/`` `
+ -/://++ooy+/++++++//` `
+ -:/+++oosho++++++++-
+ `.:/++ooohdy+++++++-`
+ `.:+++ooodmdy++++++-`
+ `.-/+++ooodmmdo+++++-`
+ ```````.:/++oooohmmmhoo+++-` `
+ ``````````-/++oooooyddmmdyo+/.`` ```
+ ` ````````.-/++ooooosyhdmmmho+/.`` `` ````
+ ` ``````````.-/++ooosssssshdmmmhso+...````` ``
+ ``````````````..-/+oooosssssshdmmdhso+-....`.``` ``
+ ``...```` ````.``````.........:oooossssssdmmmdhys+-----`...`` ``
+ `.--:::::-.`````````.`````...`......-/+ooosssshmmmmmdhyo+/::-....``` ``
+ .:////////-`````````.`..............-++oo+osoodmmddmmddsoo/:-.--...``` ````
+ `-/+/++++/-``````........----........++o+ooooommmhymmmdhs+::-.----..`` ````
+ ```./++++++/:...............------..---:+oossyyhmmmhyhmmmds/:-----...``` ````
+ `````./+++++/:-------------------------::+oyhhhhdmmmdhddmmmh/:::::---...``` ``` ````
+ ``````:++++++/:---::::::::::::::::::::::/+osyhdddmmmmddddmmmdho////::::--.`` ``` ````` `
+ ``````:++oo+/::::::::::::::::::://////+++o++sdddddmddmmmmmmmmmdo//////::--.` ````` ```````
+ `````.`-oooo+-:-::::::::://////////////+oo+/+odddmddddmmmmmmdmmmd+++////::-.`````````` `````` ``
+ ``````..-oooo/---:///////////////////////+o++ooddddddhhdmmmmmddmmmho++///::-.`````````` ``````` ` `````````
+ ` ``...``--:syyyo+++++///////////////////////++/+ydddddhhhdmmmmmdhmmmms+o+//::-.``````````` ```````` `` `````````
+ ``` ``...-...-oohmmmdyyys/////////////////////////++/yhdddhyydmmmmmmdydmmmmo+o+++/-.```````` ````````````` ```````````
+ ```..-----.-ssymmmmyyyso+/:::::::::::::///:::/:::ooyhddhhhsdmmdmmddyhmmmmdooo+oo.`````` ````````` ``````````
+ ````````` ```````..---:::::+yydmmmdyyyo+//:///::::////+/o//++::/oyshddyyyyddddmmdhyydmmmmdhysss-....```````` ```````````
+ ``````````` ` ``````....-:///+ooyyhmmmmhhho++o+++/:://++++//ooss+///oyyhddysyyhdhdmdhysyhdmmmddmhys--......```` ``` ````````````````````
+ ````````````` ` ``````...-.-:////osyddhdmmmmmdsss+++///+oooo+///syo+///ssshyysssyhhhdmdhyhyyhdmmhyhhyo:..```````` `.` ````````````````````````
+ ````````````` ` `````..------:++++symmmdmmmmmmmdhs+++ssyyooyo+//syss//+o++sssoooosyydmmhhhsoyooo:-........```` ``` `````` ````````````````
+ ````````````` ` `` ```````..--::/+oossydmmmmmmhdmmmmmdhyyyysssyhyoohdss+/++++ooo++++sshhdyss/:-+o+:--...``````````````` ` ` `````` ``````` ``````
+ ``````````` ` `` ````````.---::/+osssydmmmmmdmmmmmmmdhsoooyssoss++s+/:::::::////+syhdhdyo+///++/::-..`````````.`` ` ` `````` ```````` ``````
+ ``````````` `` ````````.---::/+++/+/:/+ohdhhysoo+:--..``-..-/++:-:-----......-/osmdyds:..--.:-.` ````````````````` ````
+ ``````.``` `` ```````....---.```` `/yso. ```./::```:/- `/oddddhy:` `-.--. ````` ```````````````````
+ `````````` ````````````.......` `-ohs+` ` ./--````// ``-:-/+yys//y:. .----.....` .--...` ```````````````````
+ ````` ```````````.....---- -/shy+` `` .-.` ` `.--.`` .. ``.--..-::......```` -oyhys+/:-` ````````````
+ ```````` ```````````.....`..- ```:+yhhs-``--:so:-...-:--.` ` .....```` `````````````
+ ````````` ```````````.....``-. .----/syddo//++ydhhdddho/-.` ` . ``..````````
+ ``````` ````````````..-//:.:````-+++/:osoymmddmddmmmmmmy-.`` ` ``..``.`````
+ `` ```` ````````````...-+s/+/``.../shdmmmmmmmmmdsoymmmh/.`` ``.....`````
+ ` ```````` ```````````` `./oysy+-.--.://+hddyyddhyhhs:/y/.---.` `.````..```. ````. ```````` ``..`````````
+ ``````````````` `./osy+s+----///:+y+sydo. -so.:+:.:///+osss++syoso/:. ``````` ``` ```` `````
+ ````````````` `../+so++:::..::.--:/oys -o/:+oshy/+syyhy:..-+o/--` `````` ` ``````
+ ``` ```````` `..:oo/` ` `-/:-.//+/+ ::sooys+-+ssss+::+/.` `-.`` `````
+ `` ```````` ` `.-// `../+.`:osso. sso+oss+ossooooo: .. ` `.` `` `
+ `` `.` ``` `--//.``.//: -///+:-`.:...-.` .-: `.` `` ` `````
+ ````` `````` .`.+s+//:/+` ...`. `-.` `.` ```--`..`.`.` ````````
+ ``````` ``` `````` ` ..../+++:-:. `.`` `` ` `::/-````` ` ````````
+ ``` ```.........` ```` `` `````
+ `
+
+ ``
+ `.....`` .///::`
+ .-:--.` ./////`
+ .://::```-/////`
+ `-////.``-//++/-`
+ ``-://+-``://++/:` ``
+ `.::/++:`-:/++++/.````
+ `` `.::/++:.://++++/.```
+ `..```.:://+:-////++++/..`
+ -------:///::+//+++++/:-`
+ .////:::://:-+//++++++/:`
+ `://///:///:.++o++++++//- `
+ -///+++++/:./sysso+++//. `
+ `-/+++++o+/:./hhyys++++/:-
+ `:/+++++oo//:+ssshho+++//-
+ `://++++oo///++ooydy+++++.
+ ``-:++++oo+:++ooosddo+++/
+ ```````:++++o+:o+ooosdds+++- ``
+ `.-. `````````.//++oo/ooooohmmh+++-`` ` ````
+ `.--::- `` ` ```````````.:/+oo+ooossmmmdo++/.` `` `````
+ `--:::::-....---` ` `````````````..-/+ooososssmmmdy+++-.````` ``` `
+ `--:::::://////- ````````````.......-:/ooossssydmmmho++:-..`.``` `` `
+ `-::::::::////.````````.``````..........---/ossossyyhmmmdsoo+:--`...``` ``
+ .----..-://.`````````.``.`............---+hhhysyyyymmmdyoo/::-.--..``` ``
+ ``````..```````````.`..............---:+ydddyyyhdmmmmdso::::.---..``` ````
+ `````.```````````........-----......:/:/syddmsyhmmmmdmmho+::------...` ````
+ `````......................-----------+++sydmmhoymmmmmmmhyo:------...``` ````` `
+ ````````.......---------------------::::/sssydmmmssmmmmmmmyhh+:::::---...`````` ````
+ `````````....----::::::::::::::::::::::://syyymmmmhshdmmmmmdhhho+////::--..` ``` ``````` ```
+ ```.-.`.::-..----:::::::::::::::///////////osydmmmmhyydmmmmmdhhdss+++//::--.` `````` ``````` `` ``
+ ````.://+oo+/--:::::::::::///////////////////ohdmmmmdddmmmmmmdhdmddysoo+/::-.`````````` ``````` `` ```
+ ``..`.:+oossso////+o+////////////////////////++shdmmddddmmmmmmmdmmmmdyyss+/:-.```````.`` ``````` `` ``````````
+ ` `.....`.+ossyyyssssyo+++///////////////////////+yyhddddddmmmmmmmdmmmmmdyyyyo:-.````````.`` ````````` ``` ```````````
+ ``` ``....-...-ossyyhddhdhssso+/////////////////////:/ydhddddddmmmmmmdddmmmmmdyyyy+-.````````` `` ````````````` ```````````
+ ``....----::+sssyydmmmyssso:::::::::::///::::::::::odhddhddmmmddddhhhmmmmmmdsso-.```````` `````````` ```````````
+ ```````````` ```````....--::/+//sssyyhdmmdssso////++++o///+++/////:///+yyyhhhhdddhhdhyyhdmmmmmdyo/--...::..````` `````````````````` ``
+ ```````````` ` ``````.....-:///oo+sssyyhhmmmhyss+++ossyyy++///so//////+++sssyhhhyddyhhyyyyhddmddhso/:::--++/....` ``` ````````````````````````
+ ````````````` ` `````......--://+ssydhhhhdmmmmyys+ooyyyyys+++++yo///o+//++ssssyhhyyhyddhhhssydmmyso+///:-...````` `.. ````````````````````````
+ `````````````` ` `````..-----::+oosyydmddmmmdmmddyyyyysssyoo+osoyo//oso++++ssssoooyhyymmhhyosssso:-...........```` ``` `````` `````````````````
+ ````````````` `` `` ```````..---:/+osyhhdmdhmmmmmmmdhhhhhossshyosysyssoso+++++ooo+++osshhdyss+-:s++::--...`````````````` ` `````` ````````````````
+ ``````````` ` `` ```````.----://ooyyhyddmmmmmmmmmdhdddsssssyysoooshsss/::::////++shmdhhssso//++/::-..``..```.`.`` ``` ` ``````` ````````````````
+ ``````````` `` ````````.---::/++o++//++syhyysooo/:----.`./+/:-///:/oo---.-...-+ymmhhhso/-.-.-:.` `` ` ` `````````````````````````
+ ``````.``` `` ```````.....--.```` .:. `-.` `://-`-```.-+. `../hdmmdhy+.``.---. `....` ```````````````````` `
+ `````````` ````````````..--...` `::/` `.+o:-``.:oo/-.```.`/-` ./--/oyys+/s:. .-:--.....` `.-:--..`` ` ```````````````````` `
+ `````` ```````````.....---- `` `-//:` .oshy+/-::/oo/-.``` `.` `-.``-:::......````` -ooyyoo+:-.` ```` `````````````
+ ```````` ```````````....``..- `---` `--/+/--.`.shdhyo++/++/-` ` ` ..`...``` ``...`````````
+ ````````` ```````````.....``-.`-::-` `.-ss+///:sdmmdddhy/-.`` .` `....````````
+ ``````` ````````````..-//:.:`.-//:--:::-odmmmmmmdddmmmd+.``` `` ``.....``````
+ ``````` ````````````...-+s/+/``-:oyhhhddmhhmdmmdyoosmmy-```.` ` ``.....``````
+ ` ```````` ```````````` `./ossy+-.-::/+osddysdmy/+oyd+:s:...-.. ``````..```` ````.````````` `...``.``````
+ ``````````````` `./osy+s+----///:/s/sdmo` .oy-:+:.:///++syyo+syoo+/:. ``````` `````` ``.` `````
+ ````````````` `../+so++-::..::.--:/ods :s::+oyhy/+syyhy:..-+o/--` ``````` ` ``````
+ ``` ```````` ` `..:oo/` ` `./:-.//+// ::sooys+-+ssss+::+/.` `-.`` `````
+ ``` ```````` ` `..:/ `.`:/.`:oooo. sso+oss+oosooooo- .. ` `.`` `` ` `
+ `` ``` ``` `--::.```//: -///+:-`.:...-.` .-: `.` ```` ``````
+ `````` `````` .``/o+/::/+` ...`. `-.` `.` ```--`..`.`.` ` ````````
+ ```````` ```` `````` ` ..`.://+:-:. `.`` `` ` `::/-````` ` ````````
+ ``` ` `......`.` ```` `` ```````
+ ``
+
+ ``
+ ``..` ````:////:.``
+ `----` ..``.:::o++////:-
+ ::::-` .:---/+ohhy++///:`
+ `/:::- -/:-/+shddho+///:`
+ -///:. .//:/+oddddo+++//-
+ :///:` `-/+//+ohdmdo++++/:`
+ `://:- `:/++++oohdd++////:
+ .:/:-` `:/++++ooodh++////:
+ ..`` `//+++ooo+oy++////:
+ ./++++ooo+++//////:`
+ `.:++++oooo+:-:////:` `
+ `` .+++++ooo+- `-//- ``
+ ` ``/+//++oo+: `::`
+ ```-+///+oo+: `.`
+ `````+::/+oo+/`` ``.-:-.
+ ```````-`.-+osss+:..-::::`
+ ```````.```-.````+ydmhsso+///:. ``
+ ``````````.---::.``.ommmmhddd++/- ` ````
+ ` ````````````-://+/-..ymmmmmmmmh+/`````` ````` `
+ ` ``````````````..-//+++/--ymmmmmmmmdy:`````` ``` ``
+ ````````````........:++ooo/+ydmmmmmmmds--.`..``` ```` `
+ ```.``````..........---:+osyyyyhdmmmmmmh+::-.-..``` ````
+ `````````````````.``...........----:+sdhdhshmmddddo/:::.---.``` ` ```
+ `````````````````.`..............---:::+yddmdhdmdhhdyo+//:-----..`` ` ````
+ `` ```````````````........-----......---:+oyddmmmmmmmdhmdho++/:::---..` ``````
+ ```````````..................-------------::oydddmmmmmmmmdmmdyyho////:..````` `````` `
+ `---.....`.......----------------::---::::/o+shddddmmmmmmmmdmmhhmmyssso:-..``````` `````` ``
+ `.///++++/:--:-----:::::::::::::::::::::://sshhhdddddmmmmmmmmdhdmmmhyyy/:--.``````` `````````````
+ ```-+ooooooooo/::::::::::::::::::///////////osddhdddddmmmmmmmmmddmmmdhyy/::-.`` `````` ```````` ```` ```
+ `````-+oooosssy+////::::::://////////////////+shdddddhdmmmmmmmmmmmmmmdyyy//::.`````````` ```````` ``` ``````````
+ ```````.:+ooshddhooossoo++///////////////////++sydmddddddmmdmmddmmmmmmdyys+/::.```````.``` ```````` ``` ```````````
+ ` `````..```../+shdddysssssssso///+oo+/////////////+oddddddddddhddddmmmmmmmyso+/:-.```````..``` ````````````` ```````````
+ `` ``````...`....:+syhdhssssssso/+syyyys////////////:/oyhdddhddhhhhhhhmmmmmmmhyo//:-.``-`````` `` ````````````` ```````````
+ ```````....-----:/ohdmysssso/:/syyyys+:/+/::::::::::oshddhydhyyyhhhyddddmmmhss:-..``.//-`` ``````````` ```````````
+ ```````` ```````...---::::::/+hmmmhysso///syyssss//+++/////////++sshhyshddhhhdhshhhddmmdhs+---...:++:.`.``` ` ````````````````````````
+ `````````` ` `````````..--://+//:/smmmmhyyyyyssyyssos++++++o+//////+o+osyhyyyhdhhddhsyhhddmdydyy+/:----:+/...` ``` ````````````````````````
+ ```````````` ` ``````.....--::+so++/osdmmmmhyyyddhddssyy++++osso//////+o+ossyhyyydhmmdhssyydmmdssoo+/:---..````` `.. ````````````````````````
+ ````````````` ` ``````....--::/osso++ssmmmmmdhyyhddmdyyhyh++syyss+/++/++++ososssoshmmdhyoosyyyo+-:-.....----.```` ``` ``````` `````````````````
+ ````````````` ` ```````....-://osys+oyhmmmmmmmddhdhmdhhyydhyyyssssyhds++o+oos++++ymdhys+:--/o++:----...````..`````````` ``````` `````````````````
+ ``````````` ` ` ````````..--::/+oyyyyddmmmmmmmmmmdhmhhsssyhdyso++ossys::////+/++smmdhys////++o+::-...`.....--:.` ```` ` ``````` ````````````````
+ ``````````` `` ````````.----://++++:/++syyyyssoo++o+/-..:+so+//::///+---:-...-/hmmhhdh+...---:-` `...` ` `````````````````````````
+ `````````` `` ````...--..``` `.. ..`.+o/-` `.-+/.`.````.-` .. `.odmmdhdy/``.-:-.-` ``..-.` `````````````````````````
+ `````````` ``` ```````````....` `.. `:-.+yy/-` .--:-.```` - .`..../+syyo:+s:.`--:--.....` `..:::-.``` ` `````````````````````````
+ ````` ````````````.....--- ..`.-:/:-ohy+:.`..:-.` .-..`-:::......````` -oosysoo/:-.` ```````````````````
+ ``````` ```````````....``..- .-::////-+hho+:---:-` ` .......`` ``...`````````
+ ``````` ``` ```````...`.``-- .::+++++:+yhyhhhs::-` ` ``...````````
+ ``````` ``` ``````..-//:.:`......---:+ydmmmmmddmdmmmo..```. `......``````
+ `` ```` ````````````...-+s/+/.-ohhyyyhhdhddhdmmmdysdmmh.````` ``.....``````
+ `````````` ```````````` `./ossy+-.-:/++++hyhmdhs/:ydh//y/...-.` `````..```` ````. ```````` `...``.``````
+ `````````````` `./osy+s+----///-/o/ymdo` -hs.:+:.:///++syyoossoo+/:. ``````` `````` ``.` `````
+ ````````````` `../+so++:::..::.---/ydo -o:-+oyhs/+syyhs:..-+o/--` `````` ` ``````
+ ``` ```````` ` `..:oo/. ` `-/--.:/+// -:s+oys+-+soss+::+/.` `-.`` ``````
+ `` ```````` ` `.-// `..:/.`-ooo+. sso+oss+oosooooo- .. `.`` `` ` `
+ ` `.` ``` `--::.```//: -///+:-`.:...-.` .-: `.` ````` ``````
+ `````` `````` .``/o+/::/+` ...`. `-.` `.` ```--`..`.`.` ` ````````
+ ```````` ```` `````` ` ....///+:-:. `.`` `` ` `::/-````` ` ````````
+ `` ````........` ```` `` ```````
+ ``
+
+ ``
+ `-/////++++++. ..
+ .:+++/+++++/- ``
+ ./+o+++///:`
+ -++o+/-.`
+ `:/+o:`
+ ./++`
+ `/+.
+ `/:
+ `. `` `` `
+ `.---..`
+ `-::///:-. ``
+ .//++///:-` ``` ``
+ `` ```//+os+//-. `.``
+ `````..://+sdho/.- ``
+ ````````/+++++hhdy//.
+ ````````-+o/+++dhhy++.
+ ```````````````./oy++++mhyoo+-` `` ``
+ ``````````````..-//ohs+++ddso:/:.````` ``` `.`` `
+ ` `````````````...-+ooshhs++dmhy/---```.``` ````` ``
+ ```````````````.....-:+syhmmdo+hmdho:--.``.```` ``` ``
+ ````````````.......---:/+yhhmmmsohmdds+//:-.-..``` ```` ``
+ ```````````.`````.......-------++oyhymmmsosmmdysso++///-.``` ````` `
+ ```````````````.``.........--.----+soshddmmmdysmmdhyyhyyyo++:.``` `````
+ ````````````````.......--......--://sssyhddmmmmhsdmmmdhddhdyoo+:..`` ```````
+ ``` ````````````````.......----------.---+syysydddmmmdssdmmmdddmmmdsoo:-.``` ```````` ```
+ .```.--.``..................--------------:syyyhdmddmmdoohmmmddhmmmdso+-..````` ``.`````````
+ `...://-.---:/-.----------:-:::::::::::::::oyyydmmmddmhsshmmmdhydmmdso:---..`````` `````````````
+ ``../////++//:---::::::::::/:::////////////+yyyhdmmdddyssydmmdyydmmyo+//::-.```````` ````````````` `
+ ``````-::/++/::--:::+ooo+//://///////////////++oyyhdmmddhyssshmmmyyhmmh+++//::-.```````` ````````````` `` ```
+ ````````./+/--:+//++ooooooo++++++oo//////////++++yhddddmmdyysydmmmyyymmdo+++//:-.``.`.````` ````````````` ``````````
+ ``````````..---/sso+oosssssssyhyyyys//////+////++osdddddmmmyyyymmmmyyhmmdo+++//:-.``/:.`..``` ````````````` ```````````
+ `` ```````..```..-:+ohhyooossoooshdhhyyys/////////////++ddhdddmmdyhdmmmdyhdmmdss++//:.``.//:...``` ````````````` ```````````
+ ``` ``````........-osshmmysssssosyhhyo+os+/+//////////:/:sdhddmmmmdhdmmmhydmmmdyy+//::-.``///``` `` ````````````` ```````````
+ ``````..--------:+ssdmmdssyyyshyys///::::///::::::::::/sddmmmmmmdhddddssmmmmhsys:-..````://`````` ````````````` ````````..`
+ ````````````` ` ````````..----:/::/:+shdmmmyyyhhyhdho//o/////++/+/////////ohdmmmdmmmdddhhhydmmmdyhh+:--...-/+/-...`` `````` ` ````````````````````````
+ ````````````` ` ` ```````...---::/++++osdmmmmdyyhhyymdh//syo+o+++oo+/+///++++shdddddmmmdhyyhhdmmmdyyhs+/:::-://:-..` ``````` ````````````````````````
+ ````````````` ` `````....---:///+ooossmmmmmdhdhhsymmd++yhhoo++osso/sy+/+++++yyyhdhdmmdhssyydmmmdsoo++o+/:---.```` `..` ```` `.```.````````````````````
+ `````````````` ` ````......--:/++osyhhydmmmmmmmmdsydmdsshhmho+ossso/sho++++++yssosymmmdyooooshhs+::-...------..``` ```` ``` ```````` `````````````````
+ ```````````````` `` ``````....--:/+oooyhmdmmmmmmmmmmyymmmhshhmdysossso/yys+++o+oy++++smddhso:---+o+:::---....-://-.```````` ` `` `````.` `````````````````
+ ```````````` `` `` ```````..---::/+osyydmmmmmmmdmmmhdmmmhssyyhhhysoooss++///o/+++++shmdhhyo///++o+::--........--:-````````` ```` `````.`` ````````````````
+ ``````````` `` ````````.---:::+++++:/+osyyyyyyssyo/:--..-:--:+///+:::---+:-..-+ymmhydy/.....::-` ` ``.` ``` `.```.````...````````````
+ ``````..``` `` ````````....--..``` -/-/s/-` ``` ``` :- `.sdmmhyyy-`` `.:..` ````.`` ` `````..`....`````````````
+ `````````` `````````````.....-` `:/-/y+-` ` .` `::.`/+ssso:+y:....-:-.....` ``...::-.````` ````````````````````````````
+ ```````` ```````````.....---- `-:/-/sy/. ` ..` ``..-..-:::-......```` :yyysso++/:-` `````````..````````````` `````
+ `````````` ```````````.....-..- `.`.-:::/./+os:.````.-.` ` ``` -.......`` ``....``````````
+ `````````` ```````````......::: .:+o++++:/++syyys+//:.``` ``.......``````
+ `````````` ````````````.-:///-//:.````..-+hddmmmmmmmdmmmmd/-.``.. `.......````` `
+ ```````` ```````````....:os/++.-oyssssshmdhyssyymhoohmmd/`````` `.......````` `
+ `````````` ````````````` `./ossy+:.-:-:///yshhyodo/hhdo+h+.-.-.` ``````.```` ````. ```````` `....`.....```
+ ``````````````` ` `./osy+s+----:/:-:+:ymdo` -yh-:+:.:///++syyossoos+/:. ``````` `````` `..` `..```
+ `````````````` `../+so++:::..:-.-.-/yh/ .o/-+oshs//osyhy:---+o/--` `````` ``` `...```
+ ``` ````````` ` `..:oo/` ` `./--.//++/ ::s+oyo+-+soss+::+/.` `..`` `` ``````
+ `````..````` `` `..:/ `..:/.`:ooo+. sso+oos+oosooooo- .. `.`` `` ` `````
+ `` `.` ``` `--::.```//: -/:/+-.`.:...-.` .-: `.` ````` ````````
+ ``````` `````` .``/o+/:::+` ...`. `-.` `.` ```--`..`.`.` ` ``````````
+ ```````` ```` `````` ` ....:///:-:. `.`` `` ` `::/-````` ` ````````````
+ ```` ````......`.` `` ` `` ````````
+ ``` ```
+ `
+ ````
+ `.:-
+ `..::-
+ `.--::/.
+ `..` `.---::/:.
+ -//. `.--:::://:`
+ -++- .-+/:::///-`
+ .++/ `-:yso/////-`
+ `:+o+`.:/hhys///:.
+ .:/+oo-://hhhho/:-`
+ ://+ooo+//hhhho:.
+ ./+++oyhs+/ydso/ ``
+ `:++++ohmh+/ydso/ ``
+ `-/oo++odmmo/ydys+ `
+ `-osoooodmmh+sddy+
+ ```/ssooodmmd+odmy+`
+ `````:ssssydmmmo+dmy+```
+ ```````````./ssssddmmms+ymdo.``` `` ``
+ ```````````.-ssyyhdmmmmy+smmy/..``` `` ``` `.`` `
+ ` ````````````.:syyyhdmmmmh++dmy+o:.``````` `````
+ ```````````````...:syyhhdddmmy++sdyoss-.``.``` ``` ``
+ ````````````..--.--:yyyyhddyhdy+++oo+sho:-.-.``` ```` `
+ ```.``````......-++:::syyyhddysyo++++++ohh+:-:-..``` ````
+ ```````````.````.........-ooo++yyyhhhy/+o+ooooooody/-::-.```` `````
+ ``````````````.`.............-/++/oyyhhhy+ooooooooooshy:/:--..``` ``````
+ ```.``````````........----.......---:/shddhyooooosyooooosh+/:---..`` ```````` `
+ ````.-::-.................-------------::+hdddyoooosdmsooo++yy/--...`````` `````` `````
+ ```````.:/:-....----------------------:::://ydmmdhysosdmmdooosyyho::---...`````` ```````` ````
+ ``````--:/++------::::::::::::::::::::::////sdddmmdhyshdmmmysyhdddy///:::-.``````` ````````````` `
+ ``` ``````.::++oyo:::::::::::::::::::::::////////ydddmmmdhyddmmmyydmmmdh+////::..`-/-```` ````````````` ```
+ `````````.-//+oshh+-:::::::::://///://///////////yddddmmddydmmdmyydmmmdh+++//::-.-///.```` ```````` ``` ``````````
+ `` ```````.:/+oohdmo-:////:::///////////////////++odmdddmddhdmmddyymmmmmy++////:-.`://....``` ```````` ``` ``````````
+ `` `````.......-/oosddmy:://////////////////////////o+:hmdhddddhddmmmyymmmmmho++/+oo+:`.:/....``` ````````````` ```````````
+ ``` ``..-----.:::+shmmmd+//////////+////////////////+o+odmdhdddhhdmmmhydmmmmms+//oyso/.`-//.`` `` ````````````` ```````````
+ ```...----::+ooydmmmmo//::::-::://:::::/::::--::::+oosddhhhhyhmmmmdyymmmmmh+:-+yso/..//:-.```` ```````````` ```````````
+ ```````````` ```````..---:::::oshddmmmdo++/////o+/++///://///::::://++osdhyyyyhmmmmmddmmmmmdhyo+sddhs///--....`` `````` ` ````````````````````` ``
+ ` ``````````` ` ` ``````...--::::/++sdmddmmysyo///+oy+:+++oo////////o+///+ooyhyyyyyhdmmdmdmmmmmmhyyooyhhyo//:-....` ```` ````````````````````````
+ ````````````` ` `````.....--:////+ooydmdmmhhdy+++odh+//ooys////////+s/++/oshhoossyydmdddyyhdmmmhss++so+/-....```` `.. ` `````````````````````````
+ ````````````` ` ```..`......-:+++ossyhmmmmmmmys++dmds//oyhhs+o+/////oo+//+ohysososhmmddhoosyhdy+::--...---::...`` ``` ` ``````` `````````````````
+ ````````````` ` ` ```````.....-:+osooyhdmmdmmmmdyshmmmd+/ohyshdhsoo++o+oo++++ss++++smmdhy+::-:oo+/-----....:/::..````` ` `````.` ````````````````
+ ``````````` `` `` ````````..--::/+oooyhdmmmmmmmmmmmmmmdsoohs++ossooo+/://:::////++ymmdhds+////s++/--.......`...-.`````` ` ` ` `````.` ````````````````
+ ``````````` `` `````````.--:::///::::++syyyyyyso/:--........-----:------.//-.-+dmmhydo:```.:::-. ` `` `````````````````````````
+ `````````` `` `` ````..---.``` :/:-` `-.`` ` `::``odddysyy- `-:-.. `````` `` `````.```..``````````````
+ `````````` ``` `````````.-..--` `:/-:.` .+::`` `./o:-+ooo+:+y:. `.-:-.....` ``.--:-.````` ```````````````````````````
+ ` ````` ````````````..::--:- `-//-:/-.`` -yo-`` `.---:::-:-.......``` :yhhysso//::.` `````````````````````
+ ```````` ```````````....----- `.-://:./+:``` `-.:s:` ` ````` --.......` ``....`````````
+ ```````` ```````````......-:: `..--:////:-+o++oooys://.`..` `....````````
+ ``````` ````````````..-///.:`.`` `:++/+ydddmddhhhhdmmdo--.``.. `......``````
+ `` ``` ````````````...-+o/+/`.+ooyyhhdmmdhssmhdhyhdmmd+.``` ` ` `.......`````
+ ` ```````` ```````````` `./ossy+-.-::/+//y+/yysds-+ddo+ho----..````````.```` ````. ```````` `...``..`````
+ ``````````````` `./oss+s+----///-:+-osoo. `oy-/+:.:///+syyyssoooso/:. ``````` `````` ``.` `````
+ ````````````` `../+so++:::..::.-.-:/+- -o/-+oshs:/ooshy/-.-+o/--` `````` `` ``````
+ ``` ```````` ` `..:oo/` ` `-/--.:++/: ::s+oyo/-+soss+::+/.` `..`` ` ``````
+ ``` ```````` ` `..:/ `..//.`-ooo+. sso++os+ooso++oo- .. `.`` `` ` `
+ `` `.` ``` `--:/.```//: -///+:.`.:...-.` .-: `.` `` ` ``````
+ `````` `````` .`./o+/::/+` ...`. `-.` `.` ```--`..```.` ` `````````
+ ```````` ```` `````` ` ..../+/+:-:. `.`` `` ` `::/-````` ` `````````
+ ``` ````......`.` `` ` `` ```````
+ ``
+
+ ``
+ `+++/:-- ``-`
+ .+++/::- `.-.
+ .++++//:``..-::
+ -ooo++/-.---.:/.
+ .+oooo+//:/+:.-/-
+ .+ooooo++//ss/.`.-.
+ -+o+++oo++/+yyo--.`.
+ -+++++oo++/+hhs:/:-`
+ +++++o+++/+hho-/::-..`
+ -++++o++++oyo+-//:::-.
+ /+++o+++++oo/:///:::`
+ `+++o++///++/:////::`
+ `:/o++//:::--////::
+ .+++//-.``-////:-
+ `.--::-.``-/////-
+ ` ``..-:.``.:////:`
+ `` ```.:.````-::::.
+ `.````-:-.`.` .: ```
+ ``...../+:---``````-` ``
+ `````````.:::/oo/:::``````://-.`` `
+ ` ` `````````````.-:+osys+/++--.```-++o+/-` `
+ ``````````````````..oosyhhyo+yhs+-....+ooo+-```
+ ```` ``` ```````````````````.-shyhhhhs+hddh/----/oso+..```
+ `-://-````````````````....``````....-+dhhhddysdmdds::--:sss/...```` `
+ `://+o/-``````````..`................-/dhyhddhhddmdy+/:-:sss/....``` ``
+ ``://os+-.`````........................:ddhhdddddddds+:---oss:...```` ``
+ ```-/+sys/..........------------.....----dddddddmddyyo/::::oss:-.....```` `
+ `````./oyhy+----------------------------:::hddmdddmddyy+///+oyyy/::---::.``
+ ````````/shhho------:----:::::::::::::::::://+yhmdhdmdmdhs+++osddhs::::-+o+.`
+ ``.````...:hdddo/:::::::::::::::::::::::::::/++/ohddhhddmmdy+++oydmmd/::::oso/. ``````
+ ````....``.--+hddds+/::::::::::::::::::::::::::/so+yhhdhhddmmmhsooohmmmd+/:::oso+-`````````
+ ```...--..-:/oydmmso////////////::::::::::::::::oooyhhhddhdmmmhsossdmmhho/:::+yo-``` ````` ` ``
+ ` ``...------/oshdmmso+/:///////////:::::::::::::::o/syhdddhmmmmmyoshdmmdhyo:::ods-``````.` ```` ````````
+ ````...------:shddmdso/::::::-:::------:::-------:///oyhdhdhmmmmmmhymmmmmhyso::oh+/.``` `` `` ```````
+ ` ```` `````..---:-:::odmmmmdyso/+so+/+::::::::://::::::::/++syyydhdmmmmmmmmmmdmmhysyss//++:.```````` ``` `
+ ```````` ` ````...--:::::/ohmmmmmmddyyhhho+/::///+////:::::::///oshssyhdmmmmdddmmddmmdyosos+/++-...````` `` ``` `
+ ````````` ` ```````...--:///+oyhmmmmmmmmdhddmy+/::///+s////////:/++/+ohyssshmmmmmhhddhhdmmyoo+++//:.``````` ``` `` ``` ``
+ `````````` ` ````````....-:/++oshmmmmmmmmmmhmmmhyo+/+///oy//++/++//++//+hsososmmmmmhsoo+sshy/--..``.````````` ` `` `` `` `
+ `````````` ` ````````...--:/+oooymmmmmmmmmmmmmmmhyoooo++ohdysooo///////+ys/+oydmmmms/--./++o--....`````` ```` `````` `` `
+ ```````` ` ` ````````..--::/+o++sdmmmmmmmmmmmmmmmho++oo+oyhho++o/::-::::++/+ohdmmdds/::/+o/+:-...`````` ``` `````` ```
+ `````````` ` ``````.-://++o+//::::/+oyhhhhsoo/:--.```.:-oss:-::-...--.-.-+/syhmdyds:``.::-/-` `` `` ``` ``````
+ `````````` ` ``:::://:.``` `////. .-.oso. ` `-++yoyhssys: `--.--` ` ```` `` ``````````
+ ````````` ``` ````````-::::-. -////.` .:..+s+` `/oss/++o/:oy:. .-.-.....`` .---:-` `` ``` `````
+ ```` ````````````..-:::-- .:////..` `://-``-. `.....-:-.....```` -yyhhyso/:::-.` ``````
+ ``` ````````````.....`.. `://///...` `+oo/.``.. ` ` .....`..`` ``````````
+ `` ``` ````````..````-- `.://///-.-//++ydmhs/:--` ``` ```````````
+ ``` ``` ``````..-:::.-`.````-::+shdddddmmmmmmmmmds/-.-``.` ```````````
+ ``` ````` ``````...-+o/+/``:/+oyhhdmmddhymyhhsydmmd/.``--` ```````````
+ `````` ```````````` `./osss+-..:-:/:/yh/:+/ds-/hms+ho--::-o.``..```.```` ````. ```````` ```````````
+ ````````````` ../oss+s+----///-:o-//+o. .oh:/+/.:///oyyyhyo+ooso/:. ``````` `````` ``` ````
+ ````````````` `../+so++:::.-/:.-.-::o/ -o/:+osys-:+ooo+:..-/o/--` `````` ````
+ `` ``````` `..:oo/. `.``-/--./++:: --s+oyo/-+oooo/-:+/.` `..`` `
+ ` ```````` `` `.-:/ .-.//.`-ooo+. sso+ooo++oso++oo: .. `.` `
+ ` `.` ```` .:://.```//: -//++:-`.:..--.` .-: `.` ``` ` ``
+ ``` ````` ...+s+/::/+` .....` `-.` `.` ```--`..```.` ```
+ ````` ``` ``````` ` .-.-/+++/::. `.`` `` ` `::/-`````
+ `` ```...----..` ```` ``
+ `
+
+
+ `:::`
+ .:-.
+ ```--. `
+ --..` ``
+ -- ..`
+ ` `.`
+
+ `
+ ...``
+ .....
+ .----
+ .----
+ -:---
+ `::::-
+ -::::-
+ `.::+s:-` `
+ ```---sh/:. `..`
+ ``..---sdo/-` `-//:.` ```
+ ``.---:sdhs/.`````-:///-` ``
+ ````````-----:/sddy+:.`````...//- `
+ ` ` `````````````.-::-//odmho/-.`...:.`...` ``
+ `--.````` ``````````````````....--//odmdso:....:/:-.`.```
+ `-:::-.`` ``````````````````````````....-/++dmdhs+--::+s+--`...``
+ `::---`````````````````......`````.....-/::/++dmddyo:-:+shy:-.....```` ``
+ `.``.``````.````....`...............-//+//+++ddddyo:::/sdh:-.--....`` ````
+ `````....-://:.......................:++++++++yhyds/---/ydd:--....```` ```
+ ``````````-://++++:-----------------------:+o+++++++osdy/:::+hmm/::---....``` ``
+ ```````````-:/+++++/:::::-:::::--::::------:/syoo+ooooshdy+//+odmmh+//:::---.`` `
+ ```````....//++ooo+::::::::::::::::::::::::+oshsooooooyddsooo+odmmdhy+/::::--.` `` `
+ `````......-::++oooyys+/::::::::::::::::::::::ossysoooooohdmhyydssdmmmhho///::::.``````````
+ ````.......-::osoooysy++//////////::::::::/::/+osysoosssyddmmmmmddmmmmhhs////:/+-`````````` ````` `
+ ````..-----.-//osssssyyso+//////////::::::::::/+ooysooshhyddmmmmmmmmmmmdhh++///++/.````````` ````` ````````
+ ` ````..----::/+soyyhyyyyyso+//////////::::::::::/oosyoooydhddmmmmmmmmmmmmdhsos+++++.``````` `````````` `````````
+ ````...---:+ooshyhddyhhyyyoo+:::::::-::::::-----:+ooyhoosdddddmmmhmmmmmmmmdy+ss+++/.```` ``````` ````````
+ ` ````` `````...---:+osyhhhmmhdmdhysoyo//:::::+/://:::::::/+ssdyosyddmdmmmdddddmmmmmhyysoo+/-...``````` ````````
+ ```````` ` `````...--::/oyddmmmmddmdhhyyyhs/:////oo+o/////////osshhssyhddmmmmhddhhhmmmmhyhys++/-......``` `` ``````````````
+ ``````````` ` ````````..--::/+oyhdmmmmmmmhhhyyhhhs/////oyoyy+///////+ooyhssyhdmmmmmhhhyyydmmmhosso/--.```````` ``` `````` ``````` ````````
+ ````````````` ` ````````...-://oosyhmmmmmmmdhysyyyyyo/++/oyyhmyo/++////++oyyohyhmmmmmhyso+oshso/:-....`.``````` `````` ```` ` ````
+ ``````````` ` ```````...--:::/+oshhhmmmmmmmdsooshhyso+++syyhmyoooo+///+++ssshymmddhh+//:--/y/--.--..`````````` `````` ```` ````
+ `````````` ` ` ````````.-://////+ohdhdmmmmmmmdysyhmmyo++osoosoooo+/:::-:::/+hhdmhhhsdo/////+o+-........`` `` `````` `````
+ `````````` `` ````````.-::///////--/oyhhhhyo+/::---...-/::-::+//---....--oyydysyssds-`.:---/. `` ```````````````
+ `````````` ` `````----.``` `-:::::. `----:.-` ` ` `:+yyy+sysshs- `-.-.:. `` . ````````````````
+ `````````` ``` ``````````..--` ::::::. -//://.-` `::ys:+oo+:os-` ...--.`..`` `---//. `````````````````
+ ````` ````````````.....--- ::::-. `.oyyss/-:.` `.--.-:-.....```` -syhddy+:::---.` ``````````
+ `````` ```````````....``.-- `-/++-` ::hddhy+:/-` `` ` `` .---..```` ````````````
+ ` ```` ``` ```````...`.``-: .-oyys/:--://symmmdy/:+: `` ````````````
+ ` ```` ```` ```````..-//:.-`-```..:+shdmmmmmmmmmmmmmmd/..+/`.` ````````````
+ ``` ````````````...-+o/+/``:+yysydmmhyyosdoohyhdmmh-../+` `````````````
+ `````` ```````````` `.:osss+-..:-::::sd+:ooms.-hmy/h+.--/s+```..```.```` ````` ``` ``` `````````````
+ `````````````` `.:+ss+s+---.:/:-/y//o+o. `+h:/+:.://+ssyyhyooosyo/:. ``````` `` ```` `````
+ ````````````` `../+so++:::..::.-.-:/s: .++:+osys-:+oooo:..-/o/--` ````` ` `````
+ ``` ```````` `..:oo:` ` `-/--.//+:: --s+oso/-/oooo/::+/.` `..`` ````
+ ` ```````` ` `..:/ `..//.`-ooo+. oso+ooo/+ooo++oo- .. `.` `
+ ``` ``` ``` .--:/. ``//: -//++:-`.:...-.` .-- `.` ``` ` `````
+ ``` ````` .`./o+/::/+` ...`. `-.` `.` ```--`..```.` ```````
+ `````` ```` ```````` ..../+/+:-:. `.`` `` ` `::/-````` ` ```````
+ `` ```.......`.` ```` `` ```
+ `
+
+ `
+ `
+ ``
+ `.``
+ ``.-.`
+ ``.-.`
+ `..-..
+ `..-..
+ .-.`
+ -.`
+ ...
+ `.--`
+ `.::` `
+ `.-/::`
+ `..--+o/:`
+ `.-::oo/:.
+ ``-::///:-`
+ `.-:::://:-``` . `
+ ``-::://///:::--````:` ```
+ `` ``.-::::///////////:--/` ` ```
+ ````````..-:////////////////+s+``` `` ``
+ ` `` ``````````-:::///////////////+yhs...`.``` ``
+ ` ``` `````````````...-://///////++++++-/+dmy:--`...`` ``
+ ``...````````````````...-:///+++++/+oo++/::odmh/::.--..`` `
+ ``````/:.```````......```....:///+++++++ydds///+hmd+/:----..``` ``
+ ````.-/s:``....`..............-+//++++++oymmdo/++smms+/-:---...` ````
+ `` `````````..-:++......................:yo++/+++++ymmmyos+ommhs/:---...``` ```
+ `````````````...:+oo:----------------------/yyo+/++oooymmmhyyyymmmhy+::---...``` ``
+ ``````...````...+sso:::::-:::::::::::::::::+ydso++oosohmmmdhdmmmmmmdhy//:::-..` `` ```
+ ````......-...---oss/:::::::::::::::::::::///oddhs+osyymmmmmmmmmmmmmmho////::-.` ````` `````
+ `````....-/:::::///+oo/:::::::::::::::::::::///ohddh+oshhmmmmmmmmmmmmdmds+////::-`````````` `````` `
+ ````...../o++++ooso/oso////////////:/::::://///ohdddooshhdmmmmmmdhdmhymmy++////:-`````````` `````` ``
+ ``````..--+oooosyhhyssyo++/////////////::::////+oyhddsoshddmmmmmdyymmdydmho++///:.`````````` ``````` ` `````````
+ ` `````...::/oossyhddhyyy+/++//////////++//:::/://+sshdyoshhdmmmmmdysdmmdhmdyo+//::-.``````` ``````````` `````````
+ `````...-::+ssyyhmmyyys//:::::::::::syyys:----:/+oohhyosyydmmmmmhsohmmmmmdhy+///-.````` ```````` `````````
+ ```````` ``````....-::/oyhdmmmdhyo////////::::/yyhhh/::::://ooyyyssyyhdmmmmhyoydmmmmmhhy++++:.....`````` ``````````
+ ````````` ` ``````...--:++oshmmmmmmh++++++++//////yhddh//////+/+oyyssshhhdmmmmyysyhmmmmmhyy+++++/:-.....`` `` ````````````````
+ ` ``````````` ` ` `````...--//ooosyhmmmmmmyo+++oooso++++shmds//////+/++sossoyhhdmmmdyssyyhdmmmhoso///:-...````` ``` ````````````````````````
+ ````````````` ` ```````....-:+oossyyydmmmmmmhsoshhhhs+o+oyhddho///+++//+oossosyhdmmddysysosyhys/:-......````` ` `````` ````````````````
+ ```````````` ` ```````....--:/+osyyyhmmmmmmmmdhhddddy+osyssyhdho++s+///+++oo++symmhsyo+s---/o//-......`..``````` `````` ```` ``````
+ ``````````` ` ` ```````....--://+ossydmmmmmmmmmmmmmmmdssso++ooooso++::---::////ohmdyoysy+////+::....`````` ``` `````` ``````` ``````
+ `````````` `` ````````..-::////::-/oosyyyssoo+/:-://:---:/-:://:---........-+dhhoshh/``-..:-` `````````````````
+ `````````` `` `````.---.`` -::. `+/:..--. ` `-.ssyhyyys- ..--.` `` `` ``````````````````
+ `````````` ``` ``````````..--` `:::` :oo+--::. -/s/oso+:/s-` ..--..`..`` `.-:/+/. ``````````````````
+ ````` ````````````.....-:- `-/o+:` `ohhy:://. `-//----.....``` -syhddy+:----..` ```````````
+ `````` ```````````....``.-- `:oyhyo:.`..``.ymmh/-//. ..--..```` ````````````
+ ` ```` ``` ```````...`.``-- `-+syhdmdhyyysoodmmdo///. ` `````````````
+ ` ```` ```` ```````..-//:.:`-````-/syyhdmddmdmmmddmmmo-:+-`` `````````````
+ ``` ````````````...-+o/+/``://+syhdms/s+ydyhdhhdmmy-.++.` ``.``..``````
+ `````` ```````````` `.:osss+-..-.-::/hd+/ooms:ydd++h/.-:+s/```.`` `.``.` ````` `` `````````````
+ `````````````` `.:+ss+s+---.:/:-/s//o+o. .os-/+:.:///oosyhyoossys+:. ``` `` ```` `````
+ ````````````` `../+so++:::..::.-.--/+- -o/:+osys-:+oooo/..-/o/--` ``` ` ` `````
+ ``` ```````` ``.:oo:` ` `-:-..:/+:: --o+oso/-/oooo+::+/.` `..` ````
+ ` ```````` ` `..:/ `..:/.`-ooo+. oso++oo/+ooo++oo- .. `.`
+ `` ``` ` ` .--::. ``//: -//++:-`.:...-.` .-- `.` `` ` `````
+ ````` ````` .`./o+/::/+` ...`.` `-.` `.` ```--`..```.` ```````
+ ``````` ```` `````` ` ....///+:-:. `.`` `` ` `::/-````` ` ```````
+ `` ```.......`.` ```` `` ```
+ `
+
+ ``
+
+
+
+
+
+
+
+ ` `
+ ```-.. ..
+ `..---` -`
+ `..-:-` `-`
+ ``..-:--..--` `
+ ``.---::--:::----.`
+ ..----:::::::::::.
+ .---:::::::::::::.
+ .----:::::://::::``.`
+ .----:::::://::::---`
+ ``.-..--:::::o/:::::::. ```
+ `` ```````.--::::/s/:::::::. ```
+ ` `````````....---::://+y///-.-//.` ` ``
+ ```````````````---::/:::/o+oh+/:.../+.``````` ``
+ `` ``````````````....-::///////yysds/-..-+:.--.`..``
+ ``````````````````````````..::::////+++/hmdsy-----o:-:--`...`` `
+ ````` ``.````````````````............/////+++oo++ddo+:----+o//:-.....``` ``
+ ```````````-+-``..``````........---.......//+/+++oysohdy++::::/so+/:---....`` ````
+ ``````````.-+y+...................--.......-+s+++++sdydmd+h//o/:+++/:-:...```` ```
+ ```.```....:shs-----------------------------/hhsss+ohmmmdsmyyyo:++++/o+-....```` ``
+ ```.....---/yhh/--:::::::::::::::::::::::::::shysysyodmmddmmmdsoooooyyo:::---.`` `
+ ````....-:::+yddo:::://://:::/::/:::::::::::::/oo/+sdssddhdmmmdhsyssshhs/::::--.` ``
+ ``````...-/++oshdmh//:///////////////////:::::://++/:sdsyyhhdmmmhyydhsshhy////::-.` ```````
+ ``````...:ossyydmmd+:::///////////+oss+///////////o/+yhohyhddmmmyhdddyydhh///++/-.`````````` ` ``` `
+ ` ``````..../yyhydmmmyss+++++++++++osyyyyo//////////+:+hhshhddmmmmhdhmdddmhh+//oo+:.````````` ````` ` `````````
+ `` `````....:oshhhmmmmhhyy++ooooo++++oyhhhhy/:://::/:::odhydhhmmmmmddhdmmmmdhs++ooo+.```````` `````````` `````````
+ ` ```````....-+shhdmmmmmhhysyyysss+////yyyyho::----:::::yyyydhydmmmmdhhhmmmmmds+++++/:`````` ``````` ````````
+ ````````` ````````....--:/+syhdmmmmdhhhhhhhhyo//+/syhhys/::::::::/+yohddhyhmmmmdhhhdmmmmdyysohy++/::-.`````` ````````
+ `````````` ` ```````...--:/++ssoymmmmmdhhhhhhhhs//++oyyho++////////+oooyddyhhhmmmdhhhhdmmmmdddydmy///:-...``` `` ```````````
+ ````````````` ` ````````...-://+osysymmmmmmdhhhhhhhs//+++oyhhy++++++//oso+oyhhyyhdmmmhyyyyydmmmyssoyyo--.```` `` `````````````` ```
+ ````````````` ` ````````....-://+oosyhmmmmmmmdhhhhhhs//+++ohmhhs+++++++oso+ooyysshmmddyoyoosysso:--.......`` `````` ```` ````
+ ````````````` ` ````````..--/://+oosyhmmmmmmmmmdddddhsoossyddyyho++++++oo++++++o/ymdsy+/o--/+:/:-....````` `````` ```` ```
+ ``````````` ` ` ````````..-:+//+++osydmmmmmmmmmmmmmmdhyyyyysso+/+o+/::-:::::////+dmhshhs+:/+o/--...`````` `` `````` `````
+ ``````````` `` ````````..-::+/++//:::/+syyyysooo///++/-:/+----::/:--...-.....--hddhydh+.`-::-.` ```````````````
+ ``````.``` ` ````````..-::.`````.`..` `/oo:.-:o. `` `-ohddhyhy- .---` `.``-: ````````````````
+ `````````` ``````````````...--. `.-+: ``-hhy/.-/o-` `+s+syyo/+y:. `-.-..````` `/++osy+-` `````````````````
+ `````` ```````````.....--:- .:/o:` `:+o++hdds--:+:` ./:----.....``` .+oyhhs/:---..` ```````````
+ ````````` ```````````.....`..- `-+sssyhdhy+yhmh/:-:-` .......`` ````````````
+ ````````` ```````````.....``-- `.+sydmmdhhhdmmy+:-.` .` ````````````
+ `` ```` ```````````...-//:.:``` `-:---/osyhmmmmddmmh+-.````` ````````````
+ `` ``` ```````````....-+o/+/``-.:++ooydyyhshmmmmdddmd/..../-. `````..`````
+ `````` ``````````` `.:osss+-..-.::-:yh+++smh+ymdssh:.--:+-```..```.``.. ````` ``` `````````````
+ `````````````` `.:+ss+s+---.:::-:+://:+. .+s:/+:.:///+osyyyoossyy+:. ``` ` `` ```` `````
+ `````````````` `../+so++:::..:-.-.---/: -s+:+oshy::+ooss+-.-/o/--` ``` ` ` `````
+ ``` ```````` `..:oo:` ` `-/--.//+/: ::s+oyo/-+oooo+::+/.` `..` ````
+ `` `.`````` ` `..:/ .-.//.`:osoo. sso+ooo++ooo++oo: .. `.`
+ ``` `.`` ``` .--:/. ``//: -///+:-`.:...-.` .-- `.` `` ````
+ ````` `````` ...+o+/::/+` .....` `-.` `.` ```--`..```.` ``````
+ ``````` ```` `````` ` ..../+++:-:. `.`` `` ` `::/-````` `````
+ `` ```....--...` ````` ``
+ `
+
+ ``
+
+
+ `
+ ``
+ ```
+ ``...`
+ ``.--`
+ ``.-` `
+ ``` `..
+ `...````.--.``
+ `-------:----.
+ .-:::::-----.
+ .:::----..
+ ..``
+ ```
+ `-:---......-.
+ `-:::--------.
+ `.-::::::::::` ```
+ `.-::::::::::````````` ``
+ ` `````````.:::////+/::.`````````` `` `
+ ````````````````-::////os+//----.....```````` ``
+ ```` `````````````......::://osho///::::..--....`..`` `
+ ```` ...`````````````````````````......--.-+yydo+///++:-:/:----....``` `
+ ```````````--.`````````````.`..................-+hhds++++ho//++/:::-.-...``` ``
+ ```````````::-..````````.........--..........---/hddy+++yhhoss++://-----...`` ```
+ ``````..-:-:/:-...................-..........---:ymdho/+dmdhhhso+os+-....```` ```
+ `````-/+++////:.---------------------------------smdds++dddddhyssyyy/----...``` ``
+ `````.:+ooo+oo+:-/o:::/:::::::::::::::::::::::::--+dddyoyddhddhyyhhhho/:://:-.`` ` ``
+ `````-+ooosshyo::oy/::////:::::::::::::::::::::::-+ddmdhhmmhdmdyhddddy+///++:-.` ``` ````
+ `````.+oossymds/:oy+//+++/////+oo///:::::::://::::oddmmddmmdmmmdhmmmmhoo++o+/-.`````````` ````` `
+ `````..-+osymmh+/sys//ooo++//+oo+///::::///:://///odmmmmdmmmdmmmdmmmmdooooo++-.`````````` ````` ``
+ ` `````...-//oymmmsosyy++sssoo++++/+/////:////::::/:/odmdhmmmmmmmdddmmmmmyoooo++:.``````````` ````` ` ````````
+ ``` ``````...--:+ssdmmmhosh+ooss+++++++oo++o//////::::://ydmhsdmmmmmmhdddmmmmhooooo+:..``````` ``````````` `````````
+ ```````````..--::ossdmmmdhss///:::://////++os/:::---::::/+hmhs+sdmmmmdhhdhdmmmd+++hdo/-..``````` `````` ````````
+ ```````````` ` `````````....-::/++ssdmmmmhoo+/////+//////++ohs/:::::::://yhdso+oymmmmhyyhhhdmmmysoomh+//:-.``````` `````````
+ ````````````` ` ````````-::--://+o+odmmmmdsoo++++++////++ooohy++////////yhshhsossymmmhyyhdsydmmhddsdh+//:--...``` `` ````````````
+ ````````````` ` ````````./+--::///++ohmmmmmhhyo++++++/+oo+osyhy++++/+////yhooyhsssymmmhsydyoodmmyo++s+:-..```` ``` ``````` ````` ````
+ `````````````` ` ````````.-:--:///+ooohmmmmmmmdyyyyoo++oyy+yyhmd+//+++/+o/yssosyyssydmdhyddos++++:---.....```` `````` ```` ```
+ ```````````````` ` ````````..---:///+ossdmmmmmmmmdddhyyyhddmmdyssdhoo/+++oooo+oo+oo+oydysdhy/-/:---.....````````` `````` ```` ```
+ ```````````` `` ` `````````..-::/++++sshmmmmmmmmmmmdhhyysyhdhyo++ooo+///:::::::://odmhssdyo::/+:-....````.```.`..` `````` ````
+ ``````````` `` ````````..--::/+//::--/+syhyysoosssso///++:-..--:::-..........-/ydddhdh+.``..``` ` -/` ``````````````
+ ``````..`` `` ````````..---.` ``` ``-/syhy/::+:. ` `:syhdhhhh: `..`` `:-.-/o/` ```````````````
+ `````````` ``````````````...--. `` `-:+yshmdy+:/::.` `/s/ohys++y:. `..-..````` .o:+osy+-.` ``````````````
+ ``````` ``````````......--:- ` -oyhhyhdys/:/:/-. `/::---.....```` `:/+yyo:---.` ``````````
+ ````````` ```````````.....`.-- `-yddhyyyss++//---` ` .......`` ```````````
+ ````````` ```````````.....``-- `-+dmdyyhhdhys/:-.`` ..` ````````````
+ ````````` ```````````..-:///-:``` ``.---:oymmmmmmmmmho-.````-/` ````````````
+ ```````` ````````````...:+s/++``-.-/oyhdmmmhsdmmmdmmmdo/`````` ````````````
+ `````````` ```````````` `./ossy+-..-.-://syy//+dh/+dmyss-`----.```..```.```. ````` ``` ` ````````````
+ ```````````````` `./osy+s+----///-/+://+o. .+y:/+:.:////osyyyosssss+:. ```` ` `` ```` ````
+ `````````````` `../+so++:::.-/:.-.-::/: -oo:+oshh::+ooss+-.-/o/--` ``` ` ` ````
+ ``` ````````` `..:oo/` ` `-/:-.//+/: ::sooyo/-+oooo+::+/.` `..` ``
+ `````..````` ` `.-:/ .-.//.`:osso. sso+oos+ooso++oo: .. `.`
+ ``` `..` ``` .:://. ``//: -+//+::..:...-.` .-: `.` `` ```
+ `````` `````` -..+s+/://+` ....-` `-.` `.` ```--`..```.` `````
+ ```````` ```` `````` ` ` .-.-/++o/:/. `.`. `` ` `::/-````` ` ```
+ ``` ```...----... ````` ``
+ ``
+
+ ````
+
+
+
+
+
+
+
+
+
+
+ ` ````
+ ..`----.``
+ `.-..:::-...
+ ``------:::--`
+ `.-----::/:-.
+ `-----:/+:``
+ ``.-:/o+:```` ``
+ ```-:/os+:``/`````.:` ```
+ ```-:osyo:`.o-````.+-` ` ``
+ ````````````-/+syyy/./so:--..oo-````` `
+ ` ```````````````..-oossyyo:syso++:.+so-.`.`` ``
+ `````````````........syyyyhy/sdysss+-oyyo-...```
+ ````` `` ` ```````````````......../yhyhhy+odhyyhs:oyhy/--..``` `
+ `````````` ``````````````......``.........-oyyhdh++hmhdmy/ohhhs/:...``` ``
+ ``...```.````````````...`................---:oyhdh++ommddysydddh+/--...`` ``
+ ``.....--```..```........................----:shmmy++hmddhhymmmm+/-...``` ``
+ `````..:o:....-........-----------------------:ohmmms+odddddhmmmm++:---..``` ``
+ ````..-oh/....----------::::---:::----::::::::/symmmdyyddmmmhdmmyoo+/:::-.``
+ ``.--.-oy+-.------::::::::::::::::::::::::::://oyddmmdmdhdmmmdmmmso++/:/--.`
+ ```.:/:::ss------:::::::::::::::::::::::://::///oydddmmmddddmmdmmmyooo+/:--.` ` ````
+ ````-/////+ys/:---::::::/:://::::::::::::::///::/ohhhhdmmmdddddddmmdo+o/::--.` ` ````` `` `
+ ````.://++++/oyys::////////////:::://::::::::::-:/ohyyhddmmmdhhdddmmmo/+//::-.``` ``` ` `` ```
+ ` ````..-//++ooo/+ss+::////////////:::/+::::::::::--:syyyydddmmdhhhddmmms++///:-.``` ``` ``````` ````````
+ `````..--:+o++hdyyyo////:::::::::--::/o:--:-----:::/oyyyhddhdmdhysydmmmho/:/::-.```` ` ```` ````````
+ ``````` ``````..---:+o+sdmmdhyyyyyo+++/:://::::+y/:///:::::://+yyhhhdhhmmysshsdmmdyo:::---..````````` `````
+ ````````` ` `````..--::/++odmmmddhhhhysyy++ooo////oy//+++/::///+++yysyhdmmmdsooy+ydddyo/:::-.....`````` `` ``````````
+ ````````` ` `````..-::::/+oodmmmmmmmdhyyhho+ooos+++sy++o+///////yooyysssdmmmdo+so/oddds+/:---..```` ` ``` `````` ```` ` ``
+ ```````````` ` `````..-::::/+osdmmmmmmmmdhhhhdhysoys+odhooos+//////syyssyysmmmdh/yh+/++++--.`````````` ` ````` ``` ```
+ ```````````` ` `` ```````..-://:/++osmmmmmmmmmmddhhdddhsyyooydyooso++/+/+++o/+++smmddhyyo...---.....``` ` .---` ````` ``` ``
+ ``````````` ` ` ``````````..--:///osssdmmmmmmmmmmddhyyyssys+:/+++o+/:--:::::///+oymmdddhy/:/::--...````.` ``-//-` `````` ```
+ `````````` ` ````````..---://:::..:/oyyhhyysyyys++:.``....------..........-/odmdhdhs-.`````` .` `.:/:. `````` `````
+ `````````` ` ``.-.....` -//++:oyyo/:. ` `` `./ydmhhdh/` `` `-/--://:-` `````````````
+ `````````` ``` `````````....` /+oyo:odds/:- ``.-ooshyo/oy/- `.....````` -+.:+oo--. ` ``` `````
+ ````` ````````````...`..-- +shhs+sddy//:.` `` ``-:::::...-..``` `-:////:-...` ``````
+ ```` ``` ```````...```.- `oddhyosmmho///-.` .-.` .`.....``` ``````````
+ ` ``` ``` ```````..`.``-. .+dmdhyymmmhyoo:-.```-/. ```````````
+ ```` ``` ```````.-//:.:`.`````.---/sdmmmmmmmmmmho/.````.. ```````````
+ ``` ```` ```````..-+s/+/`.+shddddmmmmdhdmmdhmmmmy+-````` ` ```````````
+ `````` ```` ````` `./ossy+-..:-:///+hyyhhmh+/ydsss-`.---. ``..``-.```. ````.````````` ```````````
+ ``````` ````` ../osy+s+----///-/o/+hyo. .+s:/o:.:///oosyyyoosooo+:. `````````` ``` ````
+ ````````` `` `../+so++:::.-/:.--::/s+ -so/+ooyy::+oooo+-.-/o/--` `````` ````
+ ``` ```````` ..-:oo:` ` `-+:-.///:: ::s+oyo/-+oooo+::+/.` `..``
+ `` ```````` ` `--// .-./+.`:osoo. sso+ooo/+oso++oo: .. `.`
+ ` `..` ``` .:://.```//: -///+:-..:...-.` .-: `.` `` ` `
+ ```` `````` -..+so/://+` ....-` `-.` `.` ```--`..```.`
+ `` ```` ``` `````` ` ` .-.-+++o/:/. `.`. `` ` `::/-`````
+ `` ```...----... ````` ``
+ `
+
+
+
+
+
+
+ `
+ `.
+ `..
+ ``.--.
+ `-.---.
+ `.-----` .
+ .-----. +:`
+ ------` `o+-`
+ `----.` `oo+:`
+ `-::-.`..-osoo-
+ .-::::---/ssss+``.
+ .-:::::::ssssyo`.-`
+ `-::::://hhsyys``/.`
+ ````.::::/++dhsyyy-.-/`` ```
+ `````.:::/ssdhsyyho::/-`` ` ``
+ ````````````..-:/+yoshyyhddo/:-.```` `
+ ` ````````````````.....-:+ho+dydmmmh+:::-`.`` ``
+ `````````````...........-:oy+sdmmmmmmo++/:...```
+ `````` ` ````````````````..........--/ssoydmmmmmmyos+:....```
+ ``````````````````````````......`````......----+ysyhdmmmmmmdhds/---..``` `
+ `````````````````````....`.................-----+hyhhdmmmmmmmmmd+---....`` ``
+ ````````...`...............................-----:yyhhdmmmmmmmmmm+--...```` ``
+ ```````..........-------------------------------:oyddmmmmmmmddmmy+:--...```` `
+ `.....`.....-----::::::::::::::::::---::::::---::/ydddmmmmmmddmmdo+::---..``
+ ```......--::-:::::::::::::::::::::::::::::::---://yddmmmmmmdhhdmmso/:::--.``
+ `````...-:/++/-:-::::::::////:::::::::::::::::--://+yddddmmmmdhhhdmyo+//::--.` ` `
+ ````...--/osss+:--://///////////:/:::::/:::::::--:/+yddhdddmmmdhhhdmdo+///:--.` ` ````` ` `
+ ````..--/+ydhyhhhyoosyyso+++++o////:::::/+/:::::--:osyddhddmmmmhyhhdmmo+//:::-`` ``` ``` ``
+ `` ````..:///odmhhddmmhhhhhyysssss+//////::/+so:::----+yyhddhhdmmmdhsshdmms+//:::-```` ``` `````` ````````
+ ``````.-+++oydmmmmmmmhhyyssssss+::::::/:::+o/-----::/yhhdhyymmmhysooodmmo/-----.```` ```` ```````
+ ````````` `````..-:::+ooodmmmmmmmhyysssyyo///////////+o/::::///ohdhhyssmmmyso+oodmms/----....`````````` `````
+ ````````` ` `````.--::-:+ooymmmmmmmdhhyyhdho///o++//+//oo+/::/+++ohdhhhssmmdyo+osoyddy/---.-......``````` ``` ``````````
+ ` ``````````` ` `````..-:/:::/+osdmmmmmmmdhhhhhy//+++o+//+++ssso////+osyyyhysodmdsooyyosdddo/--..-.```..--.`` ``` `````` ``` `
+ ````````````` ` `````..-://////+oydmmmmmmdhyhhh+//+++oys/++ooyho///+oossoosssodmds/shy/++++-..````.```-:::--` ``` ````` ``` `
+ ```````````` ` `````````...-:///oso+osdmmmmmmdhoohho//++oysyysoosdy+///+++o+//+++smddo-yy:..-:-.....````.``/yo---`` ````` ``` `
+ ``````````` ` ` ````````.-:/::////osoosdmmmmmmmdyhysso/+syso:/++++/:-----::::://osdmddyshs/:::--...`````.:..-/:..-.` `````` ````
+ ``````````` ` ```````.---::://:::.-:/shhhyyhyyo:-...````.`......```........-:odmdddhy+.`````` .. `..``.. `````` ``````
+ `````````` ` ````..--.``` :+/--/ooo/` ` ```+hdddhdh+. `-.``..``..` ` ``````````````
+ `````````` ``` ``````````....` /o+/++so+/` `-.-ssyso+sh/- `.....`..`` --`://:....` ````` ``````
+ ````` ````````````.....--- /sssysoys+-` ` ``.---::...-..``` `-::-----.`` ``````
+ `````` ```` ``````....``.-: -yhhhyoyyhyo-...` `` ......```` ``````````
+ `` ```` ``` ```````.....``-:` `.odddhyyhdmdhys+-..``` .` ```````````
+ ``````` ``` ```````..-//:.:`-.````..-/:dmmmmmmmmmmmmy/:.`` ` ` ````````````
+ ``` ````````````...-+s/+/`./+osyyyhmmmdhdmmdhmmdmy/.``` `` ```````````
+ `````` ```````````` `./osss+-..---://hm+shomh+:ohyys:..--.. ``.``...```. ````. ```````` ```````````
+ `````````````` ../osy+s+----///:/s:+ys+. .+h++o:.://osssyhysoo+oo/:. `````````` ``` ````
+ ````````````` `../+so++:::.-/:.--::/s: -ss/+ooyy::+oso+/.../o/--` `````` ````
+ ``` ```````` `.-:oo:` ` `-/:-.//+:: ::s+oyo/-+oooo+::+/.` `..`` `
+ `` ```````` ` `.-// .-.//.`:oooo. sso+ooo++ooo++oo- .. `.` `
+ `` `..` ``` .:://.```//: -///+:-`.:...-.` .-: `.` `` ` ``
+ ````` `````` ...+s+/://+` .....` `-.` `.` ```--`..```.`
+ ``````` ``` `````` ` ...-/+++/:/. `.`. `` ` `::/-`````
+ `` ```...----..` ````` ``
+ `
+
+ ``
+
+ ..`
+ -/-.`
+ `` `//:-`
+ `.` :++/`
+ `-.` -oo+-
+ `-.. `+oo/.
+ --.` /oo+:`
+ .--.`` .:soo+`
+ `---...`/osooo.
+ .------ossooo:
+ `-://::yyyooo/ `
+ ``-os+/yhy/+yo`
+ ````oyssydmy:/s`
+ `````+sssydmmo/s.`
+ `````-osysshmmdsy-```
+ ```````.+yhhyyymmmmy/.`.`` `
+ ```````````.-oyddhyhhmmmmy:.-.```` ```
+ ````````````.-+hdmdhhhmmmmms::-`````` ```
+ ` ```````````....--ymmdhhhmmmmmmo//.````` ``
+ ` ``````````........---/mmmhhdmmmmmmooo/-...`` ``
+ ` ```````````........-----:ymmddmmmmmddsydd+.-..``` ``
+ ```````` ``````````````````........----:+dmmmmmmmmdhhhdmh---..`` `
+ ``````````````````````````...............---:::/dmmmmmmmmmhhdmmd---...``` ``
+ `````````````````````.........--.........----:::+hddmmmmmmmhhhdmm/---...`` ````
+ ````--.................................------:odddmmmmmmdhhhhmm+:-...``` ```
+ ````.+//::--...-------------------------::::-:/sdddddmmmmddddhmms/:---..``` ``
+ `` `````.+ooosoo+--:::::::::::::::::::::::::::/:-:+yddddddmmmmddddmmyo//::--.`` `
+ `..``````.-+ssyhhss+:::::::::::::::::::::::::////:::oydddddddmmddddmmmyo///::--.` ``
+ `--.```..-+syyhdyys:::::::::////:::::::::://////:::yhhdhdhhdddddddmmmso////::-.` ` ```` ```` `
+ `.-------/shhhdmdyy//////////////:/::::://///+++//+hhhdddhddddddhddmmhy+////:-.` `` ````` ```` ``
+ `.://://ohdhddmmhho////////////////:::://///+++/+sdhhhddymdhdhhhhdmmdhy////:-`` ` ```` ```` ```````
+ `` ```.://///+soshmmdhs/////////////////::::::::++++syhdhydhsmmhhyyhhhddddh///::-.``` ``` ``````````` `````````
+ ````..-::////+symmdho//::::/:::::-:::/::------:sosyhddsyhy+ydhyysyhyhdddy:--...`````` ````` ````````
+ ````````` `````..-----:/+/sdmmmds+///+oy///:::::////:::::::sssyhhhshyo+ddhysooyyhddds:--.....`...-.```` ```````
+ ````````` ` `````.-------:/+ommmmmdhyyhhhhy+/////////+///////oysyyyyssooommdhsossyyhhho://-....`.-:::-.`` ```` ``````````````` `
+ ` `````````` ` `````.---:::://+oymmmmmdhyso++//////////++++++++/oysooooososymmdhshyoosddh++ss:--.``.-::---. `.` `````` ```````` ```````
+ ````````````` ` ``````.--:////++ooshmmmmmyyyyo+o//++++++++o+++oo+/+yooo++++sydmmdhhds+/+++/...````.....--.... ``` ````` ````` ` ` `````
+ ```````````` ` ` ```````..--:/://++ooydmmmmmmddhsyhssyyyooyyyssyso+//+o++o+////+mmmdhhy:.`..--.....``````.-+-...`` ````` ```` ``````
+ ` ````````` ` ` ``````````.---:///+++ohdmmmmmmmmmmdddhysyys+:+o++++:::---:://///+ymmmdhys/::::--....````..``.-.````` `````` ````` ``````
+ `````````` ` `````````.---:/:::-..:/oyhhhyoo+/:::-.`````..---::-..........--ommmdmh+..`` ``` .` ` `` ``````````````` ` ``
+ `````````` ` ```..-..`` .``-+/:-.` `--` `.`:hhhyydy:` ` .-` `` `` ``````````````````
+ ````````` ``` ```````````..-` ` `:s+--:.`-+/-` :/-+sso/+sy/. `........`` :.`--.. ````` ``````````
+ ````` ```` ```````.....-:- ``.+hs/-+o/oso+-`.` ` ``.`.--:-......``` `-::--....`` ``````````
+ ``````` ````````````...```.: .-/yhho/oyyyyys+::-`` ` ` ...``.```` ```````````
+ ``````` ``` ````````..`.``-: `:ohdhyoohdmmddh+/:-.`` `` `` ````````````
+ `` ```` ``` ``````..-//:.:`-`` ``.--/hmmdddmmmmmmh+/.``` ` `` ````````````
+ ``` `````````````..-+o/+/``:::::oymmddds/+odmmdhdo:.`` . ````````````
+ `````` ``````````` `./osss+-..---::/hy-++-sho/hhyys:...-.. ``.``...```` ````. ```````` `````````````
+ `````````````` `./oss+s+----///:/o-/+/+. .+y++o/.://ossyyyso+++oo/:. `````````` ``` `````
+ ````````````` `../+so++:::.-::.---::+/ -o+:+ooyy:/osyso/.../o/--` `````` `````
+ ``` ```````` `..:oo:` ` `-/--.:/+:: -:s+oyo/-+oooo+::+/.` `..`` ```
+ `` ```````` ` `.-:/ .-.//.`-ooo+. sso+ooo/+ooo++oo- .. `.` `
+ `` `.` ``` .:://. ``//: -////:-`.:...-.` .-- `.` `` ` ``
+ `````` `````` ...+o+/::/+` .....` `-.` `.` ```--`.````.` ``````
+ ```````` ```` `````` ` ...-/+++:::. `.`` `` ` `::/-````` ``````
+ ``` ```...----..` ```` ``
+ `
+
+ ``
+
+ `
+ `.`
+ .-`
+ ::.
+ ``` /+:
+ `--` /o+`
+ `:/- +oy-.`
+ .:+/. /oo--.
+ .:+o/` :+/--.`
+ `-/ooo:.`:+----.
+ `.:+oso+:.-+----- `
+ `:/osssso/-+:::--` ``
+ `./+sssys+:/oos+:```...
+ `.-/ossyysooshddy/----`
+ ``:+ooyyhhyyyshddyssy+.
+ ``````/osyyhhhddshmddhhdhs/.` `
+ ````````````--syhhdmmddmmddddyyyo`` ```
+ ` `````````````...-yhhmmmmmmmmddhyyy+.``` ````
+ ` `````````````...---+hdmmmmmmmmmdhhhh/.```` ```
+ ````````````........----/hhmmmmmmmmmmhhhh/-..``` ``
+ `` `` ```````````.........-----/hsdmmmmmmmmmdhhh::-..``` ``
+ ``````````.` `````````````````.``.........----:+yoymmmmmmmmmmdhh-::-..`` ``
+ ````````.`-``````````````................----::+yoshmmmmmmmmmmdy::::-..`` ````
+ `-...-./.````````........----........-::::::+o++ydmmmmmmmmmds///:---.`` ````
+ ``-:-:+/+:..................-........--://::::://ohdmmmmmmmmdoo++/-...`` ```
+ `````-::/oo//-..-----------------------:::/++////:/+syssdmmmmmmmddhy+/:--..````` ```` `
+ ````..--.-/+-----::::::::::::::::::::::::/+++++/+///+ssoohmmmmmmmdddds+/::-.``````` `````` ```
+ ```....----//--::::::::::::::::::::::::://+yssys+++++oyoooydmmmmmmmdddho++/:-.```````` ```````` ```` `
+ `````.-:::://::-:::/:::::////////://://////+hhhhyooo++sho++ydmmmmdmmmddho++/:-.````.```` ``````` `` ```
+ ````...-:/+++/:/::://///////////////:://///+hdhhysooosyho+shdmddddmmmddho++/:-.`````..```` ``````` `` ``````````
+ ` ```.....-+yyhhy+sso+////////////////////////oydhhhysssyyhsymdddddhdmmmmdyo++//-.`````...``` ```````` ```` ``````````
+ ``` ```....-.-shdddmmddhy+++++//////////////////:osyhyyyyssyyyymmmddmdddmmmmho++//:--.``````` `` ````````````` ```````````
+ ```...----/odmmmmmmdhs/::::::::::::::///::--/+ssyyhyys++++dmmmmmmmmmmmmmhyo:--......``` `````````` ``````````
+ ```````````` ````...------:+sdmmmmmdh++///+oo+/::://++++/:/+++sshhyso++++dmmmmmmmddmmmmddh+--.........```` ````````````````
+ `````````` ` `````.---:--::/oyhmmmmmh+osooyhyys//++o++++++o+++syyyyo++ooodmmmmmmdhhmdddddhs:----........`` ``` ````````````````````` `
+ ````````````` ` `````..-:::::://oshmmmmmdshhyshhhhso+ooo+++oo+o+++oosss+++ooohmmmdddysyddddyys+:::-.`..``` `` `.. ````````````````````````
+ ````````````` ` ``````````..-://///+++ymmmmmmmmmmhhddhhyysooo+++o+++++/+++os++++oommmmddho+os+++:--..--....`````` ``` `````` ````````````````
+ ````````````` ` `````````..--://://ooshmmmmmmmmmmmddddhysssshhysy++++//+/++oo//+/+dmmmhys-...-:---......```---.````` ` `````` ````````````````
+ ``````````` ` ` `````````..--://///oshdmmmmmmmmmmmmdddysssyo+syo+++:::---:://++++ommmmhyo/////::--.....--.``.-.` ``` `````` ````````````````
+ ``````````` `` ````````..-:::+/:::--/+shhhyyso+/:::-....-...--:::...........--/hmdyhh+..````..`` ` `-. ` `````````````````````````
+ `````````` ` ```..---.`` `-::.--``.--.`````` ` `./sdds+sh:`` `` ```` ` `-` ` ````````````````````````
+ `````````` ``` ```````````...-. -:/-.::/++/-.....` ` :+:oys/+sh:. .----.....` -..-..` `````````````````````````
+ `````` ````````````.....-:- -oo/--oyyys+//:-` `` `````...-::-.....````` `:/:::--.` ``````````````
+ ```````` ```````````....``..- ./yyo/:ohdmddso+-` ``` ` `.` ..```````` ```..`````````
+ ````````` ``` ```````.....``-- `/+syso+yhdmmmhys:.```` ` ` ``...````````
+ ````````` ```` ```````..-///.:`.` ``.-:shhdddmmmmmmdyh+.``` ` ` ``.....``````
+ `` ```` ````````````...:+s/++.`--:+yddmmddhho+ydmmmdho/-``` `` ` ``.....``````
+ ` ```````` ``````````` `./ossy+-..---::/hs:+o:odshmhhhhs.----:.`..````.``.` ````.````````` ``..```.`````
+ ``````````````` `./osy+s+----///-/o-+ys:. .sy/ss+.:/++syysss++++oo/:. ``````` `````` ```` `````
+ ````````````` `../+so++:::.-/:.-.-:oy/ -s+:+ooys:osyhy/-.../o/--` ` `````` `` ``````
+ ``` ````````` `..:oo/` ` `-/:-.//+/: ::s+oso/-+oooo+::+/.` `..`` `````
+ ``` `..````` ` `.-:/ .-.//.`-oooo. sso+o+o/+ooo++oo: .. `.`` `` ` `
+ ``` `..` ``` .:://.```//: -+/++:-..:...-.` .-- `.` `` ` ``````
+ `````` ````` -..+o+/::/+` .--.-` `-.` `.` ```--`..```.` `````````
+ ```````` ```` `````` ` ` .-.-/+++::/. `.`. `` ` `::/-````` ` `````````
+ ``` ```...----... ````` `` ``````
+ `` `
+
+ ``
+
+
+
+ `` `
+ ..`/`
+ --:s: ```
+ `----.`./:+ys-`
+ oosoo/+o+osso+-.
+ +ssssssssshhhyo++:` ``` ` `
+ .ossssssyhhdmddyyhy-..`
+ `..-ososssyshdddmmdhhdd+-.` ` ``
+ .+ssssoossyyhmmmmmmdddds.`` ``
+ -sssoosssyhmmmmmmdddmy.`` ``
+ `.ossooosydmmmmmmmdmmho:`` ``
+ ``.oss+:/ydmmmmmmmdmdyyo-`` `
+ ```-/+o::+hdmmmmmmdmhyys+.``` ` ````
+ ````````..--.:oyhmmmmmddhso/+````` ```````````
+ ````````````.```.-:+sdmmmmmhys-``````` `````` `..`` ``` ```
+ ```````````.......-:/+hdmmmmdh/..`...```` ``````.`` ` ````
+ ` ````````````....------://yhdmmmdh+:..-..```` `` `````` ```
+ ` ``````````......--------::::oyhdmmdsso:-/:-..`` ` ````` ``
+ ```````````.......-::---:::::::/oydmmdyyso:+/:-..`` ````` ``
+ ```` ``````````..``.......://::::/:::///+ymmmmhyyyyyo/:-..`` ````` ``
+ `````````````````.`..............-/++/////////++ohmmmmdhhhhhhs/:--.`` ```````` ``` `
+ ```````````````........----......-/sso++o++///++osddmmmmdddhhhho/:-.```` `````````````````
+ ``````````................-------:/+yyyyssyo//:::/oymmmmhmyhhhhhhy::-..````` ``.```````````````
+ ```````.........-------------------:+yyhhyhhyhs++//+oyhmmmmhhhhdddhhh+/:--....``` ````````````` ```
+ ````````.....----:::::::::::::::::::::+hhhyhhyhy+o++oyhdmmmmmmmmdddddho+//-.``..```` ````````````` ``````````
+ ``````````.------::::::::::::::::////////yhhhhyhhhoooosdmmmmmmmmmmmddyysso+/:-``...`.`` ` ````````````` ``````````
+ ````..-.`..::///://::::://///////////////yysssyyhhssoohmmmmmmmmmmmmmyssssoo+:-.........`` ````````````` ```````````
+ `````.+sso+:/osso+o//////ossyys///////////syssysyhhyssshmmmmmmmdmmmmmdysoooo+/-.-...-...`` ``````````````````````````
+ `` ```..`/yso/ooyhhyyy+////+yhhhys///////////+ssossyyyyssyhmmmmmmddmmmmmmdysoo++/-...`.--..`` `````````````````````````
+ `` ```.....+/.-:ohddhhh+////+hhhhho////////////+o+ooyssssyhhmmmmmdddmmmmmmdddho+///::-...``.-`` ````````````` ````````..`
+ ````....---.-:+hdmmdh+/:::/hhhhh+::::///::::/++/++soo+++oydmmmmmmmmmmmmmddhh+:::---..```.-:.` ````````````` ````......`
+ ```````````` `````.....-::-:/oddmmmdo////oddhhy+//+oo++/////+o+o+oooooooohmmmmmmmmmmmmmddhs///::---....-:-` ````````````````````````````````````````
+ `````````` ` `````.-----:///osddmmmddooooyddhyo++oyo++++++/+ooooossyssssshdmmmmmmmmmmmmddh+///::----....`` ```````````` `.```.```````````````````
+ ````````````` ` `````.--:-::+++shmmmmdsmmhsydddh+++osy+++++o+++oo+ossyyoooosydmmmmmdddmmmmhyo+//+--....````` `-.` ```` `.```.````.```````````````
+ ````````````` ` `````````...--:::/++ohdmmmmdhmmmmmmmdhoy+osysdo+ooo++o++oyyysooooyohmmmmdddyyoo+::-.-::......```` ```` `` ``` `.```.`````.````````````.`
+ ````````````` ` `````````...-:/://+syhmmmmmmmmmmmmmmmddhsysyydddyoo+++++osss+/++ooodddmhhhs-://:--------``````````````` ``` ```` `.```.`` ``.``````````````
+ ``````````` ` ` `````````..--:://++oydmmmmmmmmmmmmmmmddhyyso/+ooo++::::--::///+syydmdddhhho++++:---...-::..``..```````` ```` `..`..`````..`````````````
+ ``````````` `` ````````..--:://::-.-:+syyhysoooys////-...``.---::...........-/+dmdhddys/-...-.` ``..` .``` `..`..````....```````````
+ `````````` ` ````..--.`` `.``.-` `-so/:::.` ```` `./yddhyhds-....`..` ```.` `` ` `````..`.......``````````
+ `````````` ``` ```````````....` .```--``/hhsso/.` ` ``.-` ` ``-o:+yyoooh/-`.-::--.--.. .``--.` ````````````````....``````````
+ ````` ````````````.....--- .```----+hdhyyo:` ``.```.` ` `...-//-.-.-...````` `:::::--.`` ` `````````...````````````````````
+ ```````` ````````````...```.- .-.`.-:ooshdhhds/.`::.` `` ..```````` ``.....``````````
+ ````````` ```````````.....``-. .+/:/oyhsddddhdho-..`` .` ``..........```````
+ ``````` ```` ```````..-//:.: ``` ``..-+shdmmmmmmmmhho:-``` .` ``.........````````
+ ` ```` ````````````...-+o/+/``-+yhdddmmyhhdhdmmddmmmmo.````.` ` ``.........```````
+ ```````` ``````````` `./ossy+-..---::/ho-so:ydsyhsyhd+.----:```.````.```` ..``.``````````` ``....`......```
+ ``````````````` `./oss+s+----://-/+-/+--. .ss-+s/.:/++ssysso+++oo+/:. ``.``````````` `..` `....``
+ ````````````` `../+so++-::.-::.-.--::- -s/:+ooyy+syddh/-.../o/--` ` ``````` ``` `....``
+ ``` ````````` `..:oo:` . `-/--.//+:: ::s+oso/-+oooo+::+/.` `..`` `` ```````
+ ``` `..````` ` `..:/ .-.//.`:oooo. sso+++o/+ooo++oo: .. `.````` ` ````````
+ ` ``` ``` .::::.```//: -//++:-`.:...-.` .-- `.` ```` ``````````
+ `````` `````` .../o+/::/+` .....` `-.` `. ```--`..```.` ```````````
+ ```````` ```` `````` ` ` .-.-/+/+:-:. `.`` `` ` `::/-````` `````````````
+ `` ```...----..` ````` `` `````````
+ ` ````
+
+
+ `-ossyyso+++-
+ ./sssyysoo+o:
+ `-+ssyyyysoos+.`
+ `:osyyyhhhyyso/.
+ `. :syyhhdddhyoo+:`
+ `:+/.` `:ohhddddddyooo/`
+ -ooo:`:+shddddmddyooo:
+ .oo+. -sshddddmdho+oo. `
+ `-os. `osyddddddy:--/`
+ `.:+o/ .sydddhhy+.```
+ `:/:. :yhhyyyso:.`` `
+ -syyyyys+-.` `
+ .yyyyyyy--`
+ ` .:+syhd:-`
+ `` ```+yhd/-`
+ `````````:syydm+.```
+ ``...````syyydms.``` `
+ `` ``````.----.```syyyhdy--.```` ```
+ `````````..--::-...ohhhhdd:/-.`.``` ````
+ `````````````.--:/::--:sdmmmmmy++:...`` ```
+ ` `````````````...--:://:///ommmmmmd+++/:-.``` ``
+ ````````````........-::///////smmmdmmmooyoo+:.``` ``
+ `````````````........-::++////odmmmodmmyssy+/:-.``` ``
+ `````````````......``........-:/o+++++hdmmmohmmmhsy:::--..`` ```
+ ```````````````...`................--+++o+++shdmmmsymmmdyh/://--..`` ````
+ ```````````.........................--:osss+++yddmmmyymdmmdh+::--..```` ```
+ ``````.`.........-.---------------------:+syyh+++ydmmmmhhdhmmmh+/:::--...````` ``
+ `````..-:-....----------::::/::::::::::::/+osysyo++smmmmdhddhdmmy+++++/::-.``````` ``` `
+ ````````.:+o/:---::-:::::/+++++::/::::::::/+ossyssooosmmmmhhddddmmh+oyys+/::..```````` ```````
+ ````````.+syso/::::::::+sssoo/:://:::::////+oosoooosydmmmhshdddmmmshhhhs+/:-.````.````` `````` ` ``
+ ```````..:shhyo/::::::/+o+////:////:://///++o+soossyyhmmmdsyddmmmmdddddhs+/-.`````..``` `````` ` ```
+ ````..```..-+hddys:///////+////////++///////++oosyyhhhyydmmmhhdmmmmmmdddddho/-.`.````.`-+. ``````` `` `````````
+ ` `````...``.--/dmmdy////////o+///////++//:/::/+sssyhhhhyyyhmmmdddmmmmmmddddhy+//:-..`````.-` ```````````` ``````````
+ ``````......--:hmmdh+///+/:+s/:::-:::///:--::/+ooyhhhyyso++hmmmdddmmmmmdhhy+::---.```` ``````` ``````````
+ `` ````` ``````.......--:odmmmdyy+oss+ys/::::/:/+++/::+++++oshhhys+++/odmmmhhdmmmmho+:::----...``````` ``````````
+ ```````` ` ````.....----::smmmmdyoooyhohh/////++++o+///+++++oshhhys+oossdmmdyyhdmmdhyo///:---.....```` ``` `````````````````
+ ````````` ` ````..------:::/+dmmmmsoosddodh+ss++sshydo+/++++++oyhysooosyhhmmddyyyydmdyso+//:-..````` ` `.. ``````````````` ````````
+ ```````````` ` ````...-::::////+hmmmmsoosmmhdhydy+oyshdd+++++//++syhssossyhhmmdmdsyooyys/--..--.`.````` ``` `````` ````` ```````
+ ```````````` ` ` `````..--://+oo++oymmmmmdssmmmddhhssyhssyhyoo++///++osoo/+o+odmdhdo+o+-:+/:-....--..`````````` `````` ```` ``````
+ ``````````` ` ` ``````````..--://+osyssdmmmmmmmdmmmmhyyosyyo//ossyy:::::-:::///osymmdmdhhho++++:-...`.-.--`````` `..` `````` `````` ``````
+ `````````` ` `````````..--:/::--..:/oyhhysooyhoys-...`...-:/++o-...--.....-/ommddmdhy/...-/-` `` .` ..` ```````````````
+ `````````` ` ````.-..`` `-.``:oy+ys-``` `````..` . `.sydmmddds-.``..-:` ` `.` ` `` ````````````````
+ ````````` `` ``````````...` .-..yss+yh:.``````.```` ` `.soshhsosh/-`.----.....` `.`.-.` ``````` ``````````
+ ````` ```` ```````..`..-. .--sdysoyho-.``-... `.` ``..-//:--.--.``` `:/:---..`` ``````````
+ ```` ``` ````````..```.. `` `--/ddhssoyy+-../-`` `/- ` ..``````` ````````````
+ `` ``` ```````.````-. `.`-/smmhhhhhyhho/-``` ..-. ````````````
+ ``` ``` ``````.-:::.- ``` ``..-/oydmmmmmmmmmmdhs-````-.` ````````````
+ ``` ```` ````````-+o/+/``--:/oyhddyhddyhddhdmmmy/.```.-`` `````..`````
+ ````` ````` ` ` `.:osss+-..-.--:/hy/+/:+s+-ydddd/.----:-.`.`` `.```` ..``.```.````` ``.``````````
+ ````````````` `.:oss+s/---.://-/o-//-+. `+s:os/-/+++ssysoo++ooo+/:. ``.``````````` ```` `````
+ ````````` `` `../+so++--:.-/:.-.--::: -o+:+ooyy+shdmh/--.-/o/--` ` `````` ` ``````
+ ` ``````` `..:oo:` . `-/:-.//+:: -:s+oso/-+oooo+::+/.` `..`` `````
+ ` ```````` ` `..:/ .-.//.`:ooo+. sso+++o/+ooo++oo: .. `.`````
+ ``` ` ` .:://.```//: -//++:-`.:...-.` .-- `.` ```` `````
+ ` ````` ...+o+/::/+` .....` `-.` `. ```--`..```.` ```````
+ ``` ``` `````` ` .-.-/+++:-:. `.`` `` ` `::/-````` ` ```````
+ ```...----..` ````` `` `````
+
+
+
+
+
+
+
+
+
+ ``
+ ` .:
+ `` .+
+ `.`` .o` ``
+ ...` -s:``//`
+ `...` `-yo-.os:` `
+ `.-.` `-yyo+sys-.```
+ `--.```:hhh:yhyys-``
+ `.--.``.:hhd-yhhhy-`` `
+ ````.--.`.-:hhm:yhhhy:`````
+ ````.--...-:ydm/hddhy/.```` `
+ ```````..-.-:/ohmm+hmmdd+.````` ```
+ ``````````..-:yhddmmm+hmmmd+.``.``` ````
+ ```````````....-/dmmmmmd/dmmmd+.``.``` ``
+ ` `````````````.....--:/hmmmmms/hdddhs--.-.``` ``
+ `````````````........---//ymmmmm/yhhdhhy::.:-.``` ``
+ ``````````````........---//ommmmy:yhdmddy/:----.``` ``
+ `````````````......````.....----:/++dmmm+/shdmmdh+/-::-...`` ``
+ ```````````````...`....-...........---::/++ydmm+/oddmmmdo:-::---..` ````
+ ```-+o/.````.............--.........--::::/+++smm/:/hdmmmmo:----...```` ```
+ ``````:sso:........---------:----------:/++//+oo+odm+//ydmmmmy/:::::--...````` ``
+ ````````:yyy/------------:::--:/:::-::::/+ysooossooohms++ydmmmmdooo+//::-..`````` ```
+ ```````.:hhys:-----::::::::::::/::::::/++ohyhyyysooosmyoosdmmmmdssso///::-.` ``````` ``````
+ ```````.-:ydhyo/:::::::::::::::://:::::/++odhdhhhsooooshssydmmmmhhyo/////::..```````` ````` `
+ ```````.::+ddhyo+::::::::::::::://:::////+odhdhhdsoooooyhhddmmmmhhy+//////:..````````` `````` ` ```
+ `````````.-//odhhhy/////////////:::/:::////+ohhhdhds++osssdmmmmmmmhds/////+/:--```````` `````` ` `````````
+ ` ````.`````..:+sddddh///////////////:/::::/+/++yyyhhhso+syysmmmmmmmmmd+/////+/::-.`````` ```````````` `````````
+ ````````....-/hdmdhh///::-:::-::///:/::--://///osyhyo//yyyhmmmmmmmmmh/:----:-..````` `````` ``````````
+ ` ``` ``````.......---/dmmmdy++ooyyo:::::++o++++:::///++oyyyyo+ohyhmmmmmhdmmmmy+//::--....````````` `````````
+ ```````` ` ``````...-----::/dmmmms+ydhhhh/:://oysoshhyo////+osysyhhyydhdmmmdhyydmmmdhs+//:-.....``````` ``` ``````````````
+ ```````` ` `````...---:-:::odmmmmo+shhyhh+:://+yyoydy//////+oysssyddhhhdmmddysyhhmmmhs+//::-..````` ` `.` `````` ``````` ```````
+ ` ````````` ` `````..--:::::::/ymmmmdyooyhhho:/+++hyosd+//////+ososyyyyhhhdmmhhooooshho+:-..--.`.````` `` `````` ```` ` `````
+ ```````````` ` `````..--:/o+/////ymmmmmmmdhhhd+/+++ohysyyss+/++/+ssooso++++ommddhhho/-/y/---..--...``` ```` ` `````` ``` `````
+ ` ````````` ` ` ```````````.--:/+ssyyosdmmmmmmmmdhyho+oosyyo/+yssso--://:::://++sdmmdmddhs+//o+-....`...-.```.`` ` `````` ````` `
+ `````````` ` ````````..--:/:::/..-:oshyyssdhsyy::-..``..----:/..----.....-/hmmmdmhy+..`.:o.` ` .` ``` ```````````````
+ `````````` ````...``` ..`.ods+yy:.`` `` ` ``` `.ohdmdydhs.```.-:: ``. ` `` ````````````````
+ ````````` `` ```````````..` .-.smdsohs/..` ` -- `.+oyhyo:+y/-`.----.....` `.`...` `````` `````````
+ ````` ``` ```````..`..-. .-+dmyssyys+:-` `` `./. `.--://:--.--.``` `:/::--..`` `````````
+ ``` ``` ````````..```.. .-ommoyyyhhhso-``` ``-- ...`````` ````````````
+ `` ``` ```````.````-. ````-/hmdshddddmdy/.`` ..-. ````````````
+ `` `` `````.-:::.- `` ``--::/sdmmmmmmmmmhyy+:````.--` ````````````
+ ``` ```` ````````-+o/+/``..-:+yhmmmmmhyddhhmmmho/-```..-` ````````````
+ ````` ``````` ` `.:osss+-..-..-:/ys-:+hmy::omdmmo---:::-....` `.```` ..``.```.````` `````````````
+ ````````````` ../oss+s/----///-/o-/+hs. .+hoyhy/+sssssysso++ooo+/:. ``.``````````` ``` `````
+ ````````` `` `../+so++-::.:+:.---::so -os++syhy+shdmd+----/o/--` ` `````` ` `````
+ ` ```````` `..:oo:` -``:+:--//+:: -:s+oso/-+ooso+::+/.` `..`` ```
+ ```````` ` `.-:/ .:-++..:oooo. ssooo+o/+ooo++oo: .. `.`` ``
+ `.` ``` .:///.```//: -++oo/:..:...-.` .-- `.` `` ` ``
+ ` ````` -..+so////+` .--.-` `--` `.` ```--`..```.` ```````
+ ``` ``` `````` ` ` ----+o+o/:/- ..`.` `` ` `::/-````` ` ```````
+ ```.------.-. ````` ``
+
+
+
+
+
+ ` ..`
+ `` `ooo/-
+ .-``ssso:`
+ ./-.syso-
+ ./o-yys+.
+ `+ssyys+`
+ ``` `+syhhy/
+ ``.` /syhhy/
+ `... ```-oyhhy:
+ ....`..../yhhy-
+ .......:./yhho`
+ `......./..:hy-
+ ........+.`.hy-
+ ``..---..---`/ys/`
+ `.---------+.s+o+`
+ `` `.---------:s//`-o. ```
+ ```..---------/yo.`.o: ` ``
+ ``````````.-----------/hs-.-+:` `` `
+ ` ````````````..----:::::---:hs:-...``````
+ ````````````..``..--::::::::::.-s/::-....`..``
+ ```````````.......--:::::::::::--o-:/:----`...```
+ `-..`` ```````````......`......--:://://////++shddoy:---.....``` ``
+ `/+/.```````````...`.........------:::+o//////+hhdmmdymo:--.--....`` ``
+ `.+.``````````................----::::+yo+/////ddmmmmhmd:--.-...```` ``
+ `````-.`............--------------::::::/oyyo/////dmmmmmmmmy:::::--..```` `
+ ```````.......----------:::-::::::-:::::://+syy+//++ymmmmmmmmd///::/::--.`` `
+ ```.....-.--------:::-:::::::::::::::::::::/osho++++smmmmmmmmd+///:::::--.` ```
+ `````...--:/----:-:::::::::::::::::::::://::/oyhs+++osmmmmmmmmms/////////-.````````
+ ``` ```..--+o:-.-:::::::::///////::::/::::///ooyhy++osymmmmmmmmmd+///++++/:-.````````` `
+ `````````..-:os///////////////////++/:////::::+ysyhs+oshhmmmmmmmmmms///++++:-.``` ```` ` `` ` `````
+ ` ``````````..-/s+shh/://///////////+oo+/:::::::/oysyho+oydhmmmddmmmmmh+////+/:-.``` ```` ``````` ````````
+ ``````......--+sohmd::/::oyy+//:::/syhho:::////+yysshyyhmdhmmmhhmdmmmds/::::...```` ```` ```````
+ ` ```` ``````..--.---:yyshmms/syyyddo+/:::+shdhds//ooooshyssyhddmmhmmmyyhddmmdds/::/-...``````````` `````
+ ```````` ` `````..-----::/hdhdmmmhooydddo++++++sddhyss/+ososyhsoyhddmmhmmmssyhdmmddh++:::-...````````` `` `` ````````
+ ```````` ` ````..--:::::::+ddddmmmmy+hddh++oyhyssddo/////+osyyyssyyhdddhmmmsosyydmyddso+/:--..````` ` ``` `` ``` ```` `
+ ````````````` ` `````..-://++//+dddmmmmmdodmdyoshddhysdh+//////osysyysyyyhhyymmdsoshhsdh:/:--..--..````` ``` ````` ``` ```
+ ```````````` ` ```````..--:/ooyy++sdmmmmmmmhdddddmmmmdyyhh+//+sy++yhsssoo++++ymmddsyhh+-+h/---......-`````````` `````` ``` `
+ ``````````` ` ` ``````````..--:/+oyyssyddmmmmmmmmmmmmmdhdhso/oys+++/::s+:::://++shmmdmdhhy+/+yo--...```..-``..` ````` ````
+ `````````` ` `````````..--:///+/-.:/oyhhysshdhh+::-...``.........----.....-:odmmddhss:.`./s.` `.``` `..` `````` `````
+ `````````` ` `````....``` .-::/+yyyy-` ` ` ``sdmmdhyy//.` `:/: ``.``` ``` `` ``````````
+ ````````` `` ``````````...` `-+dddhyyy:` .` `/yshddy//y/-`..-:-.....` `-.`..` ````` `````
+ ````` ``` ``````...`..-. `-+mmdyyyyo-.-:. ```.` `.--/+/:--.-...``` `:/::-...` ``````
+ ``` ``` ```````...```.. `-:dmhhyyyys+++:`` ``-. ` -...```.` ``````````
+ `` ``` ```````..````-. ``../ymdhhhhhhdhys+-` `.--. ```````````
+ ``` `` ```````.-:::.- `` `.-::/ydmmmdmmmmmmdhsso.``.--` ````````````
+ ``` ```` `````````-+o/+/``-.-ohdmmmdyhyshdhydmmdyo-``...` `` ```````````
+ ````` ````` ````` `./ossy+-..-.:///ho-sy+hdsodhdmms.--::-```.`` `.```` ..`..```.````` ````````````
+ ````````````` `./osy+s/----/+/-/o-+hh+. .+hoydhoyysyyyyss++osoo+/:. ``.``````````` ``` ````
+ ````````` `` `../+so++-::.:/:.--:/sd+ -oo/ohhhhsshdmdy::--/o/--` ` `````` ````
+ ` ```````` `..:oo/` .``-+::-//++o -:s+oyo/-+ssss+::+/.` `..``
+ ```````` ` `.-:/ .-./+..:osoo. ssoosss+ooso++oo: .. `.`````
+ ``` ``` .:://.```//: -++oo/-..:...-.` .-: `.` `` ` ``
+ ` `````` -..+so////+` .-...` `--` `.` ```--`..```.` ````
+ ``` ``` ```````` ` .-.-/++o/:/. `..`` `` ` `::/-``````
+ ```...----..` ````` ``
+
+
+
+ `:/:::-`
+ -:///-
+ .:.
+ `
+ ```
+ `.``
+ `.``
+ `...`
+ ....`
+ `...``
+ ...`
+ ..`
+ `..
+ ...
+ `.` `
+ ````` ..``--::.`
+ ``````.``.:/os+/.`
+ ```..``````./shyso+-` ```
+ ````...`````.+hdhhso:` `` ``
+ `````````````...-..-..-odmddyo:``` `` `
+ ` ```````````````.....----::::hmmmmho-...`.```
+ `````````````.........--::://+odmmmmds:---.-..``
+ ```````````````````.........-:::/+++hmmmmmdh/:::.--..```
+ ```````````````.......````......--:://+osodmmmmmddo:::.--...``` `
+ ``````````````..........-..........---:///soyydmmmmmmdh/::-----..`` ``
+ ````````............................-----://osyhdmmmmmmdd+:------..``` ``
+ ``````````......--------------------------:::///+yyhhmmmmmmdhh+:::----...```
+ ````````````...----:::::::/::::::::::::::::::/:://++yydddmmmmmdyhd+/////::-..`` `
+ ````````````.:/oo+/::::::://::::::::::::::::////:/+++hhddddmmmmdshdo+++++o/:-.`` ```
+ `````````../syyhs/:::::::++///::::::::::///////:/+++yddmddddmmmddds++++oo+:-.````````
+ ```````....-+yhhhy////////++//////////////////+/::+++ymmmmmhdmmmmdddo+ooo//:-.```` ````` `
+ ```````..--:shhddy/////+/++++/////////////////+///++osmmmmmhyddmmddmh++oo/::-.``` ```` ` ```
+ ` `````......./ydddddho//+/ooso++/////////////::///o//+osymmdmmdsyhdmmdmd+/++/:--.``` ```` ```` ````````
+ ````...--.-/hhddddddho///oyy+/////::://:::-:-://+s+//+oyhdhdmmy+yhhmmdmo:-/:-.```` ``` ````````
+ ```````` ``....--::::+hddddddmmh+++oyh++oss+/++++//:::::/+oyo+//oyyyyymmh+oyymmmmy+:::-..``````````` `` ``
+ ````````` ` ````...-::////hddddmmmmdo++oyhohhyyooyh++///////+ohys+++ssoooommdoosshmmdys+:::-...````````` ` `` ``` ```
+ ` `````````` ` ````...-::++//oddmmmmmmmy++ohddhsyyoohds+//////oshdhs++oyo++++mmdysysymmhs+o/::--..````` ``` `` ``` `` `
+ ````````````` ` `````...-:/+oo/+ymmmmmmmmdoyhdmmhosysoyds////+ssoyddhysshyo+++smmdsyhyodd/:---......````` `` `` `` `` ``
+ ```````````` ` `````````..--:/+++++sdmmmmmmmddmmmmmsoosysshy///+hmhsyyhyyss+o+/+sddhdhhh/-od/---...``.-```````` ` `` `` ``` `
+ ``````````` ` ` ``````````..--:/+++oshmmmmmmmmmmmmmmyo++ohso+oo+/+o//+o//:::://+shmdyydhys//+so---..```...``..` ````` ```
+ `````````` ` ````````..--:://+/+:://oyhysyhddy/--..`..```.....-..----.....-/ymdh/sho:.``./s-` ``` ` ````` `````
+ `````````` ` ````..-:-.``` `..``:syy+ ``` ` `-hmmmdshy:` `.::/ `..```` ` ```````````
+ `````````` ``` `````````...-` `...+yyyy+` ``` ``` ` -soyddy//y:.``.-:-....`` .-.`..` `` `` `````
+ ````` ```` ```````.....--. `.:hddssyo-` `:+. ````` `..--///:-....```` `//:::...` `````
+ ```` ``` ```````...```.. `:hmmhssso+::+ys-`` ````` ` -...````` ``````````
+ ` ```` ``` ``````.....``-. `:sdmdyssyyyyyhdhyo:`..-. ```````````
+ ``````` ``` ``````..-//:.:```````..-yhmmdddddhhmmdyyss:..`- ```````````
+ ``` ```` ``````...-+s/+/``/oyhdddmhydmmdmmdy+dmdys-```.` ```````````
+ `````` ```````````` `./ossy+-..--:::/s/:yo+dyyyo/hdds---.-+```.`` `.```` ..``.````````` ```````````
+ `````````````` `./osy+s/----://-:/.+so:` .o+-sdhsooooyhyyssoosso+::. ``````` ``` ``` ````
+ ````````````` `../+so++-::.-::.--:+hdo -o/:oyyhhsshdddyo/:-/o/--` `````` ````
+ `` ```````` ``.:oo/` ` `-//:-//+yy` -:s+oyo/-+soso+::+/.` `..``
+ ` ```````` ` `..:/ `-./+..:osoo. ssoosss+ooso++oo: .. `.`` `
+ ` ``` ` ` .-::/.``.//: -+/+o:.`.:..--.` .-: `.` ```` `
+ ```` `````` .`./o+////+` .-.`. `-.` `.` ```--`..`.`.`
+ ``````` ``` ```````` ..../+++:-:. .. ` `` ` `::/-``````
+ ```.....-.`.` `` ` ``
+
+
+
+
+
+
+
+
+
+
+
+
+ ``
+ ``
+ ``` `````
+ ``..``.`...`..``
+ ``....../s+/:-.`
+ `......-hdhhs/:.
+ `-:/:-.-yddddy/.`
+ `.+sso/--sdmmmdy.`
+ `````-yhhsoosdmmmmd-. ```
+ ``` ``````-hddhhydmmmmm/-` ``
+ ` ``````````````..+mmdhydmmddms-.`` ` `
+ ` ````````````````.....:dmdhhdmmmddds:.``````
+ `````````````...`.......:hmdddmmmmddmh+--.`..```
+ ````````````````````````............:omdddmmmmddmhy/--`...```
+ ```````````````````.......`````.......---/ddddmmmmddmhhy:-......`` `
+ ` ``````````````````.......................----:ydddmmmmdddhhhs-.----..`` ``
+ ````````.-:/+/.............................-----:ohhmddddhhdhhdh:---:-..``` ``
+ ``````.:+osyyo:--------------------------------::/hhddyhhsyddddd+/////--.``` `
+ `````````./syyhhhyo/:::::::::::::::::::----:::::---://yhddyyhsoddddh++++++/--.``
+ ``````````./yhhhdh/:::::::::::::::::::::::::::::---://oyddyssssydddd++++++/:--.`
+ ```````....+yhhddh/:/::::::///:::::::::::::::::/:-://+++shyoooysddmdyo++++/:--.````````
+ ```````-/+yyhddddh+////////////////:::::/::::://::://++++sysooysddmmdo+++/:::-.` `` ````
+ `` ``````..-shhdddddddho++//////////////:/:::/::::///-::/++++++hhyssyddmmmso++//::-.``` ``` ```
+ ``` ````..---::hhddddmmdho+/++///////////////:::::::+so/://+/+++++ymdoyddmmmsoo++/:--.``` ``` `````` ````````
+ ````..---:/+hddddmmmms++/:::::::://:-::/::-----/syhhs//////:::+mmosddmmmo:::::..```` ` ```````
+ ``````````` `````...-:/++odddmmmmmdys////////++:::/+///:::::+yydhhs+///+//+hmmyshhmmmmo::---..```````````` `````
+ ` ``````````` ` ``````.-:/+o+/sdmmmmmmmdy++++++///////+y/////+o+syhmddho+++oooymmmdsyydmmhho/:---...```````` ` `` ```````
+ ````````````` ` ` ``````..-:/++++ohmmmmmmmmdso+++o++/+++oss/////ossyhdmhhdsoooosshmmmdsssymmy++o/--.-..````` ``` `` ``` `` `
+ ````````````` ` ``````````..-:/++ooosdmmmmmmmddmhooo++oyhooo+////+syysydhyyhhdysssommmmh+yssdh/-...```..`````` `` ````` `` ``
+ ````````````` ` ` `````````..--:++++osshmmmmmmmmdmdso+++hddyoso//shdddyoyyssssso+++ohmddd+ys--od:--...```````````` ````` `` ``
+ ```````````` ` ` `````````..-:/+o+ooyshmmmmmmmmmmdsoo+sdyhhso//ooo++/::/::-::://+oymdyyysy+//+so--...`````.```.` ````` ````
+ ``````````` `` ````````...-:+/+++++//+osyhhhhdh+:-...-....```-.-.......-.....-:smmd/+ds-.``./o. `` ` `````` `````
+ ``````..`` ` ````..-/:-..``` ``../osoyy` `:` ``` ` `odmmdsyd/` `.::- `...`` `` ```````````
+ `````````` ``````````````....-. ``:yhy+yy` +/ ``` .``/oshhs//y:. `.--..`..`` -:....` ` ``` ``````
+ `````` ``````````......---- `-oyhhs/y/` `:y+-.``````` `--..:::-.....```` `//:::...` ``````
+ ``````` ```````````....``..- .osyhhy/+o+::/sdhys:.```. ` -...`` ` ``````````
+ ````````` ``````````......``-. `/sssyhy+//osyhdmmdh+-`./. ````````````
+ ``````` ````````````.-:///.:`.````..:oyddddmmddhssmdyyys/.`.:. ````````````
+ `` ```` ```````````.--.:os+++.`/+ooooyhmmmmmmmdho+ommhy-.` `/` ````````````
+ ` ``````` `````````````` `./oysyo:..--::/+ho+shyhhys/:ydmho:---y-``..` `.```` ````` ``` `` ```````````
+ ``````````````` `` `./osyos+----/+/:/o-oss:. -o/:sys/+++oydyyyyyssso+::. ``````` `` ``` ````
+ `````````````` `../+so+o:::.-::.--:ohho :s+:+oshhssssss+++:-/o/--` `````` ````
+ ``` ```````` ` `..:oo/` ` `-/::-/+syo -:s+oyo/-+oooo+::+/.` `..``
+ ` `.`````` `` `.-// `-./+..:osoo. ssoosoo++oso++oo: .. `.` `
+ ``` `.. ``` .-://.``.//: -+/+o:.`.:..--.` .-: `.` ```` ``
+ ````` `````` .`.+so////+` .-.`. `-.` `.` ```--`..`.`.` `
+ ```````` ``` ```````` ..../+++/-:. `. ` `` ` `::/-``````
+ ``` ```....--.`.` `` ` ``
+ ``
+
+ ``
+
+ ````
+ ``` ``````
+ ````` ``````
+ ``````` ``````
+ ```````` ```.```
+ ````````````````.```
+ ``````````....`````
+ `.............````
+ `.......-:/-..````
+ `.......:syyo/-.`
+ `..-/---+yhhhsso-
+ `..-ddhhhhhhhyyyo
+ ....ymmdhoyhdhhhh.
+ `....:mmdh+yhddddm/
+ ...-:dmmh+odddddms`
+ `..-ymmmdo+hdddmmy`
+ ``````..-hmmdds+hdddmmo` ```
+ ````` `````.--smmdhy/shydmmo` ` ``
+ ` `````````````.---:ddhhy:-/oydmy.`` `` `
+ ` ```````````````....----odhyo-..:sddh-.``.```
+ ````````` ````````````````.........----:so/:----sddh/--`...``
+ ````.```````````````````..```..........--::::::::-/+ydddy:-.-...``
+ ````./::--...`````````.`.......``.`........-:::::::::::yddddd+:----..``` `
+ ``````.oo++++:.`.````.........--...........---::::::://::/hddddo/:::--..`` ``
+ ``````-yhyo/:..............................----:::::::+/-:omdddy/////-..``` ``
+ ``` `````./hhho:-----------------------------------::::://so:/ymmmdh++///-..```` ``
+ ```````...-hddho+:////:::::::::::::::::-::::::::--://////+yyoshdmmmm+++//:--..``
+ ```````...-ydddyh////////::::::::::::::::::::::::::////+ssyhhhdmmdhdo////::--..`
+ `````....-shdmmddo/+/////////////:::::::::::/:::::////+syyhdmddmddmdo///+:::--.`` ```
+ ```````..+syyyydmmmms/ss///////////////::::/:://+++/////osyhhhdmddmhhmmms//+/::--.` `` ````
+ ``` ` `````...--ohddyydmmmmdohds+//////////////:://:/+ossyy//+++syhhhmmmmmhymmmh+/+/::--```` ``` ```
+ ``` ````..--::/yddddmmmmmmddds+++///////+/////::::/ssyymd+//++ohhhdmmmmmhsmmms/://::-.```` `` ``````` ````````
+ `````..-::++sdddmmmmmmdddy/::::::/+so:::/::---:syysmmh//sooyhhdmmmhhhommm+------.```` ``` ```````
+ ```````````` ``````.-://+//sddmmmmmmdddo//////yhhho::////:::+yhhymmh/+dyyshhhmmdyyysmmmos:-----..`````````` `````
+ ` ``````````` ` `````.-:////+/sdmmmmmmdddo++++++ddddo////////+shhhhddhoydhyoshhmmdssssdmmyso:--.....```````` `` ```````
+ ````````````` ` ` ````...-://+oo++hmmmmmmmdmh+++++ymmdd+////+oo+ossssyhddhhddhosyymmdsooohmmmo+//--...`````` ``` `` ``` `` `
+ `````````````` ` ```````...--://+++++ydmmmmmmddmsoooommmdho+++++dmsos++ossyhdhhhyosodmmds+oosds+:..````.```````` `` ````` `` ``
+ ````````````` ` ` ```````...--/++ooooshmmmmmmmmmdsoosdmmdddso+++sdmmdhs+yhoosss+++//smhhy-+s-.oh:--...```````````` ````` `` ``
+ ```````````` `` ` ```````...--/+/oooyhhmmmmmmmmmddyydmmmdhhys+/+o+osy+/+o/::-::://+smmyss/yo//+s+---..`````..```` ````` ```
+ ``````````` `` ````````..-:/+/++++///+osyddhhoo+::---+o-....-:::--.-.........-:ommm++hy/.``./o-` ..``` `````` `````
+ ``````..`` `` ````````..-/::-.``` .-osoo` .o+.```....` ` ```/dmmmsyd/` `.-::` `-:.`. `` ``````````
+ `````````` ````````````......-. `ossoo. `+ys+-:+:``` ` ..:osddy+/y:. `.--.....`` `//..-`` ` ``` `````
+ `````` ``````````......---- `-oyy+/+ .+shhhys+.`.` `.-..:/::.....``` ::---...` ``````
+ ``````` ``````````.....``..- ..-oyh+---..:osshddyo-``--` ` ...``` ` ```````````
+ ````````` ``````````......``-- .//--oyhs/:://+oyhdmmh/.` o/` ```````````
+ ````````` ````````````.-:///-:`````:osssyhdmmmmmmdho+mdyss:```o/` ````````````
+ ``````` ```````````.---:os+++.`----:ohmmmmmmmmmh+//hmmd-.` `o/ ````````````
+ `````````` `````````````` .-/sysyo:.-::++++hyohhyydyoo/ommh-----hs..-..``.```` ````` ``` `` ```````````
+ ``````````````` `` ../oyyoyo:---+++:+o:oyy:. .++.+s/-/++odmhyhhhysso+::. ``````` `` ``` ````
+ `````````````` `../+sooo:::..:/---:/oo/ :ys/+osyy+oosyyo+/:-/o/--` `````` ````
+ ``` ````````` ` `.-:os/. ` `-+::-/++/: `/:oooso/-+oooo+::+/.` `.```
+ ``````..````` `` `.-// `../+..-ooso. sso+++o/+ooo++oo: .. `.` `
+ `````..` ``` `--//.``.//: -//++:.`.:.---.` .-: `.` `` ` ``
+ ``````` `` `````` .`.+so////+` ...`. `-.` `.` ```--`..`.`.` `
+ ```````` ```` ```````` ..../++o/::. `. ` `` ` `::/-``````
+ ```` ```...---...` `` ` ``
+ ``
+ `
+ `````
+ ````` .``` `````
+ `````` `+s++o-` ``
+ ``````` .syyyyys```
+ ````` oyyyhhh+.`
+ `````` /yyhdddh+-.`
+ ````````:yhhddhyys:`
+ ````..` -yhhdhyyys.
+ ````/o.`-yyyhhyyy+
+ ```.yy.`:osyhhsyy:
+ ``-dd+---/ohhsyy.
+ ``-dmho-..+yysyy`
+ ``.ohh/.. .oyo++ `
+ `....-..` `o/
+ `........ `
+ ``........
+ ``........```
+ ``........`````.:/. `
+ `````````````.........```--+hyo`` ```
+ ` ` ```````````````...------``.:yhdhy-````` `````
+ `::``` ````````````````````...--------..--ydddho....``` ```
+ ``-/++``````````````````````````...........-::::::----yddddy:---.``` ``
+ `.-:+ooo``````````````.``````..............--:::::::-::/dddddy+:/:-.``` ` ``
+ ```-+ssso..-.``````````.`.......`..........---:::////:o++mmmhyoo++/:-..`` ` ``
+ ````+syhy:/+.................--..........---:://///++shysmmmyssooo+/:--.`` ````
+ ``````-syhhssy.........--..---------......---:://///+++ydhymmmdddsoo+//:--.`` `````
+ ``````.+yhhdhy------------------------------::::///////+ddymmmmmdyo+++:--..```` `````
+ ``````....yhdmdy:::::::::::::::::::::------:::////////+oo+dmmmmmmmdddyoo/::-..````` ``````
+ ``````...:yddmmy//+so+///////////////::::/:/+/+///++++syysdmmmmmmmmmddyo+//:-.`````` ``````` ```
+ ``-++:.--/hhddmdy++ydddy+////////////////+soos++///ososhhyhmmmmmmmmmmddss+++/:-.```````` ``````` ``` ``
+ ``````.+hhysyhddddmds+ydddds+//+++///////////+yyyy+////ohdhdmhdmmmmmmmmmmdhssoo+//-.`````````` ``````` `` ```
+ ``` ``````...-/hddddddddmd+shdddy+++++++++////////++yhhhys++/shddhmddmmmmmmmmmdhssooo+/:-....```````` ``````` `` ``````````
+ ```` `` ```````..-:::ydddddddmdohddddy++++ooo++++///////+ohhhhhdh+oyhmddmdmmddmmmmmdoooo+++::.```````````` ````````````` ```````````
+ ```` ` ` ````.-:///:yhhdddmmmhdddddy+oooooooo++////////+hhhhhddo+yhddhddmmdhmmmmmmooo++++:-...`````` ` ````````````` ``````````
+ `` ` ````.-://///osohdmmmmddddd////++oso/:::/++////+hhhhddds+hyhhhhdmmhyhmmmmm+/::///--.`````` ` ````````` ``````````
+ ``````````````````` ``````...-://////+//smmmmddddo++++ooo++////+oo+++++yyyhdddhoyysyhddmmhyydmmmmy+/////:--....``````` `` ```````````
+ ```````````````` ` ``````.....-::///+o+++hmmmmdddshhsoss+++++++++o++++osyshdhhhhyhssyddmmhssydmmmms+////:---.......`` ``` `````````````````````
+ ``````````.````` ` ``````....-:////osoooosmmmmmddhdmdhhh++oo+++oosyo+oo+o+yhyyhhyhyyyhdmmyoooydmmmh++//::-....`````` `.` ````````````````````````
+ `````````..```` ` ```````..--:///+osssyydmmmmmdmdmmmmmd+oyo++odmmmdo+++++oosyyyssysyymmmsooo+odds+--..........``` ``` `````` `````` ```````
+ ````````..`````` `` ````````...-:///+osyyydmmmmmmmmmmmmmmhohmyoooyhhhdddhooyo+oooo+++/+hmhy/:/+..+ho::-...```-..--```` ` `````` `````` `````
+ ```````...`` ``` `` ```````..-:/+//o+oyhhmmmmmddddmmmmmmyohhhyyyyss+/++++y+:--::///++ymmyso/y+//+os/--..```.//-...`` `````` ``````` `````
+```````...`` ` `` ```````...-//+/+++//::++shysssooo/::-/oo+oyys//--------.-.....-:smmd+oyy:.``.:/:`` -/-``` ```````````````` `
+``````....`` `` `````````..-/::-..`` .:` `:+oosys: ``` ` `` ``+dmmd/sh/` `..-:.`` .:-.`` `````````````````
+ `````````` ````````````.......--. .:` --/syyy/` .-.` `. `./oydds//s:` `.--.....`` `:-.``` ```````````````````
+ ``````````` `````````....-..--:- ::-` .:-:yhs/.` -/-` `.---/+/:.....```` -----...` `````````````
+ `````````` `````````.......`.-- -+/-`` `..::..oyo-` /o. ` ..`.`` ```..`````````
+ `````````` ```````````......``-- `+oo/:-:://+/oo+so.` `y: ``..`````````
+ ```````.` ```````````..-:///-:````:/-..:ohdmmmmmmmhssmmd/:`` -y- `......``````
+ ``````````` ``.`````````.---:os+o+.`-..:/+sdmmmmmmmmh++odmms.`` os- ` ``.....``````
+ ``````````` ``````````````` `-/sysyo:..---::+h+/os+hd/:y/-+h:.-.-:dh/-o:.``.```` ````` ```` `` ``..``.``````
+ ````...```````````` `` `./oyyoy+:---:/:-:/./+/:. .+/.:+:./++oddhyddhysso+::. ```` `` `` ```` `````
+ ```.`````````` ` `../+so+o::-`.::.---:/+: :so++oosyoo+syyo//:-/o/--` `````` ` ``````
+ ``` `````..`` ` `..:oo/` `./::-/++/: ::sooso/-+oooo+::+/.` `.``` `````
+ ``````..`...` `` `..:/ `.`//..:osso. sso+/+o/+ooo++oo: .. `.` `
+ `````..` ``` `--:/.``.//: -/://-.`.:.---.` .-: `.` `` ` ``````
+ ``````` `` `````` .``/o+/::/+` ...`. `-.` `.` ```--`..`.`.` `````````
+ ```````` ```` ```````` ``../+/+:-:. `. ` `` ` `::/-`````` ` ````````
+ ```` ` `......`.` `` ` `` `````
+ ```
+ `
+ `````
+ .+ooyhh/
+ ` +sy/
+ ` ``
+ ``
+ ````
+ ``` `
+ ```
+ ```
+ ```
+ ````
+ `````
+ ```
+ `````
+ `````` .`
+ `````` o:
+ `````` :h+
+ ``` `````-yh+
+ `` ``````.``````.``sdy-`` ``
+ `.` ```````.`````./..hh-..`````` ``
+ `.` ` ```````````````..`..```.:s--hd:-:-.`.`` `
+ ` ```````````````````............oh+:hds/++:.-.``
+ ```````` ``````````````..............----/hddohddhhy+::-.```
+ `````````````````````````.```.........:-----::ohdmmddddddho/:--.```
+ ``-/:...`````````````.`...........-//..../s+:::/ommmmmmddddddyo:::-.``` `
+ ```-sys++:.````.```.........---....-oso-.---ohsoossdmmmmmdddddddh+::--.`` ``
+ ````:hhysoo.....----..-.......----..:syso/::-:yhyyhhdmmmmmdddmddddo::-..`` ``
+ .`````.-oddyo+:----:+yyo:---------------/yyyysos:-ohhhdddmmmmmdddddddd+::---.```
+ .+o-``ohddhso----:/ohdddy/::://:::::::::/syyhyyy+-:yddddmmmmmmdmddhhh+//:::-..``
+ `./syyhdddhy--:osoohdddhs///////::::::::/+yyyhhyy+/+ddddmmmmmddmds++//+/::::-.``
+ ````.../sdddhs/:/sydhyhhy++++/////////////://ossyhdhhysohhddmmmmddmho////+//:::--.````````
+ ```..----+sy+:/syyhddhhhh+/+++++/////////////+osshdddhy+shhhmmmmdhddds+/////:::-.```` ````
+ ``` ` ```.-----.---::sdddddddddh+++++++///++/////////yyhddddyyyhhhmmmddhhhmmh+/////::-.`` ` ``` ```
+ ``` ```..-:::---:::+dmmmmmddddy++++++///++++///////yyhddddhyddhhdmmdhhyydmm+//////:-.``` ``` ```````
+ `````.----:://///hmmmddddmmdo///::::::///////::/syddhhdd+hddhhmmdyyyydmmh:------..`` ```````
+ ```````````` ```````...--:/+++++smmmmmmmmmmh+++/:/:::/++//////+o+shyyhhyohdddmmdyssshmmm+:-------.``````````` ``
+ ` `````````` ` ` ```.`...--://+oosssmmmmmmmmmmdoo+///////++//++++++++soohhyoyhhdmmdsssosmmmy/::::----.```````` `` `` `
+ ````````````` ` ```...----://+oosyhmmmmmmmmmmdoo+//+++++++++++++//++++osssoshyhmmdoooo+hmmhs+/:::--..````` ``` `` `` ` `
+ ````````````` ` ````````..----:/++ooydmmmmmmmmmmmyoo++ss+++sosyhhhhyyy+++++oooo+osmmmh+++//+yyyo:..``....`..``` ` `` `` `` `
+ ````````````` `` ` ```````..-:////+++shmmmmmmmmdmmmmdooshho++ohddddddmdy+/+///++/++/+mmys:--.``-/o+:-..``-so....```` `` `` `` `
+ ``````````` ` ` ````````..-////+o+smmmmmmmmmmmmmmmdoossyydddhyhsssy/+/:/--::///+ohmdsy/:+/::::/+/-..``.-+/-...`` ````` ```
+ ``````````` `` ````````...-///+++++:://osyyssooo/:---./oo+:---.-/+/-..--.....-:ymmh/so+/`````.:-. `.-.``` `` `` `````
+ `````````` `` `````````.-:--..`` ::`:+-.` -/. .` ``odmmy/sh/` ```.-.` `.`` ` ``````````
+ `````````` ```` `````````.....-` .s+`::`.. o/` ` `sshdhs//s-` ``....`.``` ```` ` ` `````
+ ` ````` ```````````.....---- `.+hs`--``.`` :s- `.--/o+-.....``` `---...`.` `````
+ ````````` ```````````.....`..- ``..```.-ddh-..```` `s/` ` ..```` ` `````````
+ ````````` ```````````.....``-- .:/+/-::/+mmdy+/.``` os. ```````````
+ ` ``````` ````````````.-:///-:``` `.:+sdmmddmmmdmmmdy/.````.h+. ```````````
+ ```````` ```````````..-.:+s/++.`-.---:ohmmmddsmdmdhhmmmh-````yh+./ ```````````
+ `````````` `````````````` `.:ossyo:..-.-:::+-`.//dd/oh::+h+.--:/dho+y:.``.```` ````` ``` ` ```````````
+ ``````````````` ` `.:osy+s+:--.::----`::--. .+/`/o/.:++oddhhdhyssso+::. ```` ` `` ``` ````
+ `````````````` `../+so+o:::`.::.---::/- :s+:+oooyo/+shyo/::-/o/--` ``` ` ````
+ ``` ```````` ` `..:oo:` ` `./--./++/: `::o+os+/-+oooo+::+/.` `.```
+ ``` `.`````` ` `..:/ `-.:/.`-oooo. sso++++/+ooo++oo: .. `.` `
+ `````..` ``` .--:/.```//: -+/+/:-`.:.---.` .-- `.` `` ` `
+ ``````` `` `````` .``/o+/::/+` ...`.` `-.` `.` ```--`..`...`
+ ```````` ```` ```````` ..../+/+:-:. `.`` `` ` `::/-``````
+ ```` `......`.` ```` ``
+ ``
+ `
+ ````
+
+
+
+
+
+
+
+
+
+
+ .
+ `s.`
+ `.h+..`
+ ````.hhoo`
+ `` `````.ddhy.`
+ ``````....dddd/.``
+ ``````````....-dddd/-..``
+ ```````````..`.``.hhhssmmmm+/--..`` ```
+ ` ``````````./o/---/dmmmmmmmmsyo::-.```` ``
+ ``````````````.-+--+sssso+dmmmmmmmmyhdso/-.``` `
+ `..`` `````````````````````.-+ss+-+syyyyssmmmmmmmmdhhyo+:...```` `
+ `-::+o/.`````````````.``````.....+syys:/yyyhhhydmmmmmmmy+/::::.-..````
+ `.+sysss+.....````````.`.........-+syyy+-+yhhhdhdmmmmmmms/:::::---..````
+ `.-:+syyyys+////-..````.......--...-+osyys+:+osyhhhmmmmmmms/:::/:---....`` `
+ ``-/sysyyyyyyyhhhs..........---------:/+osso+yo/oyhhmmmmmmmd+//:/:-----..`` ``
+ ` ``-shhyyhhhhhdddh----------------------:+o++dyoshyydmmmmmmmh/::::---.-.``` ``
+ ` `.oyhhhhhhhhddddd/::::::::::::::::::::-::::+dhyhdhydmmmmmmmms/:://:----.```` `
+ ```/yyo+hhhddddddddo//////////:::///::::::///smdhdmhydmmmmmmmmmo//+s/::::-..``````
+ ```````-:-..+hddddddmmmh/////////////////////////omddmmdhhmmmmmmmmmy+sds/://:--..`` ``
+ ````..-.......-+hddddmmmmmo+++++///////////////+o++ymddmmddhdmmmmmmmmdodmy/////::-.````````
+ ````..----.-:::-/ydddddmmmd+++++/++//////+//+/+sooshdhhmmddddmmmmmmdmmsmmy//////:-.```` ```` `
+ ``` ` ````...----:///://hmmddmmmms+++++++//+++/+++//+sssyhyyyhmddddmmmmmmdmmhmmh/++///:-```` ``` ` ```
+ ``` ``````..---://///+smmddmmmmho+++++++//++++o++//+ooyyoooydhhmdhmmmmmhdmmdmd//////:-.``` `` ````` ````````
+ `````````..--:///+++ymmhdmmmmh+//::::::::++/++/::://oooo+syh+dhhmmmdysodmmmmo----:-..`` ` ```` `````````
+ ```````````` ` ``````````...-:://+yhdmmmdmmmmms+/+//:///:/+ooss+/////+ooo+soy+hhhmmhssooymmmmh:---:-...`````````` `````
+ ` ``````````` ` ` ````.```..--:://+dmmmmmmmmmmdo+++///////+++osys++++/++ooosoo+syhmmhoooosmmmdmo::-:/---.```````` `` `` ```````
+ ````````````` ` ` ```..-----://++ymmmmmmmmmmmh+++++//++++++++oyyso++/++oo+oo++++hmmyo+oo+hmmddh+:-:+:---...```` ``` `` ``` ```` ` ```
+ ````````````` ` ``````...-/::://+ohmmmmmmmmmmmmmsoooy//++++++++osyhys++++oooo+++//smdy++++/oyo+o+-.`.+ds-....``` `` `` `` ``` ````
+ ````````````` `` ` ```````.--:///++oymmmmmmmmmmmmmmmhooyyoosdyysosysyhhsso++++++//+//dmys:--.``.-:/+:--.::ss+-.``````` `` ``` ``` ``
+ ``````````` ` `` ````````..-/+++ooymmmmmmmdmmmmmmmmmhhyyhhddhooso+hdys///::::///+ohmdyy/:::::::::+/-...--::-...`` ````` ````
+ ``````````` `` ````````..--://+oos+:://osyyssooo//yh+---....----:o+:-.-.::...-+dmmm+s+/.`````..--. `` `` `` `` `````
+ ```````.`` `` `````````...---..`` :dy:`` `.` .:. .. `sdmmmdoyh/` ` .-. ```` ` ```````````
+ `````````` ``````````````.....-` .ymy: ` .:- -:.` ` `hyshho++s-` `.....`..`` ```` ` ` `````
+ ` ````` ``````````......---- `-:+odms/`` `-:- `o+-` ``.-.://:.....``` `:-......` `````
+ `````````` ``````````......`..- .::+syyymms+.```-.` `+y:` ..```` ` ```````````
+ `````````` ``````````......``-- ``+ssyhdddmmdho++-.`` +y/. ````````````
+ ````````` ````````````.-:///-:``` `-::ohddmmmmmmmmmmd/-````-ds:- ````````````
+ ```````` ```````````.--.:+s/++``-.://oydmdmmmmmmmdhdmmmd:.``.hho/: ````````````
+ `````````` `````````````` `.:ossyo:..-.-:--o/.-/:syo+hdsymy--::+dyoss:.``.```` ````` ``` ` ````````````
+ ``````````````` `` `./osyos+:---:::.-:`::... .+o-+s+.:++oddhhdysssss+::. ```` ` `` ``` ````
+ `````````````` `../+so+o:::../:.---:::- :y+:+ooos+/+syyo:::-/o/--` ````` ````
+ ``` ````````` ` `..:oo/` ` `-/::-/++/: .+:o+os+/-/oooo+::+/.` `.``` ``
+ ```` `.`````` ` `.-:/ .-.//..:osso. ssoo+/+/+ooo++oo: .. `.` `
+ `````..` ``` .:://.``.//: -++++:-`./---:.` .-- `.` ```` `
+ ``````` `` `````` -..+s+////+` .--.-` `--` `.` ```--`..`...` `````
+ ```````` ```` ```````` ` .-.-/++o/::. ..`. `` ` `::/-`````` ` ``
+ ```` ```...---...` ````` ``
+ ```
+ `
+ ````
+
+
+
+
+ `
+ ```````
+ `````````
+ ``````````.``
+ ````````.``+``
+ `-/o/.```.`-y.`
+ `./syy:.-.-.+h:.
+ -+yddy+++oshdh:
+ `-odmmddhhhdmmd:`
+ ``odmmmmdddmmmd/.```
+ ````odmmmmmdmmmmd/--.``
+ `````/dmmmmmmmmmmh:::-.``
+ ```.````.hmmmmmmmmmd+:---..``
+ ````````.:-``..ommmmmmmmmy-----..`` ``
+ `` ````````-``.--:/odmmmmmmmms----...```` ``
+ `.`````.:. ` ````````````./+/ohdmmmmdmmmo:---.`````` `
+ .:::::--:-```` `````````````.``...-+yoshmmmmmdddmds:---..`..``
+ `-+o/.``:o+//-`` ```````````........-shyshmmmmmdsdmmds::::-.-..``
+ `.`...-.``.:yhhs:```` ``````````.```.......:ydhyhmmmmmd/hdmmd+::::.--..``
+ ```.`` ```.-/hdh+``````````................-yddddmmmmmdy/hmmm+::::-----.``` `
+ ```` ```-:shh:`````.........-...........-ydddmmmmdddh//hmmo:::---::--.`` ``
+ `````````.:oyho-........................-:yhhdmmdddhhho-odmh/::------..`` ``
+ `````````..oyhy+-------------------------/yhohmmdddhhyo//dmds/s:/::::--.``````
+ `` ``..`````...+hhsy:::::::::::::::::::::::::+yy+smmdmmdyyoo/ymmmshy+////::-.``````
+ ```.```...````..-/ydo+/::::::::::::////::::::///+sso+dmdmmdysoy+smmmmdd+/////:--.`
+ `````......--..--:+shd++/::::::::::::///////::////oo+++ymddddysshohmmmmmms+/////:-.` `````
+ ```````...-::::+oosydhso+/://///////::///////::::/oo+++odhhhdhhddddmmmmmmh+++++/:-.```` ```` `
+ ` ``````.-.-::--ohhhddhho+///////////:::://s+//:::/+o++/ohsyyhhmmmmmddmmmmmo++/++:-.``` ``` ```
+ ``` ``...-----omddmddho//////////////:/+oyo/:::::/oo++oyosyyymmmmdhhmmmmmy//:++:-.``` ```` ````` ````````
+ `````..---:ymmddddd/:::::::::::---:/osys/:----:os++os/ohs+dmdhsoommmmmd/--:+-..``````` `` ```````
+ ```````````` ``````````...-::/+dmmmmmmd+////////::::::::/+yy+/+///+ys+/oy/shy+dmyoooohmmmmdo:--o/-..`````.```` `` `
+ ` `````````` ` ```````...--:/odmmmmmmmmy+++++++///////////syssso++ooo+++y++osommyo+ooymmmhms+:/so:::-.....``` `` `` ```````
+ ````````````` ` ``......--://ohmmmmmmmmmmdho+++s+//++++++//syooso++++o+++os+//+mmhooo+odmmddh+/+ydo/--...```` ``` `` ``` `` `
+ ````````````` ` `````...--::/++ossdmmmmmmmmmmmddmsohd//++++so++ss++so+++++++++osoohmmdo+++/sho/oh:...sddo...```` `` `` `` `` ``
+ ````````````` ` ``````..-:://++oyddmmmmmmmmmmmmdmmmdddsosysso+shyshdyso++++++///+dmmdh/--.``.-:/y+::--//os+-``````` `` ``` ``` `
+ ``````````` ` ` ````````..--::/oohdmmmmmmmmmmmmmddmmmdyyo+oo:/oo++hs+//::::///+sdmmmhy+:::::::-:os:----:---...`` ````` ```
+ `````````` `` ````````...--::++oo+:://+syyssoo+shy:-...`.-.....-:---.-...--.ymmmmmoso-```````.:+. `` `` `` `` `````
+ `````````` `` `````````.......`` .:+yhs.` ./. ``` `..ymhdmdosh/` ..` .:- ` ` ```````````
+ `````````` ```` ``````````.....` -oyhdhs:`` `-:` `--.` `-.`yhoshsoos-``.--...`..`` ``` ` ` `````
+ ````` ```````````.....---- ``-shdddhss-/-..--` `+o/.` `:.:---::-....``` `:--.....` `````
+ ````````` ```````````.....`..- .:+shhdddhsys/s:..`` `oy/.` ` -.`````` ``````````
+ `````````` ```````````.....``-- ``:syhhddhmmdddyyy:.`` `sh/- ```````````
+ ` ``````` ```` ```````.-:///-:``` `.--:/shddmmmmmmmmmmh+/.```odo/. ````````````
+ ``````` ```````````....:+s/++``--/osyhmmmmdmdmmmysdmmmh-.``-dy:s- ```````````
+ ````````` `````````````` `.:ossyo:..--:::/yh::/-:yo:odydmh::::ods/hs:.``````` ````` ``` ` ```````````
+ ``````````````` `` ../osyos+:---//:-:o-//... .od:oso-:+ooddyhdysssss+::. ```` ` `` ``` ````
+ `````````````` `../+so+o:::.-/:.---//:- /dy+oossyo/+sys+:-.-/o/--` ````` ````
+ ``` ````````` ` ..-:oo/. ` `-+::-/++/: .+:soos+/-/oooo/::+/.` ````` ``
+ ``` `.`````` `` `.-// .:.++..:osso. ssoo+++/+ooo++oo: .. `.` `
+ `````..` ``` .:/+/.`..//: -++oo:-`./---:-` .-- `.` ```` `
+ ``````` `` `````` -..oyo+//+o` .--.-` `--` `.` ```--`..`.`.` `
+ ```````` ```` ```````` ` ----+ooo+:/- ..`. `` ` `::/-``````
+ ``` ```.---::-.-.` ..``` ``
+ ``
+ `
+ ````
+
+
+ ``
+
+ `
+ ```` .:``
+ `--`` `//-.
+ `//:-` ./s++-
+ +o+/` `.ossss.
+ `oyys-...-yyyys.
+ -syyy+//:-yyhy+`
+ :yyyo.`--`yyy:``
+ .yy: ` yy:
+ `oo` o/
+ `:s-` `` `
+ `-ho-`
+ `-hho-` ```````
+ ``:ydhs.``-///-.`` ``` ``
+ ``./sddh-```shhhs-``````.````` ``
+ `````````..+yddd+```-hddd+...```..```` `
+ ` `````````````..ohhdd+....+dmmd:.....-..````
+ ``` ``````````````````...-ohhdd/-....ydmms----.--...``
+ ``.`````````````````````````...--shdd/---o+:dmmd::::.---..``
+ ````.:```````````.....``````.`...---:ohds:::+dosmmmy:::--:--..``
+ ``````````-/-`````...............````...---::oddo/:/dddmmmms/:------.`` ``
+ ``````......+/............................----::dddo-/dmmmmmmd+:---.-..`````` ``
+ ``` ``````.:-...-s:---------------------....---::-://dddh/hdmmmmmmmo/:::----.``````
+ ```.`````...`.o+:-:/+/:::::::::::::------------:::::::ooddddymmmmmmmmmys+//:/::-.`` `
+ ``````........-.-yyso+++/::::::::::::::::::::::::::::/::/shdddhdmmmmmdmmmhoo+/////-.``
+ ```````......---:hhyys+/::/::::::::::::::::::::::::::/::/ydhdhhhmmmdhhdmmdoo+////+:-.` ` ```
+ ```````......-:ohdhso/--:////////////:::::::::::::::+::/ydyhhhhmmdhyydmms+s/////+:-.` ` ```` `
+ ``` ` `````....-.-ohddhs++/////+/++///////::::::::::::::/-:/yhyyyhhdmdyyyhmd+/y////++/-``` ``` ```
+ ``` ``....-/shddmdhyo+///+++++++//////::::::::::::::-:+yhyyyyhdmdyyyhmm+/ho::/++/-.``````` `` ```````
+ ````` `````..-shddmmmmdh+/:://:::/::::::-::/::---::--::::+yyysosydmdsssydmssdds-:://..``````` ` ```````
+ ```````````` ` ````````...-::ymmmmmmmmmds++/////+/////::::///////::::::+syss+//sdmdosyydmd/dmyo:///---....````` ``
+ ` ``````````` `` ` ```````.-:/+osmmmmmmmmmmmdy++++oo///++///////+//:::////syyss+//+dmdssyydmm+hmyy+ys+:--..``````` ` ` `` `
+ ````````````` ` `````..---/+oosyhmmmmmmmmmmmmoooosd+//++++++//+s+//::////oosso+//smmdosyyhmmddmh++/sdy-.```````` ``` ` `` ` `
+ `````````````` ` ```....-:/:/+++ohddmmmmmmmmmmmsoohsdo//++++++/+yhhyh///++oo+o++//smmmh+++o+sy/:yh-...-yd/.`````` `` `` `` ` `
+ ````````.``````` ` ````..-::--://+oyhmmmmmmmmmmmmmdydmmd++++++s++ymmmdhsso++o+/o+//ommmhy:--.....-+d:-:-.:oys:```````` `` `` ``
+ ````````..`` `` ` ``````..----://+yhhdmmmmmmmmddmmmddmmy++/+ss:/ooo+o/:::o/::/+++smmmmyy/:::::::-:yo------.::...` `` `` ```
+ ``````...`` `` ```````..--::/++oo++//++syysoosyhhsyo-.`...-``........-....-..:dmmmd++o.`..````./s` ``` ``` `` `` `````
+ ``````...`` `` ``````````..-::-..``` `:+oyyoyo. ` ` ```` ```.-hdsdy//s- -.`.` `-/. ` `` ` ``````````
+ `````````` ``````````.`......-:. :ssyyyyyoo-` ` `:--.` `.--hyohsso/-`.:.....`..`` ``` ` `````
+ `````````` ````````.....-..--:- `/yyyyhhhhysy+.` -oo:. `.//::-/:-.`..``` `:---.`..` `````
+ `````````` `````````....-....-- `.+hhhhsydddhsyy/.`` :yo-` ` -...```` ``````````
+ `````````` `````````.......`.:- .-:+yhhhh+odmmmdhdo-``` :hs-` ```````````
+ ````````` ```````````..-:+++-:`-.``.-/ossydddmdddmddmmmhy/.``-dy:/` ````````````
+ `````````` ``.`````````.---:os+o+../+sdmmmmmdhddhhddyymmmmh:.``sd+:y/` ````````````
+ ``````````` ````````````````.-/sysyo:..:-:///yy-:/--+o:ydydmd+::/yd+/dy/.``````` ````` ``` ` ```````````
+ `````...``````````` `` `.-/oyyoyo:::-++/-/+-//..` .oy:oyo-:+ooddyddhsssss+::. ``` ` `` ``` ````
+ ```..````````` ` `--+oysos///-:+/---:/:/- /hs+oossyy+osso/--../o/--` ````` ````
+ ``` `````..`` `` .--/ss/. ` `:+/:-/++/: .::soos+/-+oooo/::+/.` ````` `
+ ``````..`...` `` .--/+ .:.++..:osoo. ssooo++/+ooo++oo: .. `.` `
+ ` ````````..` ``` .:/+/.`..//: -++oo/-`./---:-` .-- `.` `` ` `
+ ``````` ``` `````` -..oyo+//+o` .--.-` `--. `.` ```--`..`.`.`
+ ```````` ```` ```.`.`` ` ----+ooo+//- `..`. `` ` `::/-``````
+ ```` ` ```.---::-.-.` ..``` ``
+ ```
+ ` ``
+ `````
+
+
+
+
+
+
+
+
+
+
+ `
+ ```:-` `
+ ```` `ohyd:``
+ `````` `` ``ymmd.``
+ ```````````.``.hmmy.``````
+ ````````````:/:-hmms.``````` `
+ `````````````.syydmmd:..``````` `` `
+ ``````..`..`.--hddmmmh:...``````` ```
+ ````` ```......+-..-+/hdmmmdy-.....```` ````
+ ` ``````````....---y/---+/:ommmmd/.....``` ``
+ ```````````````...-----:hh:--:y+/mmmmm+::--..`` ``
+ ````````````......------/hms:::hy+mmmmms//-/-..``` ``
+ ````````````````````````.......----:ohmho:/sdsmmmmmy//://-..``` ``
+ `````````````````````.`...............---:::ohmdyoodmdmmmmmh//:::---..``` ```
+ ```````````````````.........--.........--::::+hddhyhmmmmmmmmh//:::----..```` ````
+ ````````..................................--::::ohhdhyhmmmmmmmmo:::::--......`` ```
+ ``````````-/-........----------------------------:::::yhyhdhdmmmmmmmmo++////:----.````` ```
+ ````..`````.+so+::------::::::::::::::::::::::::::://:::hhhhdhhmmmmmdmmoooo++///:::.````` ````
+ ``````.````..+yhy/:---::::::::/:::::::::::::::::://///:::hdyyhhhdmmmmdmmoo++++//+++/.` ``` ` ``````
+ ````....``..--/yddhs+:::/:///////////////:/:::::://////::/hdyyhhhhmmmmdmmddho++/+ooo/-` ```````` `````` `
+ ```````.`.-oyyhdmmdds/:--//////////////////::////////+::/ydhyyhhhdmmmdmmddmh++++o++/-``````````` `````` ```
+ ``` ` `````..-ohdhdmmmmmyo///++++++++//////////:////////+-:/shhysyhhdmmmdmmdhmmo+++o+/:-.``````````` ``````` ````````
+ ``` ``..--+dddhdmmmmmds++++++++++++++//////:////:///y/:/oooo+oyhmmmmddmdommy+ooo/::---....`` `` ``````````` `````````
+ ``` ```...-/ymmddmmmmmmdo+++/:::::::::::::/:::-----:/hso:::::::/ymmddddmm/smd+//+/::--...``` ```````` `````````
+ ````````````` ```````..--:+oshdhdmmmmmmdyo+o+//+//:///://+///:::://+yhs////////dmmhdddmms/dmo+///:::-...``````` ``````````
+ ````````````` ` ` ````..-:::++oshhdmmmmmmmmhssyoos+///++/++/////////++sdho++++++ommmyhhhhmd/dmyso///:-........`` ```` ` ``````````````
+ `````````````` ` ``````.---/::/++ossosmmmmmmmmmhsddddo//++++++//++++///++shhy+++++ommmdosyyyhdodmho+/:::.````````` ``` ``````````````` ````````
+ `````````````` ` ``...`.:-.-///++ossysdmmmmmmmmmmdmmm+//++++s+/+yddms///+dhhho++++hmmdho+++++s/ods:-.`.--.``````` `` `````` `````` ```````
+ ````````..`````` ` ```..-::---://+ooosydmmmmmmmmmmmmmmdo/+oyhhy+ohmmmmsso+sdhhho//+smmmhy:--....-:sh---..-os+.````````` `````` ```` `````
+ ````````.``` `` `` `````..----::/++osshmmmmmmmmmmmmmmddmdhyyhho:/+///o+//oo++oso+++hmmmyy/:://::::/y+-......::-..`` `````` `````` `` ```
+ ``````...`` `` ```````...--:/++oo+/:/++osyssosyydhs+-......``....:::/:-......-/dddmo++.`--.`..-/s. `.` ````````````````
+ ``````...`` `` ````````...:/:-..`` `.+/+hyoo-` ---. ``.dhohh+/s. .-``....:-` ``.` `````````````````
+ `````````` ````````````....---:. `./s:odhssy+. /o:. ```hy++hyso/-``--....`..`` `... ``````````````````
+ `` ``````` ````````.....----::- `.:+so.odhhoyy+. `ss:` ``.:---::-....``` `:--..``.` ````````````
+ `````````` ````````.....--...-- `/+oyy+-+ddhyyho-` -hs-` -...```` `````````````
+ `````````` `````````.......`.:- ``./syyyys//dmmdhmh/-```.dy-. ``.``````````
+ ```````.` ``````````...-:+++-/.:...-/++shdddmmdmmmmmmmmmy/..`od/-+- `````````````
+ `````````` ``.`````````.---:os+oo:ohhhdmmmmmddmmyoydhshmmmh/-..sd/:hs` ``````.``````
+ ```````.``` ``````````````` .-/syyho:-.:--:::so.-/--/+-/dydmmdo//sd+/hy:.``````` ````` ``` ` `````````````
+ `````...``````````` `` `.-/oyyoyo/::-++/-/+.//.`` .oy:oys/+oosddhddyssssso::. ``` ` `` ```` `````
+ ```..````````` ` `--+oyooo//:--//---:/:/- /ho/osssyy+oss+:-.../o/--` ````` ` ``````
+ ``` `````..`` ` .--/ss/. ` `-+/:-/+o/: `::sooyo/-+oooo+::+/.` ````` `````
+ `````...`.``` `` .--/+ .-.++..:osoo. ssooooo/+ooo++oo: .. `.` `
+ ````````..` ``` .:///.`..//: -++oo/-`-/---:-` .-- `.` `` ` `````
+ ``````` ``` `````` -..+so+//+o` .--.-` `--. `.` ```--`..`.`.` ````````
+ ```````` ```` ```.`.`` ` .---+ooo/:/- `..`. ``` ` `::/-`````` ` `````````
+ ```` ` ```.------... ..``` `` ``````
+ ```
+ ` ``
+ `````
+
+
+ ``
+ `/-````
+ ````.ss+.````
+ ````/hdhs-```
+ ```.ymmmdh-``
+ ```/dmmmmh.`` ```
+ ````ommmmmo``` ```` `
+ ```.ymmmmd:``
+ `````.ymmmmy.````````` ``
+ ``````.ymmmmo.``````````` ``
+ `````````````ymmmmh.`````` ``` `
+ ````````.```````ommmmd-`````` `` `
+ `````.``.-````..:dmmmm:`````` ``
+ ``````..`.s...../sdmmmm:..```` `` `
+ ```````..-sd/:::+hdmmmmm/..```````` ``
+ ```````````...-sdmhsssydmdmmmm:...````` `.``
+ ` ``````````....:hmmdhhhhmmshmmm/......````` `````` `
+ ` `````````....--:ydmmddddmmoommm/---.-.``` ` ``` `
+ `````````````.....----:ydmmddmmmmoommd/:::-:-..```` ` ` `` `
+ ````````````......----::hmmmmmmmmmddmmd+///:/:--.````` ` ```` `
+ `` ```````````````````...`.......--:::hmmdddmmmmmmmmho+++:/::--...````` ````` `
+ `..``` ```````````````.`..............---::/ymmdhdmmmmmmmmdooo+///::---...``` ``````
+ .::...`````````````........-----......--:://smmdyhmmmmmmmmmyyho+o+/::---:.`` `````` `
+ ```-o+///-.....................-------------:::ommhsymmmmddmmmhyms+++/----::.`` ``.``` ``
+ ``` `.:-:o+++o/......-------------------:-::::::////+mmysydmmmddmmmmhmh++//////+:.````` `````` ``
+ ````````:+//++oyo...-----::::::::::::::::::::::////+///dmyshhmmmmmmmmmdmmo++++ooo+-``````` `````````````
+ ``````````/ssssssyy/----::::::::::::::::://////////+++///hmhshhhdmmmmmmmmmmyoo++ooo+-.` `````` ````````````` ``
+ `````` ```:ooossooys:--:-:::::::://///////////////++/////oddsyhhdmmmmmmmmdmhsoooo++/:.`````````` ````````` ``` ` ```
+ ``` ```.-..:+:-/s+:/+/://///////////////////////+osshoooyosyhhdmmmmdmmhmdyssso+//-.``````.````` ``` ````````` ``` ```````````
+ `` ` ````.-.-/+oydhhhdmd+////////////////////////++odddsoooooshhmmmmmdmmhmmdysso++/-.`..```..```` ` ````````````` ```````````
+ ``` ````..---/hdmmmmmmmms////////////////////////++odddhso+oooydmmmmmmdmdmmmhsssoo+/:--...`` `` ````````````` ```````````
+ ```.`....-:+dmmmmmmmmh//::::::::::::::/::::--::/+yhdhs/:/+osmmmmmmmddmmmmdo++++/-...```` ```````````` ```````````
+ ```````````` ``````--.-----/odmmmmmmmmd//////++////////+////////+osyhhys+/sydmmmmdddhdmmmmhho////-.........``` ````````````` ```````````` ````
+ ````````````` ` ` `````.---::::/odmmmmmmmmd++++ohys//+s++++///+o++++++osyhhs+oshmmmmhhyhyhmmmmyyy/:/:---.......` ``````````` ````````````````````` ``
+ ````````````` ` ` ``.....-::://+ohmmmmmmmmd+++hdmmy/+ydo+++//+oyyhs++ossyhho+oodmmmdosssyymmmmho+/:::......```` `..` ````` `````````````````````````
+ `````````````` ` ``````.....-::/+++osmmmmmmmmh+++dmddyydmmdo+++osyhdms+osyshdsooosmmmdho+++ooyyyhh:-..---.....```` ``` ```````` `````````````````
+ ```````````````` `` ````...-..--::/+ooosmmmmmmmh+++sdmmmmmmmmdhhyhdmddmdhoossssyy+++ommmyy/--...-/o+s+---.-oyo-.```````` `````.` ````````````````
+ ```````````` `` `` ````......--://+ooohmmmmmmmhosydmmddmddyyhhy//++/+dhyys/:::/+o+ohmmmyy+:://///+:/o--.....:/-..`` ```` `````.`` ````````````````
+ ``````````` `` ````````..--://++o++:://osyssyysdy///::.....``..-/+o/:--......-+dmmdos/.``.-..:-.-- ` `.. `````.```````````````````
+ ``````...`` `` `` ```...-:/:...`` `.o::do..-:-. -s/:.` `.-dyydh+o/. `-..-...-` ` `..` `````.```...```````````
+ `````````` `````````````..----:. `-+y:/dy:.-::. -yo:. `.-sh:+yysoo-` `-::-.....` `... ``````````````````````````
+ ` ``````` ``````````......---- `-+oys//dhs--//. -hs-. ``.-:-.::-....```` `:--..``.` `.`` ``````````````````
+ `````````` ``````````......`..- `/ssyhs+:hdhs/oo/.` `hh-`. -...`` ` ``....``````````
+ `````````` ```````````.....``-- `-/oyhhhys+odddhhhy/-```-do.:- ``......``````
+ ````````` ````````````.-:///-/-:--::/+ooshmmmmmmmmhyhdmms/://+d+-y+ `.......`````
+ ````````` ```````````..-.:os+oyyyyssdmmmmmmmmmyoshoomhsmdmy-.+d/+h: `.......`````
+ ``````````` `````````````` `-/syyyo:..:-::::yy-:/:-y/-/msommy+++sd+oho-.``````` ````` ``` ` `...``....````
+ `````.`````````` ` `` `.-/oyyoyo:::-///-/o-//.`` .+s-+ys:+ossmdhddyssssyo/:. ``` ` `` ``.` `..```
+ `````````````` ` `--+oyooo//:--//----::/- :ys/osssys+ooo+:-.../o/--` ````` `` ```.```
+ ``` ````````` ` ..-/ss/. ` `-+/:-/+o// ::sooyo/-+sooo+::+/.` `..`` `` ```````
+ ```` `..````` `` `--// .:.++..:osoo. ssooooo+oooo++oo: .. `.` ` ` ````````
+ ``` `.. ``` .:://.`..//: -++oo:-`-/---:-. .-- `.` `` ` ````````
+ ``````` `` `````` -..+so///+o` .--.-` `--. `.` ```--`..`.`.` ``````````
+ ```````` ```` ```````` ` .-.-+o+o/:/. ..`. ``` ` `::/-`````` ` ``````````
+ ```` ` ```..-----..` ````` `` `````````
+ `` ````
+ `
+ ```
+ -ydh/`
+ -hmdo.
+ ``+mmms:`
+ `-hmmdyo:`
+ ```+mmmhyyo`
+ ```ymmy/oy-
+ `.hmd.`..
+ `.` ``ymd.`
+ -//.` `+dm+` `
+ -ss+.` `.hmy-
+ ` .yhho-.``:dh+` ``
+ `-``yddhs/-:.+ho` ``
+ ``:s.`ydmdhyss:+// `
+ ``.yh:.ydmmdhhhyo`` `
+ ````.hds:ydmmddddho`````
+ ````.hmh/sdmmddddds``````
+ ``````.ydy-:ymmdhhmmd:.````````` ``
+ ```````````.://--smmdysmmmd+...````` `.``
+ ``````````...-----smmmysmmmmy:-..`..``` `````
+ ` ``````````....----/:smmmdsmmmmd+::-.-..```` ``` `
+ ` ``````````......----::+:+mmmmhmmmmmyo++::--.````` ` ` ``
+ ````````````......----:::://dmmmdmmmmmdyoo:/::-..``````` ````
+ `````````````.......---:::://ymmmmdmmmmdhyo+//:--.....``` ````
+ ` ````````````..............---:::///+sdmmmddmmmmhyoo+/::-----.` ` ````
+ `````````````..``..............--:::////+sdmmmmmmmmmho+++/////:--.` `````
+ ````````````````.................-----::::////odmmmmmmmmmmo///:::/+/..`` `````` `
+ ```````````...........----------------::////+o+/+yddmmmmmmmmmmo++//+++/-.````` `````` `
+ ``````-..``.--:---------:::-:::::::::::/+++++oy+++shdmmmmmmmmmmmyoo+oo+/-.``````` `````` ```
+ ```````o/-...oo/--------:::::::::::::///+syyssys+++odddmmmmmmmmmmmhooss+/:-.` `````` ``````` `` `
+ ```..`.yyo/:/dh:----::::::::::::::::////+syysydsoo+sdhdmmmmmmmmmmmmsoss+/:-.````.````` `````` `` ``
+ ```.:--yhysoods-::::::::::/::::::::://///oyhyhdhsoohdddmmmmmmmmmmmmhooso+:-.`.````.````` ``````` `` ``` ````
+ ``````.:/o++:-:so/::::::://////:::::://////+oyyhdhs+ohmmmmmmmmmdmmmmmdoosso/-.`.````..``` ```````` ``` ``````````
+ ` ``````````-+/::::/sds:::::::://+s+/:::::/+//////sshdy++oymmmmmmmmmddmmmmmooooo/:-...```` `` ````````````` ```````````
+ ````......:hsy+/::ymy::----::::+hs:::/:::soo/:::+shdh/:/ydmmmmmdddhhmmmmm/:::::..````` ````````` ```````````
+ `` ```` ````..-----/yddhyydmh:/o++:/:::sdh+//////yyys///+oddho//ommmmdddhhyhmmmmd//::::-.....``````` ``` ` ```````````
+ ````````` ` ``````.-----:/sdmhoshds/odhdho/:+hmmy+////+hyhho+++oddhy++smmmmdhdhhydmddmmo//::--.-.......` ```` ` ````````````````````` `
+ ` `````````` ` `````..-:://///odmddho////hhhmmsshmmmdo////+ysdmhsoosdddyooymmmmhsyhyshmmddds//::-..`..````` `.. ````````````````````````
+ ` `````````` ` ````.....-/+///sdmmmdysso//hysmmmmmmmmmho///oyhmmmhysydddhysymmmds+++++ohssso/-..-++....````` ``` `````` `````````````````
+ ` `````````` ` ```...----///+odmmmmmddhddyyyymmmmmmmddhs+++hdmmmhosyyyyssyyymmmho:--...-:o+//-::--/oo-````````` `````` ````````````````
+ ``````````` ` ` ```````....--::/+osmmmmmmmmmmmmmmmmdhdhyyyys////+syyys+/::://+oshmmmhy/:::////++::-.--..`:/-..`` ```` ``````` ```````` ``````
+ `````````` ` ``````....-::///+//--:/+syhysoyy/:----.....``..+y////:-......-+dhmmyh:.```.--::... `` .. ````````````````` `
+ `````````` ` `````.::-.``` `+so-.++` :yo.````` `+ho+hdyyo. .::-...` ` ..` ```````````````````
+ ````````` `` ``````````...` .oys--+/` `hh-``` ` .+oh:+ys/+y:` `..--.....` `... ```````````````````
+ ```` `````````````....... :yhy/:o/.`` `sdo..-` .::--.:.::-....```` `---.```` ```` ````````````
+ ```` ````````````...``... :hhh+::+-.-.```..`...dh//+. -.```` ` `````````````
+ ``` ``` ```````....`.:- ``-ddhs/:/ssyyyyysos++/dsos- ``..`````````
+ ``` ```` ```````.-:///s::..`.--:--:dmmdddmmmmmdmmmmho:-doy+` ``..`````````
+ ``` ```` ````````-+s+oysssoohhhdmmmmmdsdmdyhmddmmy-../d:y: ``.....``````
+ `````` ````` ` `./oysyo:..:-:///yy-:/-/d/:smyoho-::/sd:oy/-`````.`` ````` ``` ` `````````````
+ ````````````` ../osyoyo::--/+/:/s-//... `/s:/+/./+osddhddyssssys/:. ```` ` `` ```` `````
+ ```````````` `../+sooo:::.-//---::::- -+o:+sosyy++oo+:-.../o/--` ````` ` ``````
+ ``` ``````` ..-:oo/. ` `-+:--:/+// --o+oyo/-+oooo+::+/.` `..`` `````
+ ``` ```````` ` `.-// .-./+.`-+oo+. sso+ooo+oooo++oo: .. `.` `
+ `` ``` ``` .-://.```//: -+/++:-`.:---:.` .-- `.` `` `````
+ ```` ```` ...+s+////+` .-... `-.` `.` ```--`..`...` ``````````
+ ``````` `` ```````` ...-/++o:-:. `.`` ``` ` `::/-`````` ` ````````
+ ```...---...` ```` `` ````
+ ` `
+
+
+
+
+
+
+
+
+
+ `
+ :.
+ ` `+-
+ `:` `.s/`
+ `o: ``.-y+
+ so`./:/ho
+ oh-`s/-hy`
+ /ds/:/.hd:`
+ -yhy-:.dds.`
+ `/yh/-.dds--.
+ ` `+hs:.hds:+:```` ``
+ ```````-yys-:ho+y/.``.`` `
+ ```````````-syy:./yoy/.....```
+ ``````````````...-+os:.-dhh/::.-.``` `
+ ` ```````````````.......-//----smd+//-:--.``````
+ ` ``````````````..........--:----:+mmy/+-::/-.`````
+ `````````````````.//:-..------://:::+hmmo/::///-..``
+ ```````````.````````-oso/--------+yo:::/ommd/-/++/:-.`
+ ````````````````````...`````.:syyo:--/--:ohmh/:::/dmms-o:/+:-`` ``
+ `````````.....................:syys+:-/ooohdmmhs/+hmmmmos/:/+:.```
+ `` ``````.........----.-----------:+yssso::yyyhdmmmdymmmmmmms+//+/-.``
+ `` `````.......--..------------:----:/s+oos+/+hdhdmmmmmmmmmmmmo/+/+/:-.`
+ ```..``.....-.-----------------//:::::/+/:/++/ydddmmmmdmmmmmmms+++//:-.`` ` `````
+ ``.--....``.----------:::------/o+//::/+/--://oddhdmmhymmmmddmh+o+//:-.``` `````
+ ``` ``-//----..--------:::/://::---:+yo+::/+s/:://+hddmddyymmmmmhmdo++//::-.``` ```
+ ````````-o+:::------::::::::::yso::---+sy+/:/ohy/::/oydmmddssmdmmmdmmho//::::-``` `` `
+ ``...```-y/:/:-.--:+----------hdy-----/+ho/:+ohds://+ymmmhdyodddmmdmmdo:-....``` ` `
+ ```.......-hho+:::/:ods:--:----:dmo-::::/+ys+/osdddyyssmmmmdddhdhhmmmmmdy+-.--..`````````` ``
+ `````...---.--hmhsyhhddmmm+//::/+oymd+::::/+oyy+ssydmmddhhmmmmmdddhyydmmdmdys/---......```` ` `
+ ``` `````...-::--:/smmhdmdmmmmmd+y/hmmmmmy+/:::+ohdh+yyyhdddhhymmmmmysyysosmmmdhso+--:.````` `` ` ` `
+ ``````` `````...--:///+dommmdmmmmmmmmyshmmmmmho+////oommhhyosyhyyyhyhmmmms+++//+osyyo+-.`.:h-``` ` ` ``
+ ``````` ` ```....--::/+oodmdmmmmmmdmmmmdhmmmddhyo+//+ssymmdy+/yhysooosdmmmmy---.``./+s+/------/s:` ` `` `` `
+ ````` ` `````..--::/+oohmdmmdmmmmdmmmmhhdhso+so/:/syyssyhoos::://++symdmmd:::::::/+++:-....``-:-``` `` `` ```
+ ` ````` ` ``````.-:/:///::..-::yddso+/+/-...```.`.:::oo--/++//-.....-/hyhmhd/.``` ./:/-. `` .` `` `` ````
+ ```````` ``.--..``` :hh:.` -o/.`+-``````````` `-y+/yh+yo- `:-:-.` ``` ` ``````````
+ `` ` ` ```````````.` -hh+.` :ys:``/:--.` ..`.:yo-/yo-+y:. ``....````` `..` ` ````
+ ` `` `````````..:: .hho.` .ohho. .ss+- `./+/-...--.....``` `--.````` ` ````
+ ` `` ``````````/:- -dds.` -+/oyddy:`.yhs- ..``` ````````
+ `` ` ``````````.:- `:dds:-.-:/yhdmmmms-.ydy- ```````````
+ `` `` ````..:::.-`-````.....:mmdddmmmmddmmmmd/.-mo/` ````````` `
+ `` `` ``````./o/+/``-:/+sydmmmdhdmmmdyydmmmdh-.-m:.. ```````` `
+ ```` `` `.:ossy+-..--:+++hd:::-+ho:smy/hs::::oh:-s+-``````.` ````` ``` ` ```````````
+ `````` ../osy+s+----/++/+y:/+... .+h//+/./+o+hdhddyssssso/:. ```` ` `` ``` ````
+ ```` ` `../+so+o:::..::---::-:- -yo:+sosys/oooo:-.../o/--` ````` ````
+ `` ..-:oo/` ` `-/:-.://:: `--o+oy+/-/oooo+-:+/.` ``..`` ``
+ `` ` `` ` `.-// .-./+.`-+oo+` oso+ooo/+ooo++oo: .. `.`
+ ``` ``` .-://.```//: -//++:-`.:---:.` .-- `.` ```` `
+ ``` ...+s+////+` .-... `-.` `.` ``.--`..`...`
+ `` `````` ...-/++o:-:. `.`` ``` ` `::/-``````
+ ```...---...` ```` ``
+
+
+
+
+
+
+ `
+ .
+ .
+ .
+
+
+
+
+
+
+
+
+
+
+ ` ```````` ` ``
+ ````.`` `````-```````` `
+ ````````````-s.````````...o-.```..```
+ ` ``` ``````````````.-hds+-..``.....ss:/:.--..``
+ ``````````````.``...../dmdds-.....---+ddh+-::--.```
+ ```````````````.........smmmm+-------::hmds-:::--.``
+ ``````````````.......````......--:ydmmdy+:::://+dmmy::::-/:.`
+ ```````````.....................----/ydmmmhs+/:/yhmmmy:::::/:-` ``
+ ```````````.......................--------/ydmhhhho/:ymmmmd:::--::-.` ``
+ ``````````.......----------------------:::-----/hmhyyys+/smmmmmy+/:-::--`` `
+ ````` `````..----------:::::::::::-:::::///:--:::ymyo++++ohmmmmmmms/::::-.`
+ `` ```` ```...-//--:::::::::::::::::::////+o+:--///hdy+++++ohmmmmmmmmo//:::-` ``` `
+ `` `````...-.-/hs:::::::://::::::::::/+//+os::/+ohddhyy++++dmmmmmmmmy////:-.` ```````
+ `` ``...--.-:/ym+/://///////////::://++/+oy:/ddmmmdmmmho+hmmmmmmmmmh/////:.````````` `
+ `````````..-::::shodm+///////++//////////////oy//dmmmmmmmmdyymmmddmmmmmd++///:-```````` ```` ```
+ ` ```..`````.--//:/dmdymh+++ooossys++o//////:::/+hh+hmmdmmmmmmmmmmdhhmmdmmmo+++/:.``````` `` ````````` ````````
+ ``....```...--::+ymmmmmmyhymmddhhhys//:::-----::sdhhmmddmmmmmmmddhhymmymmmo--::.````` ```` ````````
+ `` ````` ```````......----:/hmmmmmmmmmdmmmmmdds/////:::::://+hdddmmmmmmmmmddddhymmhdmdy:-:-..`````````` ``````
+ ```````` `````...---:--/+:::/dmmmmmmmmmmmmmmmmh+///////++//+ooshhhhddddmmmdhhhhhshmmdmhy+:::-......```` `` ``````````
+ ` ````````` ` ```````..--:/+o/oys:/yddmmmmmmmmmmmmdhho+//////+o+//osyyyhhhhhhhmmmdyyyhysommmhy+/:-:-`````` ``` `` ``` ``` ` ``
+ ` `````````` ` ````.....--:+oooymmsdmdhhmmmmmmmmmmdyyyy+++//ossso/oyydyhddhdyydmmmdoo++/++oos+/:-..-y+```` ` `` ``` ``` ``
+ ` ````````` ` ``````...--://osshmmmmmmdydmmmmmdmmmdyyssoooshdddddhs+ohysyyoooymdmmd:--.``.-/+:::/:-../s/-` `````` ``` `
+ ` ```````` ` ` ````````..://+++osydmmmmmdddmmmmmyhmdhyooohdhyss+sy+/++o+::/+++ohddmmd/::::::://:----...`-:.``` `````` ```
+ `````````` ` ````````.::///++/++:://oddhysooo/::--...ydy+/:-::+o/:-.......-/hydmyh+.``` `:-.` `` `.` `````` ``````
+ `````````` ` ```...-/...``` `hh/ -dh/::::/:-` ``:s:odh+sy- `:..`` ```.` ``````````````
+ ````````` `` `````````.../+ hd/ `` .hmy:+ssso-` `-:oo/-oyo-/h:. ``....`..`` ``` ` `` ``````
+ ````` ``` ```````...`.-/o `hd: `/+:+ydds/yhhs: .--..``.--.....```` --.````` ` ````````
+ ```` ```` ```````...```.- .hdo-`` ``.+yhddmdyoddo:` ..``` ```````````
+ ` ``` ``` ```````....``-. .hdhyo+:-//+hmmmmmhsdy:` ````````````
+ ` ```` ```` ``````..-///.:`` `...ydddddddmhddmmmmdsohy:` ````````````
+ ` ```` ```` ` `````...-+o/+/``.``.-+ydmhoymmmmdodmysmmm::oys-`.. ````````````
+ `````` ````` `` ` `.:ossy+-.---/+/+hh:::--ss:dd/:yh//:::yy-os:.`````.` ````` ``` `````````````
+ ````````````` `./osy+s+----/++:+y://.`` .oh-/+/./+++sdhhdhsssyys/:. ```` ` `` ```` `````
+ ``````````` `../+so+o:::..::---::-:- -hs:+ssyho/osso:-.../o/--` ````` ``````
+ ``` ``````` `.-:oo/` ` `-/:-.:/+/: `::o+oyo/-+oooo/::+/.` ``..`` ````
+ `` ```````` `.-// .-./+.`-+oo+` oso+ooo+oooo++oo: .. `.`
+ ` ``` ``` .-://.```//: -//++:-`.:---:.` .-- `.` `` ````
+ ``` ````` ...+s+////+` .-... `-.` `.` ```--`..`...` ```````
+ ``````` `` `````` ` ...-/+++:-:. `.`` ``` ` `::/-`````` ` `````
+ ```...---.`.` ```` ``
+ `
+
+
diff --git a/p5js/index.html b/p5js/index.html
new file mode 100644
index 0000000..d436aa2
--- /dev/null
+++ b/p5js/index.html
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/p5js/p5.js b/p5js/p5.js
new file mode 100644
index 0000000..432eba7
--- /dev/null
+++ b/p5js/p5.js
@@ -0,0 +1,32625 @@
+/*! p5.js v0.5.7 February 08, 2017 */
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0, 'No ' + attrName + ' specified.');
+ }
+
+ // Identification information
+ assertStringAttribute('familyName');
+ assertStringAttribute('weightName');
+ assertStringAttribute('manufacturer');
+ assertStringAttribute('copyright');
+ assertStringAttribute('version');
+
+ // Dimension information
+ assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
+};
+
+// Convert the font object to a SFNT data structure.
+// This structure contains all the necessary tables and metadata to create a binary OTF file.
+Font.prototype.toTables = function() {
+ return sfnt.fontToTable(this);
+};
+
+Font.prototype.toBuffer = function() {
+ var sfntTable = this.toTables();
+ var bytes = sfntTable.encode();
+ var buffer = new ArrayBuffer(bytes.length);
+ var intArray = new Uint8Array(buffer);
+ for (var i = 0; i < bytes.length; i++) {
+ intArray[i] = bytes[i];
+ }
+
+ return buffer;
+};
+
+// Initiate a download of the OpenType font.
+Font.prototype.download = function() {
+ var fileName = this.familyName.replace(/\s/g, '') + '-' + this.styleName + '.otf';
+ var buffer = this.toBuffer();
+
+ window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
+ window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
+ fs.root.getFile(fileName, {create: true}, function(fileEntry) {
+ fileEntry.createWriter(function(writer) {
+ var dataView = new DataView(buffer);
+ var blob = new Blob([dataView], {type: 'font/opentype'});
+ writer.write(blob);
+
+ writer.addEventListener('writeend', function() {
+ // Navigating to the file will download it.
+ location.href = fileEntry.toURL();
+ }, false);
+ });
+ });
+ },
+
+ function(err) {
+ throw err;
+ });
+};
+
+exports.Font = Font;
+
+},{"./encoding":4,"./glyphset":7,"./path":10,"./tables/sfnt":25}],6:[function(_dereq_,module,exports){
+// The Glyph object
+
+'use strict';
+
+var check = _dereq_('./check');
+var draw = _dereq_('./draw');
+var path = _dereq_('./path');
+
+function getPathDefinition(glyph, path) {
+ var _path = path || { commands: [] };
+ return {
+ configurable: true,
+
+ get: function() {
+ if (typeof _path === 'function') {
+ _path = _path();
+ }
+
+ return _path;
+ },
+
+ set: function(p) {
+ _path = p;
+ }
+ };
+}
+
+// A Glyph is an individual mark that often corresponds to a character.
+// Some glyphs, such as ligatures, are a combination of many characters.
+// Glyphs are the basic building blocks of a font.
+//
+// The `Glyph` class contains utility methods for drawing the path and its points.
+function Glyph(options) {
+ // By putting all the code on a prototype function (which is only declared once)
+ // we reduce the memory requirements for larger fonts by some 2%
+ this.bindConstructorValues(options);
+}
+
+Glyph.prototype.bindConstructorValues = function(options) {
+ this.index = options.index || 0;
+
+ // These three values cannnot be deferred for memory optimization:
+ this.name = options.name || null;
+ this.unicode = options.unicode || undefined;
+ this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];
+
+ // But by binding these values only when necessary, we reduce can
+ // the memory requirements by almost 3% for larger fonts.
+ if (options.xMin) {
+ this.xMin = options.xMin;
+ }
+
+ if (options.yMin) {
+ this.yMin = options.yMin;
+ }
+
+ if (options.xMax) {
+ this.xMax = options.xMax;
+ }
+
+ if (options.yMax) {
+ this.yMax = options.yMax;
+ }
+
+ if (options.advanceWidth) {
+ this.advanceWidth = options.advanceWidth;
+ }
+
+ // The path for a glyph is the most memory intensive, and is bound as a value
+ // with a getter/setter to ensure we actually do path parsing only once the
+ // path is actually needed by anything.
+ Object.defineProperty(this, 'path', getPathDefinition(this, options.path));
+};
+
+Glyph.prototype.addUnicode = function(unicode) {
+ if (this.unicodes.length === 0) {
+ this.unicode = unicode;
+ }
+
+ this.unicodes.push(unicode);
+};
+
+// Convert the glyph to a Path we can draw on a drawing context.
+//
+// x - Horizontal position of the glyph. (default: 0)
+// y - Vertical position of the *baseline* of the glyph. (default: 0)
+// fontSize - Font size, in pixels (default: 72).
+Glyph.prototype.getPath = function(x, y, fontSize) {
+ x = x !== undefined ? x : 0;
+ y = y !== undefined ? y : 0;
+ fontSize = fontSize !== undefined ? fontSize : 72;
+ var scale = 1 / this.path.unitsPerEm * fontSize;
+ var p = new path.Path();
+ var commands = this.path.commands;
+ for (var i = 0; i < commands.length; i += 1) {
+ var cmd = commands[i];
+ if (cmd.type === 'M') {
+ p.moveTo(x + (cmd.x * scale), y + (-cmd.y * scale));
+ } else if (cmd.type === 'L') {
+ p.lineTo(x + (cmd.x * scale), y + (-cmd.y * scale));
+ } else if (cmd.type === 'Q') {
+ p.quadraticCurveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
+ x + (cmd.x * scale), y + (-cmd.y * scale));
+ } else if (cmd.type === 'C') {
+ p.curveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
+ x + (cmd.x2 * scale), y + (-cmd.y2 * scale),
+ x + (cmd.x * scale), y + (-cmd.y * scale));
+ } else if (cmd.type === 'Z') {
+ p.closePath();
+ }
+ }
+
+ return p;
+};
+
+// Split the glyph into contours.
+// This function is here for backwards compatibility, and to
+// provide raw access to the TrueType glyph outlines.
+Glyph.prototype.getContours = function() {
+ if (this.points === undefined) {
+ return [];
+ }
+
+ var contours = [];
+ var currentContour = [];
+ for (var i = 0; i < this.points.length; i += 1) {
+ var pt = this.points[i];
+ currentContour.push(pt);
+ if (pt.lastPointOfContour) {
+ contours.push(currentContour);
+ currentContour = [];
+ }
+ }
+
+ check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
+ return contours;
+};
+
+// Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
+Glyph.prototype.getMetrics = function() {
+ var commands = this.path.commands;
+ var xCoords = [];
+ var yCoords = [];
+ for (var i = 0; i < commands.length; i += 1) {
+ var cmd = commands[i];
+ if (cmd.type !== 'Z') {
+ xCoords.push(cmd.x);
+ yCoords.push(cmd.y);
+ }
+
+ if (cmd.type === 'Q' || cmd.type === 'C') {
+ xCoords.push(cmd.x1);
+ yCoords.push(cmd.y1);
+ }
+
+ if (cmd.type === 'C') {
+ xCoords.push(cmd.x2);
+ yCoords.push(cmd.y2);
+ }
+ }
+
+ var metrics = {
+ xMin: Math.min.apply(null, xCoords),
+ yMin: Math.min.apply(null, yCoords),
+ xMax: Math.max.apply(null, xCoords),
+ yMax: Math.max.apply(null, yCoords),
+ leftSideBearing: 0
+ };
+ metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);
+ return metrics;
+};
+
+// Draw the glyph on the given context.
+//
+// ctx - The drawing context.
+// x - Horizontal position of the glyph. (default: 0)
+// y - Vertical position of the *baseline* of the glyph. (default: 0)
+// fontSize - Font size, in pixels (default: 72).
+Glyph.prototype.draw = function(ctx, x, y, fontSize) {
+ this.getPath(x, y, fontSize).draw(ctx);
+};
+
+// Draw the points of the glyph.
+// On-curve points will be drawn in blue, off-curve points will be drawn in red.
+//
+// ctx - The drawing context.
+// x - Horizontal position of the glyph. (default: 0)
+// y - Vertical position of the *baseline* of the glyph. (default: 0)
+// fontSize - Font size, in pixels (default: 72).
+Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {
+
+ function drawCircles(l, x, y, scale) {
+ var PI_SQ = Math.PI * 2;
+ ctx.beginPath();
+ for (var j = 0; j < l.length; j += 1) {
+ ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));
+ ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);
+ }
+
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ x = x !== undefined ? x : 0;
+ y = y !== undefined ? y : 0;
+ fontSize = fontSize !== undefined ? fontSize : 24;
+ var scale = 1 / this.path.unitsPerEm * fontSize;
+
+ var blueCircles = [];
+ var redCircles = [];
+ var path = this.path;
+ for (var i = 0; i < path.commands.length; i += 1) {
+ var cmd = path.commands[i];
+ if (cmd.x !== undefined) {
+ blueCircles.push({x: cmd.x, y: -cmd.y});
+ }
+
+ if (cmd.x1 !== undefined) {
+ redCircles.push({x: cmd.x1, y: -cmd.y1});
+ }
+
+ if (cmd.x2 !== undefined) {
+ redCircles.push({x: cmd.x2, y: -cmd.y2});
+ }
+ }
+
+ ctx.fillStyle = 'blue';
+ drawCircles(blueCircles, x, y, scale);
+ ctx.fillStyle = 'red';
+ drawCircles(redCircles, x, y, scale);
+};
+
+// Draw lines indicating important font measurements.
+// Black lines indicate the origin of the coordinate system (point 0,0).
+// Blue lines indicate the glyph bounding box.
+// Green line indicates the advance width of the glyph.
+//
+// ctx - The drawing context.
+// x - Horizontal position of the glyph. (default: 0)
+// y - Vertical position of the *baseline* of the glyph. (default: 0)
+// fontSize - Font size, in pixels (default: 72).
+Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {
+ var scale;
+ x = x !== undefined ? x : 0;
+ y = y !== undefined ? y : 0;
+ fontSize = fontSize !== undefined ? fontSize : 24;
+ scale = 1 / this.path.unitsPerEm * fontSize;
+ ctx.lineWidth = 1;
+
+ // Draw the origin
+ ctx.strokeStyle = 'black';
+ draw.line(ctx, x, -10000, x, 10000);
+ draw.line(ctx, -10000, y, 10000, y);
+
+ // This code is here due to memory optimization: by not using
+ // defaults in the constructor, we save a notable amount of memory.
+ var xMin = this.xMin || 0;
+ var yMin = this.yMin || 0;
+ var xMax = this.xMax || 0;
+ var yMax = this.yMax || 0;
+ var advanceWidth = this.advanceWidth || 0;
+
+ // Draw the glyph box
+ ctx.strokeStyle = 'blue';
+ draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);
+ draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);
+ draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));
+ draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));
+
+ // Draw the advance width
+ ctx.strokeStyle = 'green';
+ draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);
+};
+
+exports.Glyph = Glyph;
+
+},{"./check":2,"./draw":3,"./path":10}],7:[function(_dereq_,module,exports){
+// The GlyphSet object
+
+'use strict';
+
+var _glyph = _dereq_('./glyph');
+
+// A GlyphSet represents all glyphs available in the font, but modelled using
+// a deferred glyph loader, for retrieving glyphs only once they are absolutely
+// necessary, to keep the memory footprint down.
+function GlyphSet(font, glyphs) {
+ this.font = font;
+ this.glyphs = {};
+ if (Array.isArray(glyphs)) {
+ for (var i = 0; i < glyphs.length; i++) {
+ this.glyphs[i] = glyphs[i];
+ }
+ }
+
+ this.length = (glyphs && glyphs.length) || 0;
+}
+
+GlyphSet.prototype.get = function(index) {
+ if (typeof this.glyphs[index] === 'function') {
+ this.glyphs[index] = this.glyphs[index]();
+ }
+
+ return this.glyphs[index];
+};
+
+GlyphSet.prototype.push = function(index, loader) {
+ this.glyphs[index] = loader;
+ this.length++;
+};
+
+function glyphLoader(font, index) {
+ return new _glyph.Glyph({index: index, font: font});
+}
+
+/**
+ * Generate a stub glyph that can be filled with all metadata *except*
+ * the "points" and "path" properties, which must be loaded only once
+ * the glyph's path is actually requested for text shaping.
+ */
+
+function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
+ return function() {
+ var glyph = new _glyph.Glyph({index: index, font: font});
+
+ glyph.path = function() {
+ parseGlyph(glyph, data, position);
+ var path = buildPath(font.glyphs, glyph);
+ path.unitsPerEm = font.unitsPerEm;
+ return path;
+ };
+
+ return glyph;
+ };
+}
+
+function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
+ return function() {
+ var glyph = new _glyph.Glyph({index: index, font: font});
+
+ glyph.path = function() {
+ var path = parseCFFCharstring(font, glyph, charstring);
+ path.unitsPerEm = font.unitsPerEm;
+ return path;
+ };
+
+ return glyph;
+ };
+}
+
+exports.GlyphSet = GlyphSet;
+exports.glyphLoader = glyphLoader;
+exports.ttfGlyphLoader = ttfGlyphLoader;
+exports.cffGlyphLoader = cffGlyphLoader;
+
+},{"./glyph":6}],8:[function(_dereq_,module,exports){
+// opentype.js
+// https://github.com/nodebox/opentype.js
+// (c) 2015 Frederik De Bleser
+// opentype.js may be freely distributed under the MIT license.
+
+/* global ArrayBuffer, DataView, Uint8Array, XMLHttpRequest */
+
+'use strict';
+
+var encoding = _dereq_('./encoding');
+var _font = _dereq_('./font');
+var glyph = _dereq_('./glyph');
+var parse = _dereq_('./parse');
+var path = _dereq_('./path');
+
+var cmap = _dereq_('./tables/cmap');
+var cff = _dereq_('./tables/cff');
+var glyf = _dereq_('./tables/glyf');
+var gpos = _dereq_('./tables/gpos');
+var head = _dereq_('./tables/head');
+var hhea = _dereq_('./tables/hhea');
+var hmtx = _dereq_('./tables/hmtx');
+var kern = _dereq_('./tables/kern');
+var loca = _dereq_('./tables/loca');
+var maxp = _dereq_('./tables/maxp');
+var _name = _dereq_('./tables/name');
+var os2 = _dereq_('./tables/os2');
+var post = _dereq_('./tables/post');
+
+// File loaders /////////////////////////////////////////////////////////
+
+// Convert a Node.js Buffer to an ArrayBuffer
+function toArrayBuffer(buffer) {
+ var arrayBuffer = new ArrayBuffer(buffer.length);
+ var data = new Uint8Array(arrayBuffer);
+ for (var i = 0; i < buffer.length; i += 1) {
+ data[i] = buffer[i];
+ }
+
+ return arrayBuffer;
+}
+
+function loadFromFile(path, callback) {
+ var fs = _dereq_('fs');
+ fs.readFile(path, function(err, buffer) {
+ if (err) {
+ return callback(err.message);
+ }
+
+ callback(null, toArrayBuffer(buffer));
+ });
+}
+
+function loadFromUrl(url, callback) {
+ var request = new XMLHttpRequest();
+ request.open('get', url, true);
+ request.responseType = 'arraybuffer';
+ request.onload = function() {
+ if (request.status !== 200) {
+ return callback('Font could not be loaded: ' + request.statusText);
+ }
+
+ return callback(null, request.response);
+ };
+
+ request.send();
+}
+
+// Public API ///////////////////////////////////////////////////////////
+
+// Parse the OpenType file data (as an ArrayBuffer) and return a Font object.
+// If the file could not be parsed (most likely because it contains Postscript outlines)
+// we return an empty Font object with the `supported` flag set to `false`.
+function parseBuffer(buffer) {
+ var indexToLocFormat;
+ var hmtxOffset;
+ var glyfOffset;
+ var locaOffset;
+ var cffOffset;
+ var kernOffset;
+ var gposOffset;
+
+ // OpenType fonts use big endian byte ordering.
+ // We can't rely on typed array view types, because they operate with the endianness of the host computer.
+ // Instead we use DataViews where we can specify endianness.
+
+ var font = new _font.Font();
+ var data = new DataView(buffer, 0);
+
+ var version = parse.getFixed(data, 0);
+ if (version === 1.0) {
+ font.outlinesFormat = 'truetype';
+ } else {
+ version = parse.getTag(data, 0);
+ if (version === 'OTTO') {
+ font.outlinesFormat = 'cff';
+ } else {
+ throw new Error('Unsupported OpenType version ' + version);
+ }
+ }
+
+ var numTables = parse.getUShort(data, 4);
+
+ // Offset into the table records.
+ var p = 12;
+ for (var i = 0; i < numTables; i += 1) {
+ var tag = parse.getTag(data, p);
+ var offset = parse.getULong(data, p + 8);
+ switch (tag) {
+ case 'cmap':
+ font.tables.cmap = cmap.parse(data, offset);
+ font.encoding = new encoding.CmapEncoding(font.tables.cmap);
+ if (!font.encoding) {
+ font.supported = false;
+ }
+
+ break;
+ case 'head':
+ font.tables.head = head.parse(data, offset);
+ font.unitsPerEm = font.tables.head.unitsPerEm;
+ indexToLocFormat = font.tables.head.indexToLocFormat;
+ break;
+ case 'hhea':
+ font.tables.hhea = hhea.parse(data, offset);
+ font.ascender = font.tables.hhea.ascender;
+ font.descender = font.tables.hhea.descender;
+ font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
+ break;
+ case 'hmtx':
+ hmtxOffset = offset;
+ break;
+ case 'maxp':
+ font.tables.maxp = maxp.parse(data, offset);
+ font.numGlyphs = font.tables.maxp.numGlyphs;
+ break;
+ case 'name':
+ font.tables.name = _name.parse(data, offset);
+ font.familyName = font.tables.name.fontFamily;
+ font.styleName = font.tables.name.fontSubfamily;
+ break;
+ case 'OS/2':
+ font.tables.os2 = os2.parse(data, offset);
+ break;
+ case 'post':
+ font.tables.post = post.parse(data, offset);
+ font.glyphNames = new encoding.GlyphNames(font.tables.post);
+ break;
+ case 'glyf':
+ glyfOffset = offset;
+ break;
+ case 'loca':
+ locaOffset = offset;
+ break;
+ case 'CFF ':
+ cffOffset = offset;
+ break;
+ case 'kern':
+ kernOffset = offset;
+ break;
+ case 'GPOS':
+ gposOffset = offset;
+ break;
+ }
+ p += 16;
+ }
+
+ if (glyfOffset && locaOffset) {
+ var shortVersion = indexToLocFormat === 0;
+ var locaTable = loca.parse(data, locaOffset, font.numGlyphs, shortVersion);
+ font.glyphs = glyf.parse(data, glyfOffset, locaTable, font);
+ hmtx.parse(data, hmtxOffset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);
+ encoding.addGlyphNames(font);
+ } else if (cffOffset) {
+ cff.parse(data, cffOffset, font);
+ encoding.addGlyphNames(font);
+ } else {
+ font.supported = false;
+ }
+
+ if (font.supported) {
+ if (kernOffset) {
+ font.kerningPairs = kern.parse(data, kernOffset);
+ } else {
+ font.kerningPairs = {};
+ }
+
+ if (gposOffset) {
+ gpos.parse(data, gposOffset, font);
+ }
+ }
+
+ return font;
+}
+
+// Asynchronously load the font from a URL or a filesystem. When done, call the callback
+// with two arguments `(err, font)`. The `err` will be null on success,
+// the `font` is a Font object.
+//
+// We use the node.js callback convention so that
+// opentype.js can integrate with frameworks like async.js.
+function load(url, callback) {
+ var isNode = typeof window === 'undefined';
+ var loadFn = isNode ? loadFromFile : loadFromUrl;
+ loadFn(url, function(err, arrayBuffer) {
+ if (err) {
+ return callback(err);
+ }
+
+ var font = parseBuffer(arrayBuffer);
+ if (!font.supported) {
+ return callback('Font is not supported (is this a Postscript font?)');
+ }
+
+ return callback(null, font);
+ });
+}
+
+exports._parse = parse;
+exports.Font = _font.Font;
+exports.Glyph = glyph.Glyph;
+exports.Path = path.Path;
+exports.parse = parseBuffer;
+exports.load = load;
+
+},{"./encoding":4,"./font":5,"./glyph":6,"./parse":9,"./path":10,"./tables/cff":12,"./tables/cmap":13,"./tables/glyf":14,"./tables/gpos":15,"./tables/head":16,"./tables/hhea":17,"./tables/hmtx":18,"./tables/kern":19,"./tables/loca":20,"./tables/maxp":21,"./tables/name":22,"./tables/os2":23,"./tables/post":24,"fs":1}],9:[function(_dereq_,module,exports){
+// Parsing utility functions
+
+'use strict';
+
+// Retrieve an unsigned byte from the DataView.
+exports.getByte = function getByte(dataView, offset) {
+ return dataView.getUint8(offset);
+};
+
+exports.getCard8 = exports.getByte;
+
+// Retrieve an unsigned 16-bit short from the DataView.
+// The value is stored in big endian.
+exports.getUShort = function(dataView, offset) {
+ return dataView.getUint16(offset, false);
+};
+
+exports.getCard16 = exports.getUShort;
+
+// Retrieve a signed 16-bit short from the DataView.
+// The value is stored in big endian.
+exports.getShort = function(dataView, offset) {
+ return dataView.getInt16(offset, false);
+};
+
+// Retrieve an unsigned 32-bit long from the DataView.
+// The value is stored in big endian.
+exports.getULong = function(dataView, offset) {
+ return dataView.getUint32(offset, false);
+};
+
+// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.
+// The value is stored in big endian.
+exports.getFixed = function(dataView, offset) {
+ var decimal = dataView.getInt16(offset, false);
+ var fraction = dataView.getUint16(offset + 2, false);
+ return decimal + fraction / 65535;
+};
+
+// Retrieve a 4-character tag from the DataView.
+// Tags are used to identify tables.
+exports.getTag = function(dataView, offset) {
+ var tag = '';
+ for (var i = offset; i < offset + 4; i += 1) {
+ tag += String.fromCharCode(dataView.getInt8(i));
+ }
+
+ return tag;
+};
+
+// Retrieve an offset from the DataView.
+// Offsets are 1 to 4 bytes in length, depending on the offSize argument.
+exports.getOffset = function(dataView, offset, offSize) {
+ var v = 0;
+ for (var i = 0; i < offSize; i += 1) {
+ v <<= 8;
+ v += dataView.getUint8(offset + i);
+ }
+
+ return v;
+};
+
+// Retrieve a number of bytes from start offset to the end offset from the DataView.
+exports.getBytes = function(dataView, startOffset, endOffset) {
+ var bytes = [];
+ for (var i = startOffset; i < endOffset; i += 1) {
+ bytes.push(dataView.getUint8(i));
+ }
+
+ return bytes;
+};
+
+// Convert the list of bytes to a string.
+exports.bytesToString = function(bytes) {
+ var s = '';
+ for (var i = 0; i < bytes.length; i += 1) {
+ s += String.fromCharCode(bytes[i]);
+ }
+
+ return s;
+};
+
+var typeOffsets = {
+ byte: 1,
+ uShort: 2,
+ short: 2,
+ uLong: 4,
+ fixed: 4,
+ longDateTime: 8,
+ tag: 4
+};
+
+// A stateful parser that changes the offset whenever a value is retrieved.
+// The data is a DataView.
+function Parser(data, offset) {
+ this.data = data;
+ this.offset = offset;
+ this.relativeOffset = 0;
+}
+
+Parser.prototype.parseByte = function() {
+ var v = this.data.getUint8(this.offset + this.relativeOffset);
+ this.relativeOffset += 1;
+ return v;
+};
+
+Parser.prototype.parseChar = function() {
+ var v = this.data.getInt8(this.offset + this.relativeOffset);
+ this.relativeOffset += 1;
+ return v;
+};
+
+Parser.prototype.parseCard8 = Parser.prototype.parseByte;
+
+Parser.prototype.parseUShort = function() {
+ var v = this.data.getUint16(this.offset + this.relativeOffset);
+ this.relativeOffset += 2;
+ return v;
+};
+
+Parser.prototype.parseCard16 = Parser.prototype.parseUShort;
+Parser.prototype.parseSID = Parser.prototype.parseUShort;
+Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;
+
+Parser.prototype.parseShort = function() {
+ var v = this.data.getInt16(this.offset + this.relativeOffset);
+ this.relativeOffset += 2;
+ return v;
+};
+
+Parser.prototype.parseF2Dot14 = function() {
+ var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
+ this.relativeOffset += 2;
+ return v;
+};
+
+Parser.prototype.parseULong = function() {
+ var v = exports.getULong(this.data, this.offset + this.relativeOffset);
+ this.relativeOffset += 4;
+ return v;
+};
+
+Parser.prototype.parseFixed = function() {
+ var v = exports.getFixed(this.data, this.offset + this.relativeOffset);
+ this.relativeOffset += 4;
+ return v;
+};
+
+Parser.prototype.parseOffset16List =
+Parser.prototype.parseUShortList = function(count) {
+ var offsets = new Array(count);
+ var dataView = this.data;
+ var offset = this.offset + this.relativeOffset;
+ for (var i = 0; i < count; i++) {
+ offsets[i] = exports.getUShort(dataView, offset);
+ offset += 2;
+ }
+
+ this.relativeOffset += count * 2;
+ return offsets;
+};
+
+Parser.prototype.parseString = function(length) {
+ var dataView = this.data;
+ var offset = this.offset + this.relativeOffset;
+ var string = '';
+ this.relativeOffset += length;
+ for (var i = 0; i < length; i++) {
+ string += String.fromCharCode(dataView.getUint8(offset + i));
+ }
+
+ return string;
+};
+
+Parser.prototype.parseTag = function() {
+ return this.parseString(4);
+};
+
+// LONGDATETIME is a 64-bit integer.
+// JavaScript and unix timestamps traditionally use 32 bits, so we
+// only take the last 32 bits.
+Parser.prototype.parseLongDateTime = function() {
+ var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4);
+ this.relativeOffset += 8;
+ return v;
+};
+
+Parser.prototype.parseFixed = function() {
+ var v = exports.getULong(this.data, this.offset + this.relativeOffset);
+ this.relativeOffset += 4;
+ return v / 65536;
+};
+
+Parser.prototype.parseVersion = function() {
+ var major = exports.getUShort(this.data, this.offset + this.relativeOffset);
+
+ // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
+ // This returns the correct number if minor = 0xN000 where N is 0-9
+ var minor = exports.getUShort(this.data, this.offset + this.relativeOffset + 2);
+ this.relativeOffset += 4;
+ return major + minor / 0x1000 / 10;
+};
+
+Parser.prototype.skip = function(type, amount) {
+ if (amount === undefined) {
+ amount = 1;
+ }
+
+ this.relativeOffset += typeOffsets[type] * amount;
+};
+
+exports.Parser = Parser;
+
+},{}],10:[function(_dereq_,module,exports){
+// Geometric objects
+
+'use strict';
+
+// A bézier path containing a set of path commands similar to a SVG path.
+// Paths can be drawn on a context using `draw`.
+function Path() {
+ this.commands = [];
+ this.fill = 'black';
+ this.stroke = null;
+ this.strokeWidth = 1;
+}
+
+Path.prototype.moveTo = function(x, y) {
+ this.commands.push({
+ type: 'M',
+ x: x,
+ y: y
+ });
+};
+
+Path.prototype.lineTo = function(x, y) {
+ this.commands.push({
+ type: 'L',
+ x: x,
+ y: y
+ });
+};
+
+Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {
+ this.commands.push({
+ type: 'C',
+ x1: x1,
+ y1: y1,
+ x2: x2,
+ y2: y2,
+ x: x,
+ y: y
+ });
+};
+
+Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {
+ this.commands.push({
+ type: 'Q',
+ x1: x1,
+ y1: y1,
+ x: x,
+ y: y
+ });
+};
+
+Path.prototype.close = Path.prototype.closePath = function() {
+ this.commands.push({
+ type: 'Z'
+ });
+};
+
+// Add the given path or list of commands to the commands of this path.
+Path.prototype.extend = function(pathOrCommands) {
+ if (pathOrCommands.commands) {
+ pathOrCommands = pathOrCommands.commands;
+ }
+
+ Array.prototype.push.apply(this.commands, pathOrCommands);
+};
+
+// Draw the path to a 2D context.
+Path.prototype.draw = function(ctx) {
+ ctx.beginPath();
+ for (var i = 0; i < this.commands.length; i += 1) {
+ var cmd = this.commands[i];
+ if (cmd.type === 'M') {
+ ctx.moveTo(cmd.x, cmd.y);
+ } else if (cmd.type === 'L') {
+ ctx.lineTo(cmd.x, cmd.y);
+ } else if (cmd.type === 'C') {
+ ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
+ } else if (cmd.type === 'Q') {
+ ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
+ } else if (cmd.type === 'Z') {
+ ctx.closePath();
+ }
+ }
+
+ if (this.fill) {
+ ctx.fillStyle = this.fill;
+ ctx.fill();
+ }
+
+ if (this.stroke) {
+ ctx.strokeStyle = this.stroke;
+ ctx.lineWidth = this.strokeWidth;
+ ctx.stroke();
+ }
+};
+
+// Convert the Path to a string of path data instructions
+// See http://www.w3.org/TR/SVG/paths.html#PathData
+// Parameters:
+// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
+Path.prototype.toPathData = function(decimalPlaces) {
+ decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
+
+ function floatToString(v) {
+ if (Math.round(v) === v) {
+ return '' + Math.round(v);
+ } else {
+ return v.toFixed(decimalPlaces);
+ }
+ }
+
+ function packValues() {
+ var s = '';
+ for (var i = 0; i < arguments.length; i += 1) {
+ var v = arguments[i];
+ if (v >= 0 && i > 0) {
+ s += ' ';
+ }
+
+ s += floatToString(v);
+ }
+
+ return s;
+ }
+
+ var d = '';
+ for (var i = 0; i < this.commands.length; i += 1) {
+ var cmd = this.commands[i];
+ if (cmd.type === 'M') {
+ d += 'M' + packValues(cmd.x, cmd.y);
+ } else if (cmd.type === 'L') {
+ d += 'L' + packValues(cmd.x, cmd.y);
+ } else if (cmd.type === 'C') {
+ d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
+ } else if (cmd.type === 'Q') {
+ d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
+ } else if (cmd.type === 'Z') {
+ d += 'Z';
+ }
+ }
+
+ return d;
+};
+
+// Convert the path to a SVG element, as a string.
+// Parameters:
+// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
+Path.prototype.toSVG = function(decimalPlaces) {
+ var svg = '';
+ return svg;
+};
+
+exports.Path = Path;
+
+},{}],11:[function(_dereq_,module,exports){
+// Table metadata
+
+'use strict';
+
+var check = _dereq_('./check');
+var encode = _dereq_('./types').encode;
+var sizeOf = _dereq_('./types').sizeOf;
+
+function Table(tableName, fields, options) {
+ var i;
+ for (i = 0; i < fields.length; i += 1) {
+ var field = fields[i];
+ this[field.name] = field.value;
+ }
+
+ this.tableName = tableName;
+ this.fields = fields;
+ if (options) {
+ var optionKeys = Object.keys(options);
+ for (i = 0; i < optionKeys.length; i += 1) {
+ var k = optionKeys[i];
+ var v = options[k];
+ if (this[k] !== undefined) {
+ this[k] = v;
+ }
+ }
+ }
+}
+
+Table.prototype.sizeOf = function() {
+ var v = 0;
+ for (var i = 0; i < this.fields.length; i += 1) {
+ var field = this.fields[i];
+ var value = this[field.name];
+ if (value === undefined) {
+ value = field.value;
+ }
+
+ if (typeof value.sizeOf === 'function') {
+ v += value.sizeOf();
+ } else {
+ var sizeOfFunction = sizeOf[field.type];
+ check.assert(typeof sizeOfFunction === 'function', 'Could not find sizeOf function for field' + field.name);
+ v += sizeOfFunction(value);
+ }
+ }
+
+ return v;
+};
+
+Table.prototype.encode = function() {
+ return encode.TABLE(this);
+};
+
+exports.Table = Table;
+
+},{"./check":2,"./types":26}],12:[function(_dereq_,module,exports){
+// The `CFF` table contains the glyph outlines in PostScript format.
+// https://www.microsoft.com/typography/OTSPEC/cff.htm
+// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf
+// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf
+
+'use strict';
+
+var encoding = _dereq_('../encoding');
+var glyphset = _dereq_('../glyphset');
+var parse = _dereq_('../parse');
+var path = _dereq_('../path');
+var table = _dereq_('../table');
+
+// Custom equals function that can also check lists.
+function equals(a, b) {
+ if (a === b) {
+ return true;
+ } else if (Array.isArray(a) && Array.isArray(b)) {
+ if (a.length !== b.length) {
+ return false;
+ }
+
+ for (var i = 0; i < a.length; i += 1) {
+ if (!equals(a[i], b[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Parse a `CFF` INDEX array.
+// An index array consists of a list of offsets, then a list of objects at those offsets.
+function parseCFFIndex(data, start, conversionFn) {
+ //var i, objectOffset, endOffset;
+ var offsets = [];
+ var objects = [];
+ var count = parse.getCard16(data, start);
+ var i;
+ var objectOffset;
+ var endOffset;
+ if (count !== 0) {
+ var offsetSize = parse.getByte(data, start + 2);
+ objectOffset = start + ((count + 1) * offsetSize) + 2;
+ var pos = start + 3;
+ for (i = 0; i < count + 1; i += 1) {
+ offsets.push(parse.getOffset(data, pos, offsetSize));
+ pos += offsetSize;
+ }
+
+ // The total size of the index array is 4 header bytes + the value of the last offset.
+ endOffset = objectOffset + offsets[count];
+ } else {
+ endOffset = start + 2;
+ }
+
+ for (i = 0; i < offsets.length - 1; i += 1) {
+ var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);
+ if (conversionFn) {
+ value = conversionFn(value);
+ }
+
+ objects.push(value);
+ }
+
+ return {objects: objects, startOffset: start, endOffset: endOffset};
+}
+
+// Parse a `CFF` DICT real value.
+function parseFloatOperand(parser) {
+ var s = '';
+ var eof = 15;
+ var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
+ while (true) {
+ var b = parser.parseByte();
+ var n1 = b >> 4;
+ var n2 = b & 15;
+
+ if (n1 === eof) {
+ break;
+ }
+
+ s += lookup[n1];
+
+ if (n2 === eof) {
+ break;
+ }
+
+ s += lookup[n2];
+ }
+
+ return parseFloat(s);
+}
+
+// Parse a `CFF` DICT operand.
+function parseOperand(parser, b0) {
+ var b1;
+ var b2;
+ var b3;
+ var b4;
+ if (b0 === 28) {
+ b1 = parser.parseByte();
+ b2 = parser.parseByte();
+ return b1 << 8 | b2;
+ }
+
+ if (b0 === 29) {
+ b1 = parser.parseByte();
+ b2 = parser.parseByte();
+ b3 = parser.parseByte();
+ b4 = parser.parseByte();
+ return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ }
+
+ if (b0 === 30) {
+ return parseFloatOperand(parser);
+ }
+
+ if (b0 >= 32 && b0 <= 246) {
+ return b0 - 139;
+ }
+
+ if (b0 >= 247 && b0 <= 250) {
+ b1 = parser.parseByte();
+ return (b0 - 247) * 256 + b1 + 108;
+ }
+
+ if (b0 >= 251 && b0 <= 254) {
+ b1 = parser.parseByte();
+ return -(b0 - 251) * 256 - b1 - 108;
+ }
+
+ throw new Error('Invalid b0 ' + b0);
+}
+
+// Convert the entries returned by `parseDict` to a proper dictionary.
+// If a value is a list of one, it is unpacked.
+function entriesToObject(entries) {
+ var o = {};
+ for (var i = 0; i < entries.length; i += 1) {
+ var key = entries[i][0];
+ var values = entries[i][1];
+ var value;
+ if (values.length === 1) {
+ value = values[0];
+ } else {
+ value = values;
+ }
+
+ if (o.hasOwnProperty(key)) {
+ throw new Error('Object ' + o + ' already has key ' + key);
+ }
+
+ o[key] = value;
+ }
+
+ return o;
+}
+
+// Parse a `CFF` DICT object.
+// A dictionary contains key-value pairs in a compact tokenized format.
+function parseCFFDict(data, start, size) {
+ start = start !== undefined ? start : 0;
+ var parser = new parse.Parser(data, start);
+ var entries = [];
+ var operands = [];
+ size = size !== undefined ? size : data.length;
+
+ while (parser.relativeOffset < size) {
+ var op = parser.parseByte();
+
+ // The first byte for each dict item distinguishes between operator (key) and operand (value).
+ // Values <= 21 are operators.
+ if (op <= 21) {
+ // Two-byte operators have an initial escape byte of 12.
+ if (op === 12) {
+ op = 1200 + parser.parseByte();
+ }
+
+ entries.push([op, operands]);
+ operands = [];
+ } else {
+ // Since the operands (values) come before the operators (keys), we store all operands in a list
+ // until we encounter an operator.
+ operands.push(parseOperand(parser, op));
+ }
+ }
+
+ return entriesToObject(entries);
+}
+
+// Given a String Index (SID), return the value of the string.
+// Strings below index 392 are standard CFF strings and are not encoded in the font.
+function getCFFString(strings, index) {
+ if (index <= 390) {
+ index = encoding.cffStandardStrings[index];
+ } else {
+ index = strings[index - 391];
+ }
+
+ return index;
+}
+
+// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.
+// This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.
+function interpretDict(dict, meta, strings) {
+ var newDict = {};
+
+ // Because we also want to include missing values, we start out from the meta list
+ // and lookup values in the dict.
+ for (var i = 0; i < meta.length; i += 1) {
+ var m = meta[i];
+ var value = dict[m.op];
+ if (value === undefined) {
+ value = m.value !== undefined ? m.value : null;
+ }
+
+ if (m.type === 'SID') {
+ value = getCFFString(strings, value);
+ }
+
+ newDict[m.name] = value;
+ }
+
+ return newDict;
+}
+
+// Parse the CFF header.
+function parseCFFHeader(data, start) {
+ var header = {};
+ header.formatMajor = parse.getCard8(data, start);
+ header.formatMinor = parse.getCard8(data, start + 1);
+ header.size = parse.getCard8(data, start + 2);
+ header.offsetSize = parse.getCard8(data, start + 3);
+ header.startOffset = start;
+ header.endOffset = start + 4;
+ return header;
+}
+
+var TOP_DICT_META = [
+ {name: 'version', op: 0, type: 'SID'},
+ {name: 'notice', op: 1, type: 'SID'},
+ {name: 'copyright', op: 1200, type: 'SID'},
+ {name: 'fullName', op: 2, type: 'SID'},
+ {name: 'familyName', op: 3, type: 'SID'},
+ {name: 'weight', op: 4, type: 'SID'},
+ {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},
+ {name: 'italicAngle', op: 1202, type: 'number', value: 0},
+ {name: 'underlinePosition', op: 1203, type: 'number', value: -100},
+ {name: 'underlineThickness', op: 1204, type: 'number', value: 50},
+ {name: 'paintType', op: 1205, type: 'number', value: 0},
+ {name: 'charstringType', op: 1206, type: 'number', value: 2},
+ {name: 'fontMatrix', op: 1207, type: ['real', 'real', 'real', 'real', 'real', 'real'], value: [0.001, 0, 0, 0.001, 0, 0]},
+ {name: 'uniqueId', op: 13, type: 'number'},
+ {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},
+ {name: 'strokeWidth', op: 1208, type: 'number', value: 0},
+ {name: 'xuid', op: 14, type: [], value: null},
+ {name: 'charset', op: 15, type: 'offset', value: 0},
+ {name: 'encoding', op: 16, type: 'offset', value: 0},
+ {name: 'charStrings', op: 17, type: 'offset', value: 0},
+ {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}
+];
+
+var PRIVATE_DICT_META = [
+ {name: 'subrs', op: 19, type: 'offset', value: 0},
+ {name: 'defaultWidthX', op: 20, type: 'number', value: 0},
+ {name: 'nominalWidthX', op: 21, type: 'number', value: 0}
+];
+
+// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.
+// The top dictionary contains the essential metadata for the font, together with the private dictionary.
+function parseCFFTopDict(data, strings) {
+ var dict = parseCFFDict(data, 0, data.byteLength);
+ return interpretDict(dict, TOP_DICT_META, strings);
+}
+
+// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.
+function parseCFFPrivateDict(data, start, size, strings) {
+ var dict = parseCFFDict(data, start, size);
+ return interpretDict(dict, PRIVATE_DICT_META, strings);
+}
+
+// Parse the CFF charset table, which contains internal names for all the glyphs.
+// This function will return a list of glyph names.
+// See Adobe TN #5176 chapter 13, "Charsets".
+function parseCFFCharset(data, start, nGlyphs, strings) {
+ var i;
+ var sid;
+ var count;
+ var parser = new parse.Parser(data, start);
+
+ // The .notdef glyph is not included, so subtract 1.
+ nGlyphs -= 1;
+ var charset = ['.notdef'];
+
+ var format = parser.parseCard8();
+ if (format === 0) {
+ for (i = 0; i < nGlyphs; i += 1) {
+ sid = parser.parseSID();
+ charset.push(getCFFString(strings, sid));
+ }
+ } else if (format === 1) {
+ while (charset.length <= nGlyphs) {
+ sid = parser.parseSID();
+ count = parser.parseCard8();
+ for (i = 0; i <= count; i += 1) {
+ charset.push(getCFFString(strings, sid));
+ sid += 1;
+ }
+ }
+ } else if (format === 2) {
+ while (charset.length <= nGlyphs) {
+ sid = parser.parseSID();
+ count = parser.parseCard16();
+ for (i = 0; i <= count; i += 1) {
+ charset.push(getCFFString(strings, sid));
+ sid += 1;
+ }
+ }
+ } else {
+ throw new Error('Unknown charset format ' + format);
+ }
+
+ return charset;
+}
+
+// Parse the CFF encoding data. Only one encoding can be specified per font.
+// See Adobe TN #5176 chapter 12, "Encodings".
+function parseCFFEncoding(data, start, charset) {
+ var i;
+ var code;
+ var enc = {};
+ var parser = new parse.Parser(data, start);
+ var format = parser.parseCard8();
+ if (format === 0) {
+ var nCodes = parser.parseCard8();
+ for (i = 0; i < nCodes; i += 1) {
+ code = parser.parseCard8();
+ enc[code] = i;
+ }
+ } else if (format === 1) {
+ var nRanges = parser.parseCard8();
+ code = 1;
+ for (i = 0; i < nRanges; i += 1) {
+ var first = parser.parseCard8();
+ var nLeft = parser.parseCard8();
+ for (var j = first; j <= first + nLeft; j += 1) {
+ enc[j] = code;
+ code += 1;
+ }
+ }
+ } else {
+ throw new Error('Unknown encoding format ' + format);
+ }
+
+ return new encoding.CffEncoding(enc, charset);
+}
+
+// Take in charstring code and return a Glyph object.
+// The encoding is described in the Type 2 Charstring Format
+// https://www.microsoft.com/typography/OTSPEC/charstr2.htm
+function parseCFFCharstring(font, glyph, code) {
+ var c1x;
+ var c1y;
+ var c2x;
+ var c2y;
+ var p = new path.Path();
+ var stack = [];
+ var nStems = 0;
+ var haveWidth = false;
+ var width = font.defaultWidthX;
+ var open = false;
+ var x = 0;
+ var y = 0;
+
+ function newContour(x, y) {
+ if (open) {
+ p.closePath();
+ }
+
+ p.moveTo(x, y);
+ open = true;
+ }
+
+ function parseStems() {
+ var hasWidthArg;
+
+ // The number of stem operators on the stack is always even.
+ // If the value is uneven, that means a width is specified.
+ hasWidthArg = stack.length % 2 !== 0;
+ if (hasWidthArg && !haveWidth) {
+ width = stack.shift() + font.nominalWidthX;
+ }
+
+ nStems += stack.length >> 1;
+ stack.length = 0;
+ haveWidth = true;
+ }
+
+ function parse(code) {
+ var b1;
+ var b2;
+ var b3;
+ var b4;
+ var codeIndex;
+ var subrCode;
+ var jpx;
+ var jpy;
+ var c3x;
+ var c3y;
+ var c4x;
+ var c4y;
+
+ var i = 0;
+ while (i < code.length) {
+ var v = code[i];
+ i += 1;
+ switch (v) {
+ case 1: // hstem
+ parseStems();
+ break;
+ case 3: // vstem
+ parseStems();
+ break;
+ case 4: // vmoveto
+ if (stack.length > 1 && !haveWidth) {
+ width = stack.shift() + font.nominalWidthX;
+ haveWidth = true;
+ }
+
+ y += stack.pop();
+ newContour(x, y);
+ break;
+ case 5: // rlineto
+ while (stack.length > 0) {
+ x += stack.shift();
+ y += stack.shift();
+ p.lineTo(x, y);
+ }
+
+ break;
+ case 6: // hlineto
+ while (stack.length > 0) {
+ x += stack.shift();
+ p.lineTo(x, y);
+ if (stack.length === 0) {
+ break;
+ }
+
+ y += stack.shift();
+ p.lineTo(x, y);
+ }
+
+ break;
+ case 7: // vlineto
+ while (stack.length > 0) {
+ y += stack.shift();
+ p.lineTo(x, y);
+ if (stack.length === 0) {
+ break;
+ }
+
+ x += stack.shift();
+ p.lineTo(x, y);
+ }
+
+ break;
+ case 8: // rrcurveto
+ while (stack.length > 0) {
+ c1x = x + stack.shift();
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y + stack.shift();
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ break;
+ case 10: // callsubr
+ codeIndex = stack.pop() + font.subrsBias;
+ subrCode = font.subrs[codeIndex];
+ if (subrCode) {
+ parse(subrCode);
+ }
+
+ break;
+ case 11: // return
+ return;
+ case 12: // flex operators
+ v = code[i];
+ i += 1;
+ switch (v) {
+ case 35: // flex
+ // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
+ c1x = x + stack.shift(); // dx1
+ c1y = y + stack.shift(); // dy1
+ c2x = c1x + stack.shift(); // dx2
+ c2y = c1y + stack.shift(); // dy2
+ jpx = c2x + stack.shift(); // dx3
+ jpy = c2y + stack.shift(); // dy3
+ c3x = jpx + stack.shift(); // dx4
+ c3y = jpy + stack.shift(); // dy4
+ c4x = c3x + stack.shift(); // dx5
+ c4y = c3y + stack.shift(); // dy5
+ x = c4x + stack.shift(); // dx6
+ y = c4y + stack.shift(); // dy6
+ stack.shift(); // flex depth
+ p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
+ p.curveTo(c3x, c3y, c4x, c4y, x, y);
+ break;
+ case 34: // hflex
+ // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
+ c1x = x + stack.shift(); // dx1
+ c1y = y; // dy1
+ c2x = c1x + stack.shift(); // dx2
+ c2y = c1y + stack.shift(); // dy2
+ jpx = c2x + stack.shift(); // dx3
+ jpy = c2y; // dy3
+ c3x = jpx + stack.shift(); // dx4
+ c3y = c2y; // dy4
+ c4x = c3x + stack.shift(); // dx5
+ c4y = y; // dy5
+ x = c4x + stack.shift(); // dx6
+ p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
+ p.curveTo(c3x, c3y, c4x, c4y, x, y);
+ break;
+ case 36: // hflex1
+ // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
+ c1x = x + stack.shift(); // dx1
+ c1y = y + stack.shift(); // dy1
+ c2x = c1x + stack.shift(); // dx2
+ c2y = c1y + stack.shift(); // dy2
+ jpx = c2x + stack.shift(); // dx3
+ jpy = c2y; // dy3
+ c3x = jpx + stack.shift(); // dx4
+ c3y = c2y; // dy4
+ c4x = c3x + stack.shift(); // dx5
+ c4y = c3y + stack.shift(); // dy5
+ x = c4x + stack.shift(); // dx6
+ p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
+ p.curveTo(c3x, c3y, c4x, c4y, x, y);
+ break;
+ case 37: // flex1
+ // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
+ c1x = x + stack.shift(); // dx1
+ c1y = y + stack.shift(); // dy1
+ c2x = c1x + stack.shift(); // dx2
+ c2y = c1y + stack.shift(); // dy2
+ jpx = c2x + stack.shift(); // dx3
+ jpy = c2y + stack.shift(); // dy3
+ c3x = jpx + stack.shift(); // dx4
+ c3y = jpy + stack.shift(); // dy4
+ c4x = c3x + stack.shift(); // dx5
+ c4y = c3y + stack.shift(); // dy5
+ if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
+ x = c4x + stack.shift();
+ } else {
+ y = c4y + stack.shift();
+ }
+
+ p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
+ p.curveTo(c3x, c3y, c4x, c4y, x, y);
+ break;
+ default:
+ console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);
+ stack.length = 0;
+ }
+ break;
+ case 14: // endchar
+ if (stack.length > 0 && !haveWidth) {
+ width = stack.shift() + font.nominalWidthX;
+ haveWidth = true;
+ }
+
+ if (open) {
+ p.closePath();
+ open = false;
+ }
+
+ break;
+ case 18: // hstemhm
+ parseStems();
+ break;
+ case 19: // hintmask
+ case 20: // cntrmask
+ parseStems();
+ i += (nStems + 7) >> 3;
+ break;
+ case 21: // rmoveto
+ if (stack.length > 2 && !haveWidth) {
+ width = stack.shift() + font.nominalWidthX;
+ haveWidth = true;
+ }
+
+ y += stack.pop();
+ x += stack.pop();
+ newContour(x, y);
+ break;
+ case 22: // hmoveto
+ if (stack.length > 1 && !haveWidth) {
+ width = stack.shift() + font.nominalWidthX;
+ haveWidth = true;
+ }
+
+ x += stack.pop();
+ newContour(x, y);
+ break;
+ case 23: // vstemhm
+ parseStems();
+ break;
+ case 24: // rcurveline
+ while (stack.length > 2) {
+ c1x = x + stack.shift();
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y + stack.shift();
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ x += stack.shift();
+ y += stack.shift();
+ p.lineTo(x, y);
+ break;
+ case 25: // rlinecurve
+ while (stack.length > 6) {
+ x += stack.shift();
+ y += stack.shift();
+ p.lineTo(x, y);
+ }
+
+ c1x = x + stack.shift();
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y + stack.shift();
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ break;
+ case 26: // vvcurveto
+ if (stack.length % 2) {
+ x += stack.shift();
+ }
+
+ while (stack.length > 0) {
+ c1x = x;
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x;
+ y = c2y + stack.shift();
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ break;
+ case 27: // hhcurveto
+ if (stack.length % 2) {
+ y += stack.shift();
+ }
+
+ while (stack.length > 0) {
+ c1x = x + stack.shift();
+ c1y = y;
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y;
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ break;
+ case 28: // shortint
+ b1 = code[i];
+ b2 = code[i + 1];
+ stack.push(((b1 << 24) | (b2 << 16)) >> 16);
+ i += 2;
+ break;
+ case 29: // callgsubr
+ codeIndex = stack.pop() + font.gsubrsBias;
+ subrCode = font.gsubrs[codeIndex];
+ if (subrCode) {
+ parse(subrCode);
+ }
+
+ break;
+ case 30: // vhcurveto
+ while (stack.length > 0) {
+ c1x = x;
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y + (stack.length === 1 ? stack.shift() : 0);
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ if (stack.length === 0) {
+ break;
+ }
+
+ c1x = x + stack.shift();
+ c1y = y;
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ y = c2y + stack.shift();
+ x = c2x + (stack.length === 1 ? stack.shift() : 0);
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ break;
+ case 31: // hvcurveto
+ while (stack.length > 0) {
+ c1x = x + stack.shift();
+ c1y = y;
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ y = c2y + stack.shift();
+ x = c2x + (stack.length === 1 ? stack.shift() : 0);
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ if (stack.length === 0) {
+ break;
+ }
+
+ c1x = x;
+ c1y = y + stack.shift();
+ c2x = c1x + stack.shift();
+ c2y = c1y + stack.shift();
+ x = c2x + stack.shift();
+ y = c2y + (stack.length === 1 ? stack.shift() : 0);
+ p.curveTo(c1x, c1y, c2x, c2y, x, y);
+ }
+
+ break;
+ default:
+ if (v < 32) {
+ console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
+ } else if (v < 247) {
+ stack.push(v - 139);
+ } else if (v < 251) {
+ b1 = code[i];
+ i += 1;
+ stack.push((v - 247) * 256 + b1 + 108);
+ } else if (v < 255) {
+ b1 = code[i];
+ i += 1;
+ stack.push(-(v - 251) * 256 - b1 - 108);
+ } else {
+ b1 = code[i];
+ b2 = code[i + 1];
+ b3 = code[i + 2];
+ b4 = code[i + 3];
+ i += 4;
+ stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);
+ }
+ }
+ }
+ }
+
+ parse(code);
+
+ glyph.advanceWidth = width;
+ return p;
+}
+
+// Subroutines are encoded using the negative half of the number space.
+// See type 2 chapter 4.7 "Subroutine operators".
+function calcCFFSubroutineBias(subrs) {
+ var bias;
+ if (subrs.length < 1240) {
+ bias = 107;
+ } else if (subrs.length < 33900) {
+ bias = 1131;
+ } else {
+ bias = 32768;
+ }
+
+ return bias;
+}
+
+// Parse the `CFF` table, which contains the glyph outlines in PostScript format.
+function parseCFFTable(data, start, font) {
+ font.tables.cff = {};
+ var header = parseCFFHeader(data, start);
+ var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
+ var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
+ var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
+ var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
+ font.gsubrs = globalSubrIndex.objects;
+ font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
+
+ var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);
+ var topDict = parseCFFTopDict(topDictData, stringIndex.objects);
+ font.tables.cff.topDict = topDict;
+
+ var privateDictOffset = start + topDict['private'][1];
+ var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);
+ font.defaultWidthX = privateDict.defaultWidthX;
+ font.nominalWidthX = privateDict.nominalWidthX;
+
+ if (privateDict.subrs !== 0) {
+ var subrOffset = privateDictOffset + privateDict.subrs;
+ var subrIndex = parseCFFIndex(data, subrOffset);
+ font.subrs = subrIndex.objects;
+ font.subrsBias = calcCFFSubroutineBias(font.subrs);
+ } else {
+ font.subrs = [];
+ font.subrsBias = 0;
+ }
+
+ // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
+ var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
+ font.nGlyphs = charStringsIndex.objects.length;
+
+ var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
+ if (topDict.encoding === 0) { // Standard encoding
+ font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);
+ } else if (topDict.encoding === 1) { // Expert encoding
+ font.cffEncoding = new encoding.CffEncoding(encoding.cffExpertEncoding, charset);
+ } else {
+ font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);
+ }
+
+ // Prefer the CMAP encoding to the CFF encoding.
+ font.encoding = font.encoding || font.cffEncoding;
+
+ font.glyphs = new glyphset.GlyphSet(font);
+ for (var i = 0; i < font.nGlyphs; i += 1) {
+ var charString = charStringsIndex.objects[i];
+ font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));
+ }
+}
+
+// Convert a string to a String ID (SID).
+// The list of strings is modified in place.
+function encodeString(s, strings) {
+ var sid;
+
+ // Is the string in the CFF standard strings?
+ var i = encoding.cffStandardStrings.indexOf(s);
+ if (i >= 0) {
+ sid = i;
+ }
+
+ // Is the string already in the string index?
+ i = strings.indexOf(s);
+ if (i >= 0) {
+ sid = i + encoding.cffStandardStrings.length;
+ } else {
+ sid = encoding.cffStandardStrings.length + strings.length;
+ strings.push(s);
+ }
+
+ return sid;
+}
+
+function makeHeader() {
+ return new table.Table('Header', [
+ {name: 'major', type: 'Card8', value: 1},
+ {name: 'minor', type: 'Card8', value: 0},
+ {name: 'hdrSize', type: 'Card8', value: 4},
+ {name: 'major', type: 'Card8', value: 1}
+ ]);
+}
+
+function makeNameIndex(fontNames) {
+ var t = new table.Table('Name INDEX', [
+ {name: 'names', type: 'INDEX', value: []}
+ ]);
+ t.names = [];
+ for (var i = 0; i < fontNames.length; i += 1) {
+ t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});
+ }
+
+ return t;
+}
+
+// Given a dictionary's metadata, create a DICT structure.
+function makeDict(meta, attrs, strings) {
+ var m = {};
+ for (var i = 0; i < meta.length; i += 1) {
+ var entry = meta[i];
+ var value = attrs[entry.name];
+ if (value !== undefined && !equals(value, entry.value)) {
+ if (entry.type === 'SID') {
+ value = encodeString(value, strings);
+ }
+
+ m[entry.op] = {name: entry.name, type: entry.type, value: value};
+ }
+ }
+
+ return m;
+}
+
+// The Top DICT houses the global font attributes.
+function makeTopDict(attrs, strings) {
+ var t = new table.Table('Top DICT', [
+ {name: 'dict', type: 'DICT', value: {}}
+ ]);
+ t.dict = makeDict(TOP_DICT_META, attrs, strings);
+ return t;
+}
+
+function makeTopDictIndex(topDict) {
+ var t = new table.Table('Top DICT INDEX', [
+ {name: 'topDicts', type: 'INDEX', value: []}
+ ]);
+ t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];
+ return t;
+}
+
+function makeStringIndex(strings) {
+ var t = new table.Table('String INDEX', [
+ {name: 'strings', type: 'INDEX', value: []}
+ ]);
+ t.strings = [];
+ for (var i = 0; i < strings.length; i += 1) {
+ t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});
+ }
+
+ return t;
+}
+
+function makeGlobalSubrIndex() {
+ // Currently we don't use subroutines.
+ return new table.Table('Global Subr INDEX', [
+ {name: 'subrs', type: 'INDEX', value: []}
+ ]);
+}
+
+function makeCharsets(glyphNames, strings) {
+ var t = new table.Table('Charsets', [
+ {name: 'format', type: 'Card8', value: 0}
+ ]);
+ for (var i = 0; i < glyphNames.length; i += 1) {
+ var glyphName = glyphNames[i];
+ var glyphSID = encodeString(glyphName, strings);
+ t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});
+ }
+
+ return t;
+}
+
+function glyphToOps(glyph) {
+ var ops = [];
+ var path = glyph.path;
+ ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});
+ var x = 0;
+ var y = 0;
+ for (var i = 0; i < path.commands.length; i += 1) {
+ var dx;
+ var dy;
+ var cmd = path.commands[i];
+ if (cmd.type === 'Q') {
+ // CFF only supports bézier curves, so convert the quad to a bézier.
+ var _13 = 1 / 3;
+ var _23 = 2 / 3;
+
+ // We're going to create a new command so we don't change the original path.
+ cmd = {
+ type: 'C',
+ x: cmd.x,
+ y: cmd.y,
+ x1: _13 * x + _23 * cmd.x1,
+ y1: _13 * y + _23 * cmd.y1,
+ x2: _13 * cmd.x + _23 * cmd.x1,
+ y2: _13 * cmd.y + _23 * cmd.y1
+ };
+ }
+
+ if (cmd.type === 'M') {
+ dx = Math.round(cmd.x - x);
+ dy = Math.round(cmd.y - y);
+ ops.push({name: 'dx', type: 'NUMBER', value: dx});
+ ops.push({name: 'dy', type: 'NUMBER', value: dy});
+ ops.push({name: 'rmoveto', type: 'OP', value: 21});
+ x = Math.round(cmd.x);
+ y = Math.round(cmd.y);
+ } else if (cmd.type === 'L') {
+ dx = Math.round(cmd.x - x);
+ dy = Math.round(cmd.y - y);
+ ops.push({name: 'dx', type: 'NUMBER', value: dx});
+ ops.push({name: 'dy', type: 'NUMBER', value: dy});
+ ops.push({name: 'rlineto', type: 'OP', value: 5});
+ x = Math.round(cmd.x);
+ y = Math.round(cmd.y);
+ } else if (cmd.type === 'C') {
+ var dx1 = Math.round(cmd.x1 - x);
+ var dy1 = Math.round(cmd.y1 - y);
+ var dx2 = Math.round(cmd.x2 - cmd.x1);
+ var dy2 = Math.round(cmd.y2 - cmd.y1);
+ dx = Math.round(cmd.x - cmd.x2);
+ dy = Math.round(cmd.y - cmd.y2);
+ ops.push({name: 'dx1', type: 'NUMBER', value: dx1});
+ ops.push({name: 'dy1', type: 'NUMBER', value: dy1});
+ ops.push({name: 'dx2', type: 'NUMBER', value: dx2});
+ ops.push({name: 'dy2', type: 'NUMBER', value: dy2});
+ ops.push({name: 'dx', type: 'NUMBER', value: dx});
+ ops.push({name: 'dy', type: 'NUMBER', value: dy});
+ ops.push({name: 'rrcurveto', type: 'OP', value: 8});
+ x = Math.round(cmd.x);
+ y = Math.round(cmd.y);
+ }
+
+ // Contours are closed automatically.
+
+ }
+
+ ops.push({name: 'endchar', type: 'OP', value: 14});
+ return ops;
+}
+
+function makeCharStringsIndex(glyphs) {
+ var t = new table.Table('CharStrings INDEX', [
+ {name: 'charStrings', type: 'INDEX', value: []}
+ ]);
+
+ for (var i = 0; i < glyphs.length; i += 1) {
+ var glyph = glyphs.get(i);
+ var ops = glyphToOps(glyph);
+ t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});
+ }
+
+ return t;
+}
+
+function makePrivateDict(attrs, strings) {
+ var t = new table.Table('Private DICT', [
+ {name: 'dict', type: 'DICT', value: {}}
+ ]);
+ t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
+ return t;
+}
+
+function makePrivateDictIndex(privateDict) {
+ var t = new table.Table('Private DICT INDEX', [
+ {name: 'privateDicts', type: 'INDEX', value: []}
+ ]);
+ t.privateDicts = [{name: 'privateDict_0', type: 'TABLE', value: privateDict}];
+ return t;
+}
+
+function makeCFFTable(glyphs, options) {
+ var t = new table.Table('CFF ', [
+ {name: 'header', type: 'TABLE'},
+ {name: 'nameIndex', type: 'TABLE'},
+ {name: 'topDictIndex', type: 'TABLE'},
+ {name: 'stringIndex', type: 'TABLE'},
+ {name: 'globalSubrIndex', type: 'TABLE'},
+ {name: 'charsets', type: 'TABLE'},
+ {name: 'charStringsIndex', type: 'TABLE'},
+ {name: 'privateDictIndex', type: 'TABLE'}
+ ]);
+
+ var fontScale = 1 / options.unitsPerEm;
+ // We use non-zero values for the offsets so that the DICT encodes them.
+ // This is important because the size of the Top DICT plays a role in offset calculation,
+ // and the size shouldn't change after we've written correct offsets.
+ var attrs = {
+ version: options.version,
+ fullName: options.fullName,
+ familyName: options.familyName,
+ weight: options.weightName,
+ fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
+ charset: 999,
+ encoding: 0,
+ charStrings: 999,
+ private: [0, 999]
+ };
+
+ var privateAttrs = {};
+
+ var glyphNames = [];
+ var glyph;
+
+ // Skip first glyph (.notdef)
+ for (var i = 1; i < glyphs.length; i += 1) {
+ glyph = glyphs.get(i);
+ glyphNames.push(glyph.name);
+ }
+
+ var strings = [];
+
+ t.header = makeHeader();
+ t.nameIndex = makeNameIndex([options.postScriptName]);
+ var topDict = makeTopDict(attrs, strings);
+ t.topDictIndex = makeTopDictIndex(topDict);
+ t.globalSubrIndex = makeGlobalSubrIndex();
+ t.charsets = makeCharsets(glyphNames, strings);
+ t.charStringsIndex = makeCharStringsIndex(glyphs);
+ var privateDict = makePrivateDict(privateAttrs, strings);
+ t.privateDictIndex = makePrivateDictIndex(privateDict);
+
+ // Needs to come at the end, to encode all custom strings used in the font.
+ t.stringIndex = makeStringIndex(strings);
+
+ var startOffset = t.header.sizeOf() +
+ t.nameIndex.sizeOf() +
+ t.topDictIndex.sizeOf() +
+ t.stringIndex.sizeOf() +
+ t.globalSubrIndex.sizeOf();
+ attrs.charset = startOffset;
+
+ // We use the CFF standard encoding; proper encoding will be handled in cmap.
+ attrs.encoding = 0;
+ attrs.charStrings = attrs.charset + t.charsets.sizeOf();
+ attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();
+
+ // Recreate the Top DICT INDEX with the correct offsets.
+ topDict = makeTopDict(attrs, strings);
+ t.topDictIndex = makeTopDictIndex(topDict);
+
+ return t;
+}
+
+exports.parse = parseCFFTable;
+exports.make = makeCFFTable;
+
+},{"../encoding":4,"../glyphset":7,"../parse":9,"../path":10,"../table":11}],13:[function(_dereq_,module,exports){
+// The `cmap` table stores the mappings from characters to glyphs.
+// https://www.microsoft.com/typography/OTSPEC/cmap.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the `cmap` table. This table stores the mappings from characters to glyphs.
+// There are many available formats, but we only support the Windows format 4.
+// This function returns a `CmapEncoding` object or null if no supported format could be found.
+function parseCmapTable(data, start) {
+ var i;
+ var cmap = {};
+ cmap.version = parse.getUShort(data, start);
+ check.argument(cmap.version === 0, 'cmap table version should be 0.');
+
+ // The cmap table can contain many sub-tables, each with their own format.
+ // We're only interested in a "platform 3" table. This is a Windows format.
+ cmap.numTables = parse.getUShort(data, start + 2);
+ var offset = -1;
+ for (i = 0; i < cmap.numTables; i += 1) {
+ var platformId = parse.getUShort(data, start + 4 + (i * 8));
+ var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
+ if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {
+ offset = parse.getULong(data, start + 4 + (i * 8) + 4);
+ break;
+ }
+ }
+
+ if (offset === -1) {
+ // There is no cmap table in the font that we support, so return null.
+ // This font will be marked as unsupported.
+ return null;
+ }
+
+ var p = new parse.Parser(data, start + offset);
+ cmap.format = p.parseUShort();
+ check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');
+
+ // Length in bytes of the sub-tables.
+ cmap.length = p.parseUShort();
+ cmap.language = p.parseUShort();
+
+ // segCount is stored x 2.
+ var segCount;
+ cmap.segCount = segCount = p.parseUShort() >> 1;
+
+ // Skip searchRange, entrySelector, rangeShift.
+ p.skip('uShort', 3);
+
+ // The "unrolled" mapping from character codes to glyph indices.
+ cmap.glyphIndexMap = {};
+
+ var endCountParser = new parse.Parser(data, start + offset + 14);
+ var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
+ var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
+ var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
+ var glyphIndexOffset = start + offset + 16 + segCount * 8;
+ for (i = 0; i < segCount - 1; i += 1) {
+ var glyphIndex;
+ var endCount = endCountParser.parseUShort();
+ var startCount = startCountParser.parseUShort();
+ var idDelta = idDeltaParser.parseShort();
+ var idRangeOffset = idRangeOffsetParser.parseUShort();
+ for (var c = startCount; c <= endCount; c += 1) {
+ if (idRangeOffset !== 0) {
+ // The idRangeOffset is relative to the current position in the idRangeOffset array.
+ // Take the current offset in the idRangeOffset array.
+ glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);
+
+ // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
+ glyphIndexOffset += idRangeOffset;
+
+ // Then add the character index of the current segment, multiplied by 2 for USHORTs.
+ glyphIndexOffset += (c - startCount) * 2;
+ glyphIndex = parse.getUShort(data, glyphIndexOffset);
+ if (glyphIndex !== 0) {
+ glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
+ }
+ } else {
+ glyphIndex = (c + idDelta) & 0xFFFF;
+ }
+
+ cmap.glyphIndexMap[c] = glyphIndex;
+ }
+ }
+
+ return cmap;
+}
+
+function addSegment(t, code, glyphIndex) {
+ t.segments.push({
+ end: code,
+ start: code,
+ delta: -(code - glyphIndex),
+ offset: 0
+ });
+}
+
+function addTerminatorSegment(t) {
+ t.segments.push({
+ end: 0xFFFF,
+ start: 0xFFFF,
+ delta: 1,
+ offset: 0
+ });
+}
+
+function makeCmapTable(glyphs) {
+ var i;
+ var t = new table.Table('cmap', [
+ {name: 'version', type: 'USHORT', value: 0},
+ {name: 'numTables', type: 'USHORT', value: 1},
+ {name: 'platformID', type: 'USHORT', value: 3},
+ {name: 'encodingID', type: 'USHORT', value: 1},
+ {name: 'offset', type: 'ULONG', value: 12},
+ {name: 'format', type: 'USHORT', value: 4},
+ {name: 'length', type: 'USHORT', value: 0},
+ {name: 'language', type: 'USHORT', value: 0},
+ {name: 'segCountX2', type: 'USHORT', value: 0},
+ {name: 'searchRange', type: 'USHORT', value: 0},
+ {name: 'entrySelector', type: 'USHORT', value: 0},
+ {name: 'rangeShift', type: 'USHORT', value: 0}
+ ]);
+
+ t.segments = [];
+ for (i = 0; i < glyphs.length; i += 1) {
+ var glyph = glyphs.get(i);
+ for (var j = 0; j < glyph.unicodes.length; j += 1) {
+ addSegment(t, glyph.unicodes[j], i);
+ }
+
+ t.segments = t.segments.sort(function(a, b) {
+ return a.start - b.start;
+ });
+ }
+
+ addTerminatorSegment(t);
+
+ var segCount;
+ segCount = t.segments.length;
+ t.segCountX2 = segCount * 2;
+ t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;
+ t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
+ t.rangeShift = t.segCountX2 - t.searchRange;
+
+ // Set up parallel segment arrays.
+ var endCounts = [];
+ var startCounts = [];
+ var idDeltas = [];
+ var idRangeOffsets = [];
+ var glyphIds = [];
+
+ for (i = 0; i < segCount; i += 1) {
+ var segment = t.segments[i];
+ endCounts = endCounts.concat({name: 'end_' + i, type: 'USHORT', value: segment.end});
+ startCounts = startCounts.concat({name: 'start_' + i, type: 'USHORT', value: segment.start});
+ idDeltas = idDeltas.concat({name: 'idDelta_' + i, type: 'SHORT', value: segment.delta});
+ idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i, type: 'USHORT', value: segment.offset});
+ if (segment.glyphId !== undefined) {
+ glyphIds = glyphIds.concat({name: 'glyph_' + i, type: 'USHORT', value: segment.glyphId});
+ }
+ }
+
+ t.fields = t.fields.concat(endCounts);
+ t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});
+ t.fields = t.fields.concat(startCounts);
+ t.fields = t.fields.concat(idDeltas);
+ t.fields = t.fields.concat(idRangeOffsets);
+ t.fields = t.fields.concat(glyphIds);
+
+ t.length = 14 + // Subtable header
+ endCounts.length * 2 +
+ 2 + // reservedPad
+ startCounts.length * 2 +
+ idDeltas.length * 2 +
+ idRangeOffsets.length * 2 +
+ glyphIds.length * 2;
+
+ return t;
+}
+
+exports.parse = parseCmapTable;
+exports.make = makeCmapTable;
+
+},{"../check":2,"../parse":9,"../table":11}],14:[function(_dereq_,module,exports){
+// The `glyf` table describes the glyphs in TrueType outline format.
+// http://www.microsoft.com/typography/otspec/glyf.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var glyphset = _dereq_('../glyphset');
+var parse = _dereq_('../parse');
+var path = _dereq_('../path');
+
+// Parse the coordinate data for a glyph.
+function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {
+ var v;
+ if ((flag & shortVectorBitMask) > 0) {
+ // The coordinate is 1 byte long.
+ v = p.parseByte();
+ // The `same` bit is re-used for short values to signify the sign of the value.
+ if ((flag & sameBitMask) === 0) {
+ v = -v;
+ }
+
+ v = previousValue + v;
+ } else {
+ // The coordinate is 2 bytes long.
+ // If the `same` bit is set, the coordinate is the same as the previous coordinate.
+ if ((flag & sameBitMask) > 0) {
+ v = previousValue;
+ } else {
+ // Parse the coordinate as a signed 16-bit delta value.
+ v = previousValue + p.parseShort();
+ }
+ }
+
+ return v;
+}
+
+// Parse a TrueType glyph.
+function parseGlyph(glyph, data, start) {
+ var p = new parse.Parser(data, start);
+ glyph.numberOfContours = p.parseShort();
+ glyph.xMin = p.parseShort();
+ glyph.yMin = p.parseShort();
+ glyph.xMax = p.parseShort();
+ glyph.yMax = p.parseShort();
+ var flags;
+ var flag;
+ if (glyph.numberOfContours > 0) {
+ var i;
+ // This glyph is not a composite.
+ var endPointIndices = glyph.endPointIndices = [];
+ for (i = 0; i < glyph.numberOfContours; i += 1) {
+ endPointIndices.push(p.parseUShort());
+ }
+
+ glyph.instructionLength = p.parseUShort();
+ glyph.instructions = [];
+ for (i = 0; i < glyph.instructionLength; i += 1) {
+ glyph.instructions.push(p.parseByte());
+ }
+
+ var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
+ flags = [];
+ for (i = 0; i < numberOfCoordinates; i += 1) {
+ flag = p.parseByte();
+ flags.push(flag);
+ // If bit 3 is set, we repeat this flag n times, where n is the next byte.
+ if ((flag & 8) > 0) {
+ var repeatCount = p.parseByte();
+ for (var j = 0; j < repeatCount; j += 1) {
+ flags.push(flag);
+ i += 1;
+ }
+ }
+ }
+
+ check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
+
+ if (endPointIndices.length > 0) {
+ var points = [];
+ var point;
+ // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
+ if (numberOfCoordinates > 0) {
+ for (i = 0; i < numberOfCoordinates; i += 1) {
+ flag = flags[i];
+ point = {};
+ point.onCurve = !!(flag & 1);
+ point.lastPointOfContour = endPointIndices.indexOf(i) >= 0;
+ points.push(point);
+ }
+
+ var px = 0;
+ for (i = 0; i < numberOfCoordinates; i += 1) {
+ flag = flags[i];
+ point = points[i];
+ point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
+ px = point.x;
+ }
+
+ var py = 0;
+ for (i = 0; i < numberOfCoordinates; i += 1) {
+ flag = flags[i];
+ point = points[i];
+ point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
+ py = point.y;
+ }
+ }
+
+ glyph.points = points;
+ } else {
+ glyph.points = [];
+ }
+ } else if (glyph.numberOfContours === 0) {
+ glyph.points = [];
+ } else {
+ glyph.isComposite = true;
+ glyph.points = [];
+ glyph.components = [];
+ var moreComponents = true;
+ while (moreComponents) {
+ flags = p.parseUShort();
+ var component = {
+ glyphIndex: p.parseUShort(),
+ xScale: 1,
+ scale01: 0,
+ scale10: 0,
+ yScale: 1,
+ dx: 0,
+ dy: 0
+ };
+ if ((flags & 1) > 0) {
+ // The arguments are words
+ component.dx = p.parseShort();
+ component.dy = p.parseShort();
+ } else {
+ // The arguments are bytes
+ component.dx = p.parseChar();
+ component.dy = p.parseChar();
+ }
+
+ if ((flags & 8) > 0) {
+ // We have a scale
+ component.xScale = component.yScale = p.parseF2Dot14();
+ } else if ((flags & 64) > 0) {
+ // We have an X / Y scale
+ component.xScale = p.parseF2Dot14();
+ component.yScale = p.parseF2Dot14();
+ } else if ((flags & 128) > 0) {
+ // We have a 2x2 transformation
+ component.xScale = p.parseF2Dot14();
+ component.scale01 = p.parseF2Dot14();
+ component.scale10 = p.parseF2Dot14();
+ component.yScale = p.parseF2Dot14();
+ }
+
+ glyph.components.push(component);
+ moreComponents = !!(flags & 32);
+ }
+ }
+}
+
+// Transform an array of points and return a new array.
+function transformPoints(points, transform) {
+ var newPoints = [];
+ for (var i = 0; i < points.length; i += 1) {
+ var pt = points[i];
+ var newPt = {
+ x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
+ y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
+ onCurve: pt.onCurve,
+ lastPointOfContour: pt.lastPointOfContour
+ };
+ newPoints.push(newPt);
+ }
+
+ return newPoints;
+}
+
+function getContours(points) {
+ var contours = [];
+ var currentContour = [];
+ for (var i = 0; i < points.length; i += 1) {
+ var pt = points[i];
+ currentContour.push(pt);
+ if (pt.lastPointOfContour) {
+ contours.push(currentContour);
+ currentContour = [];
+ }
+ }
+
+ check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
+ return contours;
+}
+
+// Convert the TrueType glyph outline to a Path.
+function getPath(points) {
+ var p = new path.Path();
+ if (!points) {
+ return p;
+ }
+
+ var contours = getContours(points);
+ for (var i = 0; i < contours.length; i += 1) {
+ var contour = contours[i];
+ var firstPt = contour[0];
+ var lastPt = contour[contour.length - 1];
+ var curvePt;
+ var realFirstPoint;
+ if (firstPt.onCurve) {
+ curvePt = null;
+ // The first point will be consumed by the moveTo command,
+ // so skip it in the loop.
+ realFirstPoint = true;
+ } else {
+ if (lastPt.onCurve) {
+ // If the first point is off-curve and the last point is on-curve,
+ // start at the last point.
+ firstPt = lastPt;
+ } else {
+ // If both first and last points are off-curve, start at their middle.
+ firstPt = { x: (firstPt.x + lastPt.x) / 2, y: (firstPt.y + lastPt.y) / 2 };
+ }
+
+ curvePt = firstPt;
+ // The first point is synthesized, so don't skip the real first point.
+ realFirstPoint = false;
+ }
+
+ p.moveTo(firstPt.x, firstPt.y);
+
+ for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {
+ var pt = contour[j];
+ var prevPt = j === 0 ? firstPt : contour[j - 1];
+ if (prevPt.onCurve && pt.onCurve) {
+ // This is a straight line.
+ p.lineTo(pt.x, pt.y);
+ } else if (prevPt.onCurve && !pt.onCurve) {
+ curvePt = pt;
+ } else if (!prevPt.onCurve && !pt.onCurve) {
+ var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };
+ p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);
+ curvePt = pt;
+ } else if (!prevPt.onCurve && pt.onCurve) {
+ // Previous point off-curve, this point on-curve.
+ p.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);
+ curvePt = null;
+ } else {
+ throw new Error('Invalid state.');
+ }
+ }
+
+ if (firstPt !== lastPt) {
+ // Connect the last and first points
+ if (curvePt) {
+ p.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);
+ } else {
+ p.lineTo(firstPt.x, firstPt.y);
+ }
+ }
+ }
+
+ p.closePath();
+ return p;
+}
+
+function buildPath(glyphs, glyph) {
+ if (glyph.isComposite) {
+ for (var j = 0; j < glyph.components.length; j += 1) {
+ var component = glyph.components[j];
+ var componentGlyph = glyphs.get(component.glyphIndex);
+ if (componentGlyph.points) {
+ var transformedPoints = transformPoints(componentGlyph.points, component);
+ glyph.points = glyph.points.concat(transformedPoints);
+ }
+ }
+ }
+
+ return getPath(glyph.points);
+}
+
+// Parse all the glyphs according to the offsets from the `loca` table.
+function parseGlyfTable(data, start, loca, font) {
+ var glyphs = new glyphset.GlyphSet(font);
+ var i;
+
+ // The last element of the loca table is invalid.
+ for (i = 0; i < loca.length - 1; i += 1) {
+ var offset = loca[i];
+ var nextOffset = loca[i + 1];
+ if (offset !== nextOffset) {
+ glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));
+ } else {
+ glyphs.push(i, glyphset.glyphLoader(font, i));
+ }
+ }
+
+ return glyphs;
+}
+
+exports.parse = parseGlyfTable;
+
+},{"../check":2,"../glyphset":7,"../parse":9,"../path":10}],15:[function(_dereq_,module,exports){
+// The `GPOS` table contains kerning pairs, among other things.
+// https://www.microsoft.com/typography/OTSPEC/gpos.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var parse = _dereq_('../parse');
+
+// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables.
+// These lists are unused by now, this function is just the basis for a real parsing.
+function parseTaggedListTable(data, start) {
+ var p = new parse.Parser(data, start);
+ var n = p.parseUShort();
+ var list = [];
+ for (var i = 0; i < n; i++) {
+ list[p.parseTag()] = { offset: p.parseUShort() };
+ }
+
+ return list;
+}
+
+// Parse a coverage table in a GSUB, GPOS or GDEF table.
+// Format 1 is a simple list of glyph ids,
+// Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea.
+function parseCoverageTable(data, start) {
+ var p = new parse.Parser(data, start);
+ var format = p.parseUShort();
+ var count = p.parseUShort();
+ if (format === 1) {
+ return p.parseUShortList(count);
+ }
+ else if (format === 2) {
+ var coverage = [];
+ for (; count--;) {
+ var begin = p.parseUShort();
+ var end = p.parseUShort();
+ var index = p.parseUShort();
+ for (var i = begin; i <= end; i++) {
+ coverage[index++] = i;
+ }
+ }
+
+ return coverage;
+ }
+}
+
+// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
+// Returns a function that gets a class value from a glyph ID.
+function parseClassDefTable(data, start) {
+ var p = new parse.Parser(data, start);
+ var format = p.parseUShort();
+ if (format === 1) {
+ // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.
+ var startGlyph = p.parseUShort();
+ var glyphCount = p.parseUShort();
+ var classes = p.parseUShortList(glyphCount);
+ return function(glyphID) {
+ return classes[glyphID - startGlyph] || 0;
+ };
+ }
+ else if (format === 2) {
+ // Format 2 defines multiple groups of glyph indices that belong to the same class.
+ var rangeCount = p.parseUShort();
+ var startGlyphs = [];
+ var endGlyphs = [];
+ var classValues = [];
+ for (var i = 0; i < rangeCount; i++) {
+ startGlyphs[i] = p.parseUShort();
+ endGlyphs[i] = p.parseUShort();
+ classValues[i] = p.parseUShort();
+ }
+
+ return function(glyphID) {
+ var l = 0;
+ var r = startGlyphs.length - 1;
+ while (l < r) {
+ var c = (l + r + 1) >> 1;
+ if (glyphID < startGlyphs[c]) {
+ r = c - 1;
+ } else {
+ l = c;
+ }
+ }
+
+ if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {
+ return classValues[l] || 0;
+ }
+
+ return 0;
+ };
+ }
+}
+
+// Parse a pair adjustment positioning subtable, format 1 or format 2
+// The subtable is returned in the form of a lookup function.
+function parsePairPosSubTable(data, start) {
+ var p = new parse.Parser(data, start);
+ // This part is common to format 1 and format 2 subtables
+ var format = p.parseUShort();
+ var coverageOffset = p.parseUShort();
+ var coverage = parseCoverageTable(data, start + coverageOffset);
+ // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph
+ // Only valueFormat1=4 and valueFormat2=0 is supported.
+ var valueFormat1 = p.parseUShort();
+ var valueFormat2 = p.parseUShort();
+ var value1;
+ var value2;
+ if (valueFormat1 !== 4 || valueFormat2 !== 0) return;
+ var sharedPairSets = {};
+ if (format === 1) {
+ // Pair Positioning Adjustment: Format 1
+ var pairSetCount = p.parseUShort();
+ var pairSet = [];
+ // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
+ var pairSetOffsets = p.parseOffset16List(pairSetCount);
+ for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
+ var pairSetOffset = pairSetOffsets[firstGlyph];
+ var sharedPairSet = sharedPairSets[pairSetOffset];
+ if (!sharedPairSet) {
+ // Parse a pairset table in a pair adjustment subtable format 1
+ sharedPairSet = {};
+ p.relativeOffset = pairSetOffset;
+ var pairValueCount = p.parseUShort();
+ for (; pairValueCount--;) {
+ var secondGlyph = p.parseUShort();
+ if (valueFormat1) value1 = p.parseShort();
+ if (valueFormat2) value2 = p.parseShort();
+ // We only support valueFormat1 = 4 and valueFormat2 = 0,
+ // so value1 is the XAdvance and value2 is empty.
+ sharedPairSet[secondGlyph] = value1;
+ }
+ }
+
+ pairSet[coverage[firstGlyph]] = sharedPairSet;
+ }
+
+ return function(leftGlyph, rightGlyph) {
+ var pairs = pairSet[leftGlyph];
+ if (pairs) return pairs[rightGlyph];
+ };
+ }
+ else if (format === 2) {
+ // Pair Positioning Adjustment: Format 2
+ var classDef1Offset = p.parseUShort();
+ var classDef2Offset = p.parseUShort();
+ var class1Count = p.parseUShort();
+ var class2Count = p.parseUShort();
+ var getClass1 = parseClassDefTable(data, start + classDef1Offset);
+ var getClass2 = parseClassDefTable(data, start + classDef2Offset);
+
+ // Parse kerning values by class pair.
+ var kerningMatrix = [];
+ for (var i = 0; i < class1Count; i++) {
+ var kerningRow = kerningMatrix[i] = [];
+ for (var j = 0; j < class2Count; j++) {
+ if (valueFormat1) value1 = p.parseShort();
+ if (valueFormat2) value2 = p.parseShort();
+ // We only support valueFormat1 = 4 and valueFormat2 = 0,
+ // so value1 is the XAdvance and value2 is empty.
+ kerningRow[j] = value1;
+ }
+ }
+
+ // Convert coverage list to a hash
+ var covered = {};
+ for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;
+
+ // Get the kerning value for a specific glyph pair.
+ return function(leftGlyph, rightGlyph) {
+ if (!covered[leftGlyph]) return;
+ var class1 = getClass1(leftGlyph);
+ var class2 = getClass2(rightGlyph);
+ var kerningRow = kerningMatrix[class1];
+
+ if (kerningRow) {
+ return kerningRow[class2];
+ }
+ };
+ }
+}
+
+// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables).
+function parseLookupTable(data, start) {
+ var p = new parse.Parser(data, start);
+ var lookupType = p.parseUShort();
+ var lookupFlag = p.parseUShort();
+ var useMarkFilteringSet = lookupFlag & 0x10;
+ var subTableCount = p.parseUShort();
+ var subTableOffsets = p.parseOffset16List(subTableCount);
+ var table = {
+ lookupType: lookupType,
+ lookupFlag: lookupFlag,
+ markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1
+ };
+ // LookupType 2, Pair adjustment
+ if (lookupType === 2) {
+ var subtables = [];
+ for (var i = 0; i < subTableCount; i++) {
+ subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));
+ }
+ // Return a function which finds the kerning values in the subtables.
+ table.getKerningValue = function(leftGlyph, rightGlyph) {
+ for (var i = subtables.length; i--;) {
+ var value = subtables[i](leftGlyph, rightGlyph);
+ if (value !== undefined) return value;
+ }
+
+ return 0;
+ };
+ }
+
+ return table;
+}
+
+// Parse the `GPOS` table which contains, among other things, kerning pairs.
+// https://www.microsoft.com/typography/OTSPEC/gpos.htm
+function parseGposTable(data, start, font) {
+ var p = new parse.Parser(data, start);
+ var tableVersion = p.parseFixed();
+ check.argument(tableVersion === 1, 'Unsupported GPOS table version.');
+
+ // ScriptList and FeatureList - ignored for now
+ parseTaggedListTable(data, start + p.parseUShort());
+ // 'kern' is the feature we are looking for.
+ parseTaggedListTable(data, start + p.parseUShort());
+
+ // LookupList
+ var lookupListOffset = p.parseUShort();
+ p.relativeOffset = lookupListOffset;
+ var lookupCount = p.parseUShort();
+ var lookupTableOffsets = p.parseOffset16List(lookupCount);
+ var lookupListAbsoluteOffset = start + lookupListOffset;
+ for (var i = 0; i < lookupCount; i++) {
+ var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
+ if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;
+ }
+}
+
+exports.parse = parseGposTable;
+
+},{"../check":2,"../parse":9}],16:[function(_dereq_,module,exports){
+// The `head` table contains global information about the font.
+// https://www.microsoft.com/typography/OTSPEC/head.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the header `head` table
+function parseHeadTable(data, start) {
+ var head = {};
+ var p = new parse.Parser(data, start);
+ head.version = p.parseVersion();
+ head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
+ head.checkSumAdjustment = p.parseULong();
+ head.magicNumber = p.parseULong();
+ check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');
+ head.flags = p.parseUShort();
+ head.unitsPerEm = p.parseUShort();
+ head.created = p.parseLongDateTime();
+ head.modified = p.parseLongDateTime();
+ head.xMin = p.parseShort();
+ head.yMin = p.parseShort();
+ head.xMax = p.parseShort();
+ head.yMax = p.parseShort();
+ head.macStyle = p.parseUShort();
+ head.lowestRecPPEM = p.parseUShort();
+ head.fontDirectionHint = p.parseShort();
+ head.indexToLocFormat = p.parseShort(); // 50
+ head.glyphDataFormat = p.parseShort();
+ return head;
+}
+
+function makeHeadTable(options) {
+ return new table.Table('head', [
+ {name: 'version', type: 'FIXED', value: 0x00010000},
+ {name: 'fontRevision', type: 'FIXED', value: 0x00010000},
+ {name: 'checkSumAdjustment', type: 'ULONG', value: 0},
+ {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},
+ {name: 'flags', type: 'USHORT', value: 0},
+ {name: 'unitsPerEm', type: 'USHORT', value: 1000},
+ {name: 'created', type: 'LONGDATETIME', value: 0},
+ {name: 'modified', type: 'LONGDATETIME', value: 0},
+ {name: 'xMin', type: 'SHORT', value: 0},
+ {name: 'yMin', type: 'SHORT', value: 0},
+ {name: 'xMax', type: 'SHORT', value: 0},
+ {name: 'yMax', type: 'SHORT', value: 0},
+ {name: 'macStyle', type: 'USHORT', value: 0},
+ {name: 'lowestRecPPEM', type: 'USHORT', value: 0},
+ {name: 'fontDirectionHint', type: 'SHORT', value: 2},
+ {name: 'indexToLocFormat', type: 'SHORT', value: 0},
+ {name: 'glyphDataFormat', type: 'SHORT', value: 0}
+ ], options);
+}
+
+exports.parse = parseHeadTable;
+exports.make = makeHeadTable;
+
+},{"../check":2,"../parse":9,"../table":11}],17:[function(_dereq_,module,exports){
+// The `hhea` table contains information for horizontal layout.
+// https://www.microsoft.com/typography/OTSPEC/hhea.htm
+
+'use strict';
+
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the horizontal header `hhea` table
+function parseHheaTable(data, start) {
+ var hhea = {};
+ var p = new parse.Parser(data, start);
+ hhea.version = p.parseVersion();
+ hhea.ascender = p.parseShort();
+ hhea.descender = p.parseShort();
+ hhea.lineGap = p.parseShort();
+ hhea.advanceWidthMax = p.parseUShort();
+ hhea.minLeftSideBearing = p.parseShort();
+ hhea.minRightSideBearing = p.parseShort();
+ hhea.xMaxExtent = p.parseShort();
+ hhea.caretSlopeRise = p.parseShort();
+ hhea.caretSlopeRun = p.parseShort();
+ hhea.caretOffset = p.parseShort();
+ p.relativeOffset += 8;
+ hhea.metricDataFormat = p.parseShort();
+ hhea.numberOfHMetrics = p.parseUShort();
+ return hhea;
+}
+
+function makeHheaTable(options) {
+ return new table.Table('hhea', [
+ {name: 'version', type: 'FIXED', value: 0x00010000},
+ {name: 'ascender', type: 'FWORD', value: 0},
+ {name: 'descender', type: 'FWORD', value: 0},
+ {name: 'lineGap', type: 'FWORD', value: 0},
+ {name: 'advanceWidthMax', type: 'UFWORD', value: 0},
+ {name: 'minLeftSideBearing', type: 'FWORD', value: 0},
+ {name: 'minRightSideBearing', type: 'FWORD', value: 0},
+ {name: 'xMaxExtent', type: 'FWORD', value: 0},
+ {name: 'caretSlopeRise', type: 'SHORT', value: 1},
+ {name: 'caretSlopeRun', type: 'SHORT', value: 0},
+ {name: 'caretOffset', type: 'SHORT', value: 0},
+ {name: 'reserved1', type: 'SHORT', value: 0},
+ {name: 'reserved2', type: 'SHORT', value: 0},
+ {name: 'reserved3', type: 'SHORT', value: 0},
+ {name: 'reserved4', type: 'SHORT', value: 0},
+ {name: 'metricDataFormat', type: 'SHORT', value: 0},
+ {name: 'numberOfHMetrics', type: 'USHORT', value: 0}
+ ], options);
+}
+
+exports.parse = parseHheaTable;
+exports.make = makeHheaTable;
+
+},{"../parse":9,"../table":11}],18:[function(_dereq_,module,exports){
+// The `hmtx` table contains the horizontal metrics for all glyphs.
+// https://www.microsoft.com/typography/OTSPEC/hmtx.htm
+
+'use strict';
+
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.
+// This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.
+function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
+ var advanceWidth;
+ var leftSideBearing;
+ var p = new parse.Parser(data, start);
+ for (var i = 0; i < numGlyphs; i += 1) {
+ // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
+ if (i < numMetrics) {
+ advanceWidth = p.parseUShort();
+ leftSideBearing = p.parseShort();
+ }
+
+ var glyph = glyphs.get(i);
+ glyph.advanceWidth = advanceWidth;
+ glyph.leftSideBearing = leftSideBearing;
+ }
+}
+
+function makeHmtxTable(glyphs) {
+ var t = new table.Table('hmtx', []);
+ for (var i = 0; i < glyphs.length; i += 1) {
+ var glyph = glyphs.get(i);
+ var advanceWidth = glyph.advanceWidth || 0;
+ var leftSideBearing = glyph.leftSideBearing || 0;
+ t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});
+ t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});
+ }
+
+ return t;
+}
+
+exports.parse = parseHmtxTable;
+exports.make = makeHmtxTable;
+
+},{"../parse":9,"../table":11}],19:[function(_dereq_,module,exports){
+// The `kern` table contains kerning pairs.
+// Note that some fonts use the GPOS OpenType layout table to specify kerning.
+// https://www.microsoft.com/typography/OTSPEC/kern.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var parse = _dereq_('../parse');
+
+// Parse the `kern` table which contains kerning pairs.
+function parseKernTable(data, start) {
+ var pairs = {};
+ var p = new parse.Parser(data, start);
+ var tableVersion = p.parseUShort();
+ check.argument(tableVersion === 0, 'Unsupported kern table version.');
+ // Skip nTables.
+ p.skip('uShort', 1);
+ var subTableVersion = p.parseUShort();
+ check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');
+ // Skip subTableLength, subTableCoverage
+ p.skip('uShort', 2);
+ var nPairs = p.parseUShort();
+ // Skip searchRange, entrySelector, rangeShift.
+ p.skip('uShort', 3);
+ for (var i = 0; i < nPairs; i += 1) {
+ var leftIndex = p.parseUShort();
+ var rightIndex = p.parseUShort();
+ var value = p.parseShort();
+ pairs[leftIndex + ',' + rightIndex] = value;
+ }
+
+ return pairs;
+}
+
+exports.parse = parseKernTable;
+
+},{"../check":2,"../parse":9}],20:[function(_dereq_,module,exports){
+// The `loca` table stores the offsets to the locations of the glyphs in the font.
+// https://www.microsoft.com/typography/OTSPEC/loca.htm
+
+'use strict';
+
+var parse = _dereq_('../parse');
+
+// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,
+// relative to the beginning of the glyphData table.
+// The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)
+// The loca table has two versions: a short version where offsets are stored as uShorts, and a long
+// version where offsets are stored as uLongs. The `head` table specifies which version to use
+// (under indexToLocFormat).
+function parseLocaTable(data, start, numGlyphs, shortVersion) {
+ var p = new parse.Parser(data, start);
+ var parseFn = shortVersion ? p.parseUShort : p.parseULong;
+ // There is an extra entry after the last index element to compute the length of the last glyph.
+ // That's why we use numGlyphs + 1.
+ var glyphOffsets = [];
+ for (var i = 0; i < numGlyphs + 1; i += 1) {
+ var glyphOffset = parseFn.call(p);
+ if (shortVersion) {
+ // The short table version stores the actual offset divided by 2.
+ glyphOffset *= 2;
+ }
+
+ glyphOffsets.push(glyphOffset);
+ }
+
+ return glyphOffsets;
+}
+
+exports.parse = parseLocaTable;
+
+},{"../parse":9}],21:[function(_dereq_,module,exports){
+// The `maxp` table establishes the memory requirements for the font.
+// We need it just to get the number of glyphs in the font.
+// https://www.microsoft.com/typography/OTSPEC/maxp.htm
+
+'use strict';
+
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the maximum profile `maxp` table.
+function parseMaxpTable(data, start) {
+ var maxp = {};
+ var p = new parse.Parser(data, start);
+ maxp.version = p.parseVersion();
+ maxp.numGlyphs = p.parseUShort();
+ if (maxp.version === 1.0) {
+ maxp.maxPoints = p.parseUShort();
+ maxp.maxContours = p.parseUShort();
+ maxp.maxCompositePoints = p.parseUShort();
+ maxp.maxCompositeContours = p.parseUShort();
+ maxp.maxZones = p.parseUShort();
+ maxp.maxTwilightPoints = p.parseUShort();
+ maxp.maxStorage = p.parseUShort();
+ maxp.maxFunctionDefs = p.parseUShort();
+ maxp.maxInstructionDefs = p.parseUShort();
+ maxp.maxStackElements = p.parseUShort();
+ maxp.maxSizeOfInstructions = p.parseUShort();
+ maxp.maxComponentElements = p.parseUShort();
+ maxp.maxComponentDepth = p.parseUShort();
+ }
+
+ return maxp;
+}
+
+function makeMaxpTable(numGlyphs) {
+ return new table.Table('maxp', [
+ {name: 'version', type: 'FIXED', value: 0x00005000},
+ {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}
+ ]);
+}
+
+exports.parse = parseMaxpTable;
+exports.make = makeMaxpTable;
+
+},{"../parse":9,"../table":11}],22:[function(_dereq_,module,exports){
+// The `name` naming table.
+// https://www.microsoft.com/typography/OTSPEC/name.htm
+
+'use strict';
+
+var encode = _dereq_('../types').encode;
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// NameIDs for the name table.
+var nameTableNames = [
+ 'copyright', // 0
+ 'fontFamily', // 1
+ 'fontSubfamily', // 2
+ 'uniqueID', // 3
+ 'fullName', // 4
+ 'version', // 5
+ 'postScriptName', // 6
+ 'trademark', // 7
+ 'manufacturer', // 8
+ 'designer', // 9
+ 'description', // 10
+ 'manufacturerURL', // 11
+ 'designerURL', // 12
+ 'licence', // 13
+ 'licenceURL', // 14
+ 'reserved', // 15
+ 'preferredFamily', // 16
+ 'preferredSubfamily', // 17
+ 'compatibleFullName', // 18
+ 'sampleText', // 19
+ 'postScriptFindFontName', // 20
+ 'wwsFamily', // 21
+ 'wwsSubfamily' // 22
+];
+
+// Parse the naming `name` table
+// Only Windows Unicode English names are supported.
+// Format 1 additional fields are not supported
+function parseNameTable(data, start) {
+ var name = {};
+ var p = new parse.Parser(data, start);
+ name.format = p.parseUShort();
+ var count = p.parseUShort();
+ var stringOffset = p.offset + p.parseUShort();
+ var unknownCount = 0;
+ for (var i = 0; i < count; i++) {
+ var platformID = p.parseUShort();
+ var encodingID = p.parseUShort();
+ var languageID = p.parseUShort();
+ var nameID = p.parseUShort();
+ var property = nameTableNames[nameID];
+ var byteLength = p.parseUShort();
+ var offset = p.parseUShort();
+ // platformID - encodingID - languageID standard combinations :
+ // 1 - 0 - 0 : Macintosh, Roman, English
+ // 3 - 1 - 0x409 : Windows, Unicode BMP (UCS-2), en-US
+ if (platformID === 3 && encodingID === 1 && languageID === 0x409) {
+ var codePoints = [];
+ var length = byteLength / 2;
+ for (var j = 0; j < length; j++, offset += 2) {
+ codePoints[j] = parse.getShort(data, stringOffset + offset);
+ }
+
+ var str = String.fromCharCode.apply(null, codePoints);
+ if (property) {
+ name[property] = str;
+ }
+ else {
+ unknownCount++;
+ name['unknown' + unknownCount] = str;
+ }
+ }
+
+ }
+
+ if (name.format === 1) {
+ name.langTagCount = p.parseUShort();
+ }
+
+ return name;
+}
+
+function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {
+ return new table.Table('NameRecord', [
+ {name: 'platformID', type: 'USHORT', value: platformID},
+ {name: 'encodingID', type: 'USHORT', value: encodingID},
+ {name: 'languageID', type: 'USHORT', value: languageID},
+ {name: 'nameID', type: 'USHORT', value: nameID},
+ {name: 'length', type: 'USHORT', value: length},
+ {name: 'offset', type: 'USHORT', value: offset}
+ ]);
+}
+
+function addMacintoshNameRecord(t, recordID, s, offset) {
+ // Macintosh, Roman, English
+ var stringBytes = encode.STRING(s);
+ t.records.push(makeNameRecord(1, 0, 0, recordID, stringBytes.length, offset));
+ t.strings.push(stringBytes);
+ offset += stringBytes.length;
+ return offset;
+}
+
+function addWindowsNameRecord(t, recordID, s, offset) {
+ // Windows, Unicode BMP (UCS-2), US English
+ var utf16Bytes = encode.UTF16(s);
+ t.records.push(makeNameRecord(3, 1, 0x0409, recordID, utf16Bytes.length, offset));
+ t.strings.push(utf16Bytes);
+ offset += utf16Bytes.length;
+ return offset;
+}
+
+function makeNameTable(options) {
+ var t = new table.Table('name', [
+ {name: 'format', type: 'USHORT', value: 0},
+ {name: 'count', type: 'USHORT', value: 0},
+ {name: 'stringOffset', type: 'USHORT', value: 0}
+ ]);
+ t.records = [];
+ t.strings = [];
+ var offset = 0;
+ var i;
+ var s;
+ // Add Macintosh records first
+ for (i = 0; i < nameTableNames.length; i += 1) {
+ if (options[nameTableNames[i]] !== undefined) {
+ s = options[nameTableNames[i]];
+ offset = addMacintoshNameRecord(t, i, s, offset);
+ }
+ }
+ // Then add Windows records
+ for (i = 0; i < nameTableNames.length; i += 1) {
+ if (options[nameTableNames[i]] !== undefined) {
+ s = options[nameTableNames[i]];
+ offset = addWindowsNameRecord(t, i, s, offset);
+ }
+ }
+
+ t.count = t.records.length;
+ t.stringOffset = 6 + t.count * 12;
+ for (i = 0; i < t.records.length; i += 1) {
+ t.fields.push({name: 'record_' + i, type: 'TABLE', value: t.records[i]});
+ }
+
+ for (i = 0; i < t.strings.length; i += 1) {
+ t.fields.push({name: 'string_' + i, type: 'LITERAL', value: t.strings[i]});
+ }
+
+ return t;
+}
+
+exports.parse = parseNameTable;
+exports.make = makeNameTable;
+
+},{"../parse":9,"../table":11,"../types":26}],23:[function(_dereq_,module,exports){
+// The `OS/2` table contains metrics required in OpenType fonts.
+// https://www.microsoft.com/typography/OTSPEC/os2.htm
+
+'use strict';
+
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+var unicodeRanges = [
+ {begin: 0x0000, end: 0x007F}, // Basic Latin
+ {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement
+ {begin: 0x0100, end: 0x017F}, // Latin Extended-A
+ {begin: 0x0180, end: 0x024F}, // Latin Extended-B
+ {begin: 0x0250, end: 0x02AF}, // IPA Extensions
+ {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters
+ {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks
+ {begin: 0x0370, end: 0x03FF}, // Greek and Coptic
+ {begin: 0x2C80, end: 0x2CFF}, // Coptic
+ {begin: 0x0400, end: 0x04FF}, // Cyrillic
+ {begin: 0x0530, end: 0x058F}, // Armenian
+ {begin: 0x0590, end: 0x05FF}, // Hebrew
+ {begin: 0xA500, end: 0xA63F}, // Vai
+ {begin: 0x0600, end: 0x06FF}, // Arabic
+ {begin: 0x07C0, end: 0x07FF}, // NKo
+ {begin: 0x0900, end: 0x097F}, // Devanagari
+ {begin: 0x0980, end: 0x09FF}, // Bengali
+ {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi
+ {begin: 0x0A80, end: 0x0AFF}, // Gujarati
+ {begin: 0x0B00, end: 0x0B7F}, // Oriya
+ {begin: 0x0B80, end: 0x0BFF}, // Tamil
+ {begin: 0x0C00, end: 0x0C7F}, // Telugu
+ {begin: 0x0C80, end: 0x0CFF}, // Kannada
+ {begin: 0x0D00, end: 0x0D7F}, // Malayalam
+ {begin: 0x0E00, end: 0x0E7F}, // Thai
+ {begin: 0x0E80, end: 0x0EFF}, // Lao
+ {begin: 0x10A0, end: 0x10FF}, // Georgian
+ {begin: 0x1B00, end: 0x1B7F}, // Balinese
+ {begin: 0x1100, end: 0x11FF}, // Hangul Jamo
+ {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional
+ {begin: 0x1F00, end: 0x1FFF}, // Greek Extended
+ {begin: 0x2000, end: 0x206F}, // General Punctuation
+ {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts
+ {begin: 0x20A0, end: 0x20CF}, // Currency Symbol
+ {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols
+ {begin: 0x2100, end: 0x214F}, // Letterlike Symbols
+ {begin: 0x2150, end: 0x218F}, // Number Forms
+ {begin: 0x2190, end: 0x21FF}, // Arrows
+ {begin: 0x2200, end: 0x22FF}, // Mathematical Operators
+ {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical
+ {begin: 0x2400, end: 0x243F}, // Control Pictures
+ {begin: 0x2440, end: 0x245F}, // Optical Character Recognition
+ {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics
+ {begin: 0x2500, end: 0x257F}, // Box Drawing
+ {begin: 0x2580, end: 0x259F}, // Block Elements
+ {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes
+ {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols
+ {begin: 0x2700, end: 0x27BF}, // Dingbats
+ {begin: 0x3000, end: 0x303F}, // CJK Symbols And Punctuation
+ {begin: 0x3040, end: 0x309F}, // Hiragana
+ {begin: 0x30A0, end: 0x30FF}, // Katakana
+ {begin: 0x3100, end: 0x312F}, // Bopomofo
+ {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo
+ {begin: 0xA840, end: 0xA87F}, // Phags-pa
+ {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months
+ {begin: 0x3300, end: 0x33FF}, // CJK Compatibility
+ {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables
+ {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *
+ {begin: 0x10900, end: 0x1091F}, // Phoenicia
+ {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs
+ {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)
+ {begin: 0x31C0, end: 0x31EF}, // CJK Strokes
+ {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms
+ {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A
+ {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks
+ {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms
+ {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants
+ {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B
+ {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms
+ {begin: 0xFFF0, end: 0xFFFF}, // Specials
+ {begin: 0x0F00, end: 0x0FFF}, // Tibetan
+ {begin: 0x0700, end: 0x074F}, // Syriac
+ {begin: 0x0780, end: 0x07BF}, // Thaana
+ {begin: 0x0D80, end: 0x0DFF}, // Sinhala
+ {begin: 0x1000, end: 0x109F}, // Myanmar
+ {begin: 0x1200, end: 0x137F}, // Ethiopic
+ {begin: 0x13A0, end: 0x13FF}, // Cherokee
+ {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics
+ {begin: 0x1680, end: 0x169F}, // Ogham
+ {begin: 0x16A0, end: 0x16FF}, // Runic
+ {begin: 0x1780, end: 0x17FF}, // Khmer
+ {begin: 0x1800, end: 0x18AF}, // Mongolian
+ {begin: 0x2800, end: 0x28FF}, // Braille Patterns
+ {begin: 0xA000, end: 0xA48F}, // Yi Syllables
+ {begin: 0x1700, end: 0x171F}, // Tagalog
+ {begin: 0x10300, end: 0x1032F}, // Old Italic
+ {begin: 0x10330, end: 0x1034F}, // Gothic
+ {begin: 0x10400, end: 0x1044F}, // Deseret
+ {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols
+ {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols
+ {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)
+ {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors
+ {begin: 0xE0000, end: 0xE007F}, // Tags
+ {begin: 0x1900, end: 0x194F}, // Limbu
+ {begin: 0x1950, end: 0x197F}, // Tai Le
+ {begin: 0x1980, end: 0x19DF}, // New Tai Lue
+ {begin: 0x1A00, end: 0x1A1F}, // Buginese
+ {begin: 0x2C00, end: 0x2C5F}, // Glagolitic
+ {begin: 0x2D30, end: 0x2D7F}, // Tifinagh
+ {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols
+ {begin: 0xA800, end: 0xA82F}, // Syloti Nagri
+ {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary
+ {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers
+ {begin: 0x10380, end: 0x1039F}, // Ugaritic
+ {begin: 0x103A0, end: 0x103DF}, // Old Persian
+ {begin: 0x10450, end: 0x1047F}, // Shavian
+ {begin: 0x10480, end: 0x104AF}, // Osmanya
+ {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary
+ {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi
+ {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols
+ {begin: 0x12000, end: 0x123FF}, // Cuneiform
+ {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals
+ {begin: 0x1B80, end: 0x1BBF}, // Sundanese
+ {begin: 0x1C00, end: 0x1C4F}, // Lepcha
+ {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki
+ {begin: 0xA880, end: 0xA8DF}, // Saurashtra
+ {begin: 0xA900, end: 0xA92F}, // Kayah Li
+ {begin: 0xA930, end: 0xA95F}, // Rejang
+ {begin: 0xAA00, end: 0xAA5F}, // Cham
+ {begin: 0x10190, end: 0x101CF}, // Ancient Symbols
+ {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc
+ {begin: 0x102A0, end: 0x102DF}, // Carian
+ {begin: 0x1F030, end: 0x1F09F} // Domino Tiles
+];
+
+function getUnicodeRange(unicode) {
+ for (var i = 0; i < unicodeRanges.length; i += 1) {
+ var range = unicodeRanges[i];
+ if (unicode >= range.begin && unicode < range.end) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+// Parse the OS/2 and Windows metrics `OS/2` table
+function parseOS2Table(data, start) {
+ var os2 = {};
+ var p = new parse.Parser(data, start);
+ os2.version = p.parseUShort();
+ os2.xAvgCharWidth = p.parseShort();
+ os2.usWeightClass = p.parseUShort();
+ os2.usWidthClass = p.parseUShort();
+ os2.fsType = p.parseUShort();
+ os2.ySubscriptXSize = p.parseShort();
+ os2.ySubscriptYSize = p.parseShort();
+ os2.ySubscriptXOffset = p.parseShort();
+ os2.ySubscriptYOffset = p.parseShort();
+ os2.ySuperscriptXSize = p.parseShort();
+ os2.ySuperscriptYSize = p.parseShort();
+ os2.ySuperscriptXOffset = p.parseShort();
+ os2.ySuperscriptYOffset = p.parseShort();
+ os2.yStrikeoutSize = p.parseShort();
+ os2.yStrikeoutPosition = p.parseShort();
+ os2.sFamilyClass = p.parseShort();
+ os2.panose = [];
+ for (var i = 0; i < 10; i++) {
+ os2.panose[i] = p.parseByte();
+ }
+
+ os2.ulUnicodeRange1 = p.parseULong();
+ os2.ulUnicodeRange2 = p.parseULong();
+ os2.ulUnicodeRange3 = p.parseULong();
+ os2.ulUnicodeRange4 = p.parseULong();
+ os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());
+ os2.fsSelection = p.parseUShort();
+ os2.usFirstCharIndex = p.parseUShort();
+ os2.usLastCharIndex = p.parseUShort();
+ os2.sTypoAscender = p.parseShort();
+ os2.sTypoDescender = p.parseShort();
+ os2.sTypoLineGap = p.parseShort();
+ os2.usWinAscent = p.parseUShort();
+ os2.usWinDescent = p.parseUShort();
+ if (os2.version >= 1) {
+ os2.ulCodePageRange1 = p.parseULong();
+ os2.ulCodePageRange2 = p.parseULong();
+ }
+
+ if (os2.version >= 2) {
+ os2.sxHeight = p.parseShort();
+ os2.sCapHeight = p.parseShort();
+ os2.usDefaultChar = p.parseUShort();
+ os2.usBreakChar = p.parseUShort();
+ os2.usMaxContent = p.parseUShort();
+ }
+
+ return os2;
+}
+
+function makeOS2Table(options) {
+ return new table.Table('OS/2', [
+ {name: 'version', type: 'USHORT', value: 0x0003},
+ {name: 'xAvgCharWidth', type: 'SHORT', value: 0},
+ {name: 'usWeightClass', type: 'USHORT', value: 0},
+ {name: 'usWidthClass', type: 'USHORT', value: 0},
+ {name: 'fsType', type: 'USHORT', value: 0},
+ {name: 'ySubscriptXSize', type: 'SHORT', value: 650},
+ {name: 'ySubscriptYSize', type: 'SHORT', value: 699},
+ {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},
+ {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},
+ {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},
+ {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},
+ {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},
+ {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},
+ {name: 'yStrikeoutSize', type: 'SHORT', value: 49},
+ {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},
+ {name: 'sFamilyClass', type: 'SHORT', value: 0},
+ {name: 'bFamilyType', type: 'BYTE', value: 0},
+ {name: 'bSerifStyle', type: 'BYTE', value: 0},
+ {name: 'bWeight', type: 'BYTE', value: 0},
+ {name: 'bProportion', type: 'BYTE', value: 0},
+ {name: 'bContrast', type: 'BYTE', value: 0},
+ {name: 'bStrokeVariation', type: 'BYTE', value: 0},
+ {name: 'bArmStyle', type: 'BYTE', value: 0},
+ {name: 'bLetterform', type: 'BYTE', value: 0},
+ {name: 'bMidline', type: 'BYTE', value: 0},
+ {name: 'bXHeight', type: 'BYTE', value: 0},
+ {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},
+ {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},
+ {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},
+ {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},
+ {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},
+ {name: 'fsSelection', type: 'USHORT', value: 0},
+ {name: 'usFirstCharIndex', type: 'USHORT', value: 0},
+ {name: 'usLastCharIndex', type: 'USHORT', value: 0},
+ {name: 'sTypoAscender', type: 'SHORT', value: 0},
+ {name: 'sTypoDescender', type: 'SHORT', value: 0},
+ {name: 'sTypoLineGap', type: 'SHORT', value: 0},
+ {name: 'usWinAscent', type: 'USHORT', value: 0},
+ {name: 'usWinDescent', type: 'USHORT', value: 0},
+ {name: 'ulCodePageRange1', type: 'ULONG', value: 0},
+ {name: 'ulCodePageRange2', type: 'ULONG', value: 0},
+ {name: 'sxHeight', type: 'SHORT', value: 0},
+ {name: 'sCapHeight', type: 'SHORT', value: 0},
+ {name: 'usDefaultChar', type: 'USHORT', value: 0},
+ {name: 'usBreakChar', type: 'USHORT', value: 0},
+ {name: 'usMaxContext', type: 'USHORT', value: 0}
+ ], options);
+}
+
+exports.unicodeRanges = unicodeRanges;
+exports.getUnicodeRange = getUnicodeRange;
+exports.parse = parseOS2Table;
+exports.make = makeOS2Table;
+
+},{"../parse":9,"../table":11}],24:[function(_dereq_,module,exports){
+// The `post` table stores additional PostScript information, such as glyph names.
+// https://www.microsoft.com/typography/OTSPEC/post.htm
+
+'use strict';
+
+var encoding = _dereq_('../encoding');
+var parse = _dereq_('../parse');
+var table = _dereq_('../table');
+
+// Parse the PostScript `post` table
+function parsePostTable(data, start) {
+ var post = {};
+ var p = new parse.Parser(data, start);
+ var i;
+ post.version = p.parseVersion();
+ post.italicAngle = p.parseFixed();
+ post.underlinePosition = p.parseShort();
+ post.underlineThickness = p.parseShort();
+ post.isFixedPitch = p.parseULong();
+ post.minMemType42 = p.parseULong();
+ post.maxMemType42 = p.parseULong();
+ post.minMemType1 = p.parseULong();
+ post.maxMemType1 = p.parseULong();
+ switch (post.version) {
+ case 1:
+ post.names = encoding.standardNames.slice();
+ break;
+ case 2:
+ post.numberOfGlyphs = p.parseUShort();
+ post.glyphNameIndex = new Array(post.numberOfGlyphs);
+ for (i = 0; i < post.numberOfGlyphs; i++) {
+ post.glyphNameIndex[i] = p.parseUShort();
+ }
+
+ post.names = [];
+ for (i = 0; i < post.numberOfGlyphs; i++) {
+ if (post.glyphNameIndex[i] >= encoding.standardNames.length) {
+ var nameLength = p.parseChar();
+ post.names.push(p.parseString(nameLength));
+ }
+ }
+
+ break;
+ case 2.5:
+ post.numberOfGlyphs = p.parseUShort();
+ post.offset = new Array(post.numberOfGlyphs);
+ for (i = 0; i < post.numberOfGlyphs; i++) {
+ post.offset[i] = p.parseChar();
+ }
+
+ break;
+ }
+ return post;
+}
+
+function makePostTable() {
+ return new table.Table('post', [
+ {name: 'version', type: 'FIXED', value: 0x00030000},
+ {name: 'italicAngle', type: 'FIXED', value: 0},
+ {name: 'underlinePosition', type: 'FWORD', value: 0},
+ {name: 'underlineThickness', type: 'FWORD', value: 0},
+ {name: 'isFixedPitch', type: 'ULONG', value: 0},
+ {name: 'minMemType42', type: 'ULONG', value: 0},
+ {name: 'maxMemType42', type: 'ULONG', value: 0},
+ {name: 'minMemType1', type: 'ULONG', value: 0},
+ {name: 'maxMemType1', type: 'ULONG', value: 0}
+ ]);
+}
+
+exports.parse = parsePostTable;
+exports.make = makePostTable;
+
+},{"../encoding":4,"../parse":9,"../table":11}],25:[function(_dereq_,module,exports){
+// The `sfnt` wrapper provides organization for the tables in the font.
+// It is the top-level data structure in a font.
+// https://www.microsoft.com/typography/OTSPEC/otff.htm
+// Recommendations for creating OpenType Fonts:
+// http://www.microsoft.com/typography/otspec140/recom.htm
+
+'use strict';
+
+var check = _dereq_('../check');
+var table = _dereq_('../table');
+
+var cmap = _dereq_('./cmap');
+var cff = _dereq_('./cff');
+var head = _dereq_('./head');
+var hhea = _dereq_('./hhea');
+var hmtx = _dereq_('./hmtx');
+var maxp = _dereq_('./maxp');
+var _name = _dereq_('./name');
+var os2 = _dereq_('./os2');
+var post = _dereq_('./post');
+
+function log2(v) {
+ return Math.log(v) / Math.log(2) | 0;
+}
+
+function computeCheckSum(bytes) {
+ while (bytes.length % 4 !== 0) {
+ bytes.push(0);
+ }
+
+ var sum = 0;
+ for (var i = 0; i < bytes.length; i += 4) {
+ sum += (bytes[i] << 24) +
+ (bytes[i + 1] << 16) +
+ (bytes[i + 2] << 8) +
+ (bytes[i + 3]);
+ }
+
+ sum %= Math.pow(2, 32);
+ return sum;
+}
+
+function makeTableRecord(tag, checkSum, offset, length) {
+ return new table.Table('Table Record', [
+ {name: 'tag', type: 'TAG', value: tag !== undefined ? tag : ''},
+ {name: 'checkSum', type: 'ULONG', value: checkSum !== undefined ? checkSum : 0},
+ {name: 'offset', type: 'ULONG', value: offset !== undefined ? offset : 0},
+ {name: 'length', type: 'ULONG', value: length !== undefined ? length : 0}
+ ]);
+}
+
+function makeSfntTable(tables) {
+ var sfnt = new table.Table('sfnt', [
+ {name: 'version', type: 'TAG', value: 'OTTO'},
+ {name: 'numTables', type: 'USHORT', value: 0},
+ {name: 'searchRange', type: 'USHORT', value: 0},
+ {name: 'entrySelector', type: 'USHORT', value: 0},
+ {name: 'rangeShift', type: 'USHORT', value: 0}
+ ]);
+ sfnt.tables = tables;
+ sfnt.numTables = tables.length;
+ var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
+ sfnt.searchRange = 16 * highestPowerOf2;
+ sfnt.entrySelector = log2(highestPowerOf2);
+ sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
+
+ var recordFields = [];
+ var tableFields = [];
+
+ var offset = sfnt.sizeOf() + (makeTableRecord().sizeOf() * sfnt.numTables);
+ while (offset % 4 !== 0) {
+ offset += 1;
+ tableFields.push({name: 'padding', type: 'BYTE', value: 0});
+ }
+
+ for (var i = 0; i < tables.length; i += 1) {
+ var t = tables[i];
+ check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.');
+ var tableLength = t.sizeOf();
+ var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength);
+ recordFields.push({name: tableRecord.tag + ' Table Record', type: 'TABLE', value: tableRecord});
+ tableFields.push({name: t.tableName + ' table', type: 'TABLE', value: t});
+ offset += tableLength;
+ check.argument(!isNaN(offset), 'Something went wrong calculating the offset.');
+ while (offset % 4 !== 0) {
+ offset += 1;
+ tableFields.push({name: 'padding', type: 'BYTE', value: 0});
+ }
+ }
+
+ // Table records need to be sorted alphabetically.
+ recordFields.sort(function(r1, r2) {
+ if (r1.value.tag > r2.value.tag) {
+ return 1;
+ } else {
+ return -1;
+ }
+ });
+
+ sfnt.fields = sfnt.fields.concat(recordFields);
+ sfnt.fields = sfnt.fields.concat(tableFields);
+ return sfnt;
+}
+
+// Get the metrics for a character. If the string has more than one character
+// this function returns metrics for the first available character.
+// You can provide optional fallback metrics if no characters are available.
+function metricsForChar(font, chars, notFoundMetrics) {
+ for (var i = 0; i < chars.length; i += 1) {
+ var glyphIndex = font.charToGlyphIndex(chars[i]);
+ if (glyphIndex > 0) {
+ var glyph = font.glyphs.get(glyphIndex);
+ return glyph.getMetrics();
+ }
+ }
+
+ return notFoundMetrics;
+}
+
+function average(vs) {
+ var sum = 0;
+ for (var i = 0; i < vs.length; i += 1) {
+ sum += vs[i];
+ }
+
+ return sum / vs.length;
+}
+
+// Convert the font object to a SFNT data structure.
+// This structure contains all the necessary tables and metadata to create a binary OTF file.
+function fontToSfntTable(font) {
+ var xMins = [];
+ var yMins = [];
+ var xMaxs = [];
+ var yMaxs = [];
+ var advanceWidths = [];
+ var leftSideBearings = [];
+ var rightSideBearings = [];
+ var firstCharIndex;
+ var lastCharIndex = 0;
+ var ulUnicodeRange1 = 0;
+ var ulUnicodeRange2 = 0;
+ var ulUnicodeRange3 = 0;
+ var ulUnicodeRange4 = 0;
+
+ for (var i = 0; i < font.glyphs.length; i += 1) {
+ var glyph = font.glyphs.get(i);
+ var unicode = glyph.unicode | 0;
+ if (firstCharIndex > unicode || firstCharIndex === null) {
+ firstCharIndex = unicode;
+ }
+
+ if (lastCharIndex < unicode) {
+ lastCharIndex = unicode;
+ }
+
+ var position = os2.getUnicodeRange(unicode);
+ if (position < 32) {
+ ulUnicodeRange1 |= 1 << position;
+ } else if (position < 64) {
+ ulUnicodeRange2 |= 1 << position - 32;
+ } else if (position < 96) {
+ ulUnicodeRange3 |= 1 << position - 64;
+ } else if (position < 123) {
+ ulUnicodeRange4 |= 1 << position - 96;
+ } else {
+ throw new Error('Unicode ranges bits > 123 are reserved for internal usage');
+ }
+ // Skip non-important characters.
+ if (glyph.name === '.notdef') continue;
+ var metrics = glyph.getMetrics();
+ xMins.push(metrics.xMin);
+ yMins.push(metrics.yMin);
+ xMaxs.push(metrics.xMax);
+ yMaxs.push(metrics.yMax);
+ leftSideBearings.push(metrics.leftSideBearing);
+ rightSideBearings.push(metrics.rightSideBearing);
+ advanceWidths.push(glyph.advanceWidth);
+ }
+
+ var globals = {
+ xMin: Math.min.apply(null, xMins),
+ yMin: Math.min.apply(null, yMins),
+ xMax: Math.max.apply(null, xMaxs),
+ yMax: Math.max.apply(null, yMaxs),
+ advanceWidthMax: Math.max.apply(null, advanceWidths),
+ advanceWidthAvg: average(advanceWidths),
+ minLeftSideBearing: Math.min.apply(null, leftSideBearings),
+ maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
+ minRightSideBearing: Math.min.apply(null, rightSideBearings)
+ };
+ globals.ascender = font.ascender !== undefined ? font.ascender : globals.yMax;
+ globals.descender = font.descender !== undefined ? font.descender : globals.yMin;
+
+ var headTable = head.make({
+ unitsPerEm: font.unitsPerEm,
+ xMin: globals.xMin,
+ yMin: globals.yMin,
+ xMax: globals.xMax,
+ yMax: globals.yMax
+ });
+
+ var hheaTable = hhea.make({
+ ascender: globals.ascender,
+ descender: globals.descender,
+ advanceWidthMax: globals.advanceWidthMax,
+ minLeftSideBearing: globals.minLeftSideBearing,
+ minRightSideBearing: globals.minRightSideBearing,
+ xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
+ numberOfHMetrics: font.glyphs.length
+ });
+
+ var maxpTable = maxp.make(font.glyphs.length);
+
+ var os2Table = os2.make({
+ xAvgCharWidth: Math.round(globals.advanceWidthAvg),
+ usWeightClass: 500, // Medium FIXME Make this configurable
+ usWidthClass: 5, // Medium (normal) FIXME Make this configurable
+ usFirstCharIndex: firstCharIndex,
+ usLastCharIndex: lastCharIndex,
+ ulUnicodeRange1: ulUnicodeRange1,
+ ulUnicodeRange2: ulUnicodeRange2,
+ ulUnicodeRange3: ulUnicodeRange3,
+ ulUnicodeRange4: ulUnicodeRange4,
+ // See http://typophile.com/node/13081 for more info on vertical metrics.
+ // We get metrics for typical characters (such as "x" for xHeight).
+ // We provide some fallback characters if characters are unavailable: their
+ // ordering was chosen experimentally.
+ sTypoAscender: globals.ascender,
+ sTypoDescender: globals.descender,
+ sTypoLineGap: 0,
+ usWinAscent: globals.ascender,
+ usWinDescent: -globals.descender,
+ sxHeight: metricsForChar(font, 'xyvw', {yMax: 0}).yMax,
+ sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,
+ usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
+ });
+
+ var hmtxTable = hmtx.make(font.glyphs);
+ var cmapTable = cmap.make(font.glyphs);
+
+ var fullName = font.familyName + ' ' + font.styleName;
+ var postScriptName = font.familyName.replace(/\s/g, '') + '-' + font.styleName;
+ var nameTable = _name.make({
+ copyright: font.copyright,
+ fontFamily: font.familyName,
+ fontSubfamily: font.styleName,
+ uniqueID: font.manufacturer + ':' + fullName,
+ fullName: fullName,
+ version: font.version,
+ postScriptName: postScriptName,
+ trademark: font.trademark,
+ manufacturer: font.manufacturer,
+ designer: font.designer,
+ description: font.description,
+ manufacturerURL: font.manufacturerURL,
+ designerURL: font.designerURL,
+ license: font.license,
+ licenseURL: font.licenseURL,
+ preferredFamily: font.familyName,
+ preferredSubfamily: font.styleName
+ });
+ var postTable = post.make();
+ var cffTable = cff.make(font.glyphs, {
+ version: font.version,
+ fullName: fullName,
+ familyName: font.familyName,
+ weightName: font.styleName,
+ postScriptName: postScriptName,
+ unitsPerEm: font.unitsPerEm
+ });
+ // Order the tables according to the the OpenType specification 1.4.
+ var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];
+
+ var sfntTable = makeSfntTable(tables);
+
+ // Compute the font's checkSum and store it in head.checkSumAdjustment.
+ var bytes = sfntTable.encode();
+ var checkSum = computeCheckSum(bytes);
+ var tableFields = sfntTable.fields;
+ var checkSumAdjusted = false;
+ for (i = 0; i < tableFields.length; i += 1) {
+ if (tableFields[i].name === 'head table') {
+ tableFields[i].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;
+ checkSumAdjusted = true;
+ break;
+ }
+ }
+
+ if (!checkSumAdjusted) {
+ throw new Error('Could not find head table with checkSum to adjust.');
+ }
+
+ return sfntTable;
+}
+
+exports.computeCheckSum = computeCheckSum;
+exports.make = makeSfntTable;
+exports.fontToTable = fontToSfntTable;
+
+},{"../check":2,"../table":11,"./cff":12,"./cmap":13,"./head":16,"./hhea":17,"./hmtx":18,"./maxp":21,"./name":22,"./os2":23,"./post":24}],26:[function(_dereq_,module,exports){
+// Data types used in the OpenType font file.
+// All OpenType fonts use Motorola-style byte ordering (Big Endian)
+
+/* global WeakMap */
+
+'use strict';
+
+var check = _dereq_('./check');
+
+var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
+var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
+
+var decode = {};
+var encode = {};
+var sizeOf = {};
+
+// Return a function that always returns the same value.
+function constant(v) {
+ return function() {
+ return v;
+ };
+}
+
+// OpenType data types //////////////////////////////////////////////////////
+
+// Convert an 8-bit unsigned integer to a list of 1 byte.
+encode.BYTE = function(v) {
+ check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
+ return [v];
+};
+
+sizeOf.BYTE = constant(1);
+
+// Convert a 8-bit signed integer to a list of 1 byte.
+encode.CHAR = function(v) {
+ return [v.charCodeAt(0)];
+};
+
+sizeOf.BYTE = constant(1);
+
+// Convert an ASCII string to a list of bytes.
+encode.CHARARRAY = function(v) {
+ var b = [];
+ for (var i = 0; i < v.length; i += 1) {
+ b.push(v.charCodeAt(i));
+ }
+
+ return b;
+};
+
+sizeOf.CHARARRAY = function(v) {
+ return v.length;
+};
+
+// Convert a 16-bit unsigned integer to a list of 2 bytes.
+encode.USHORT = function(v) {
+ return [(v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.USHORT = constant(2);
+
+// Convert a 16-bit signed integer to a list of 2 bytes.
+encode.SHORT = function(v) {
+ // Two's complement
+ if (v >= LIMIT16) {
+ v = -(2 * LIMIT16 - v);
+ }
+
+ return [(v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.SHORT = constant(2);
+
+// Convert a 24-bit unsigned integer to a list of 3 bytes.
+encode.UINT24 = function(v) {
+ return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.UINT24 = constant(3);
+
+// Convert a 32-bit unsigned integer to a list of 4 bytes.
+encode.ULONG = function(v) {
+ return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.ULONG = constant(4);
+
+// Convert a 32-bit unsigned integer to a list of 4 bytes.
+encode.LONG = function(v) {
+ // Two's complement
+ if (v >= LIMIT32) {
+ v = -(2 * LIMIT32 - v);
+ }
+
+ return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.LONG = constant(4);
+
+encode.FIXED = encode.ULONG;
+sizeOf.FIXED = sizeOf.ULONG;
+
+encode.FWORD = encode.SHORT;
+sizeOf.FWORD = sizeOf.SHORT;
+
+encode.UFWORD = encode.USHORT;
+sizeOf.UFWORD = sizeOf.USHORT;
+
+// FIXME Implement LONGDATETIME
+encode.LONGDATETIME = function() {
+ return [0, 0, 0, 0, 0, 0, 0, 0];
+};
+
+sizeOf.LONGDATETIME = constant(8);
+
+// Convert a 4-char tag to a list of 4 bytes.
+encode.TAG = function(v) {
+ check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
+ return [v.charCodeAt(0),
+ v.charCodeAt(1),
+ v.charCodeAt(2),
+ v.charCodeAt(3)];
+};
+
+sizeOf.TAG = constant(4);
+
+// CFF data types ///////////////////////////////////////////////////////////
+
+encode.Card8 = encode.BYTE;
+sizeOf.Card8 = sizeOf.BYTE;
+
+encode.Card16 = encode.USHORT;
+sizeOf.Card16 = sizeOf.USHORT;
+
+encode.OffSize = encode.BYTE;
+sizeOf.OffSize = sizeOf.BYTE;
+
+encode.SID = encode.USHORT;
+sizeOf.SID = sizeOf.USHORT;
+
+// Convert a numeric operand or charstring number to a variable-size list of bytes.
+encode.NUMBER = function(v) {
+ if (v >= -107 && v <= 107) {
+ return [v + 139];
+ } else if (v >= 108 && v <= 1131) {
+ v = v - 108;
+ return [(v >> 8) + 247, v & 0xFF];
+ } else if (v >= -1131 && v <= -108) {
+ v = -v - 108;
+ return [(v >> 8) + 251, v & 0xFF];
+ } else if (v >= -32768 && v <= 32767) {
+ return encode.NUMBER16(v);
+ } else {
+ return encode.NUMBER32(v);
+ }
+};
+
+sizeOf.NUMBER = function(v) {
+ return encode.NUMBER(v).length;
+};
+
+// Convert a signed number between -32768 and +32767 to a three-byte value.
+// This ensures we always use three bytes, but is not the most compact format.
+encode.NUMBER16 = function(v) {
+ return [28, (v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.NUMBER16 = constant(2);
+
+// Convert a signed number between -(2^31) and +(2^31-1) to a four-byte value.
+// This is useful if you want to be sure you always use four bytes,
+// at the expense of wasting a few bytes for smaller numbers.
+encode.NUMBER32 = function(v) {
+ return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
+};
+
+sizeOf.NUMBER32 = constant(4);
+
+encode.REAL = function(v) {
+ var value = v.toString();
+
+ // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
+ // This code converts it back to a number without the epsilon.
+ var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
+ if (m) {
+ var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
+ value = (Math.round(v * epsilon) / epsilon).toString();
+ }
+
+ var nibbles = '';
+ var i;
+ var ii;
+ for (i = 0, ii = value.length; i < ii; i += 1) {
+ var c = value[i];
+ if (c === 'e') {
+ nibbles += value[++i] === '-' ? 'c' : 'b';
+ } else if (c === '.') {
+ nibbles += 'a';
+ } else if (c === '-') {
+ nibbles += 'e';
+ } else {
+ nibbles += c;
+ }
+ }
+
+ nibbles += (nibbles.length & 1) ? 'f' : 'ff';
+ var out = [30];
+ for (i = 0, ii = nibbles.length; i < ii; i += 2) {
+ out.push(parseInt(nibbles.substr(i, 2), 16));
+ }
+
+ return out;
+};
+
+sizeOf.REAL = function(v) {
+ return encode.REAL(v).length;
+};
+
+encode.NAME = encode.CHARARRAY;
+sizeOf.NAME = sizeOf.CHARARRAY;
+
+encode.STRING = encode.CHARARRAY;
+sizeOf.STRING = sizeOf.CHARARRAY;
+
+// Convert a ASCII string to a list of UTF16 bytes.
+encode.UTF16 = function(v) {
+ var b = [];
+ for (var i = 0; i < v.length; i += 1) {
+ b.push(0);
+ b.push(v.charCodeAt(i));
+ }
+
+ return b;
+};
+
+sizeOf.UTF16 = function(v) {
+ return v.length * 2;
+};
+
+// Convert a list of values to a CFF INDEX structure.
+// The values should be objects containing name / type / value.
+encode.INDEX = function(l) {
+ var i;
+ //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
+ // dataSize, i, v;
+ // Because we have to know which data type to use to encode the offsets,
+ // we have to go through the values twice: once to encode the data and
+ // calculate the offets, then again to encode the offsets using the fitting data type.
+ var offset = 1; // First offset is always 1.
+ var offsets = [offset];
+ var data = [];
+ var dataSize = 0;
+ for (i = 0; i < l.length; i += 1) {
+ var v = encode.OBJECT(l[i]);
+ Array.prototype.push.apply(data, v);
+ dataSize += v.length;
+ offset += v.length;
+ offsets.push(offset);
+ }
+
+ if (data.length === 0) {
+ return [0, 0];
+ }
+
+ var encodedOffsets = [];
+ var offSize = (1 + Math.floor(Math.log(dataSize) / Math.log(2)) / 8) | 0;
+ var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
+ for (i = 0; i < offsets.length; i += 1) {
+ var encodedOffset = offsetEncoder(offsets[i]);
+ Array.prototype.push.apply(encodedOffsets, encodedOffset);
+ }
+
+ return Array.prototype.concat(encode.Card16(l.length),
+ encode.OffSize(offSize),
+ encodedOffsets,
+ data);
+};
+
+sizeOf.INDEX = function(v) {
+ return encode.INDEX(v).length;
+};
+
+// Convert an object to a CFF DICT structure.
+// The keys should be numeric.
+// The values should be objects containing name / type / value.
+encode.DICT = function(m) {
+ var d = [];
+ var keys = Object.keys(m);
+ var length = keys.length;
+
+ for (var i = 0; i < length; i += 1) {
+ // Object.keys() return string keys, but our keys are always numeric.
+ var k = parseInt(keys[i], 0);
+ var v = m[k];
+ // Value comes before the key.
+ d = d.concat(encode.OPERAND(v.value, v.type));
+ d = d.concat(encode.OPERATOR(k));
+ }
+
+ return d;
+};
+
+sizeOf.DICT = function(m) {
+ return encode.DICT(m).length;
+};
+
+encode.OPERATOR = function(v) {
+ if (v < 1200) {
+ return [v];
+ } else {
+ return [12, v - 1200];
+ }
+};
+
+encode.OPERAND = function(v, type) {
+ var d = [];
+ if (Array.isArray(type)) {
+ for (var i = 0; i < type.length; i += 1) {
+ check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
+ d = d.concat(encode.OPERAND(v[i], type[i]));
+ }
+ } else {
+ if (type === 'SID') {
+ d = d.concat(encode.NUMBER(v));
+ } else if (type === 'offset') {
+ // We make it easy for ourselves and always encode offsets as
+ // 4 bytes. This makes offset calculation for the top dict easier.
+ d = d.concat(encode.NUMBER32(v));
+ } else if (type === 'number') {
+ d = d.concat(encode.NUMBER(v));
+ } else if (type === 'real') {
+ d = d.concat(encode.REAL(v));
+ } else {
+ throw new Error('Unknown operand type ' + type);
+ // FIXME Add support for booleans
+ }
+ }
+
+ return d;
+};
+
+encode.OP = encode.BYTE;
+sizeOf.OP = sizeOf.BYTE;
+
+// memoize charstring encoding using WeakMap if available
+var wmm = typeof WeakMap === 'function' && new WeakMap();
+// Convert a list of CharString operations to bytes.
+encode.CHARSTRING = function(ops) {
+ if (wmm && wmm.has(ops)) {
+ return wmm.get(ops);
+ }
+
+ var d = [];
+ var length = ops.length;
+
+ for (var i = 0; i < length; i += 1) {
+ var op = ops[i];
+ d = d.concat(encode[op.type](op.value));
+ }
+
+ if (wmm) {
+ wmm.set(ops, d);
+ }
+
+ return d;
+};
+
+sizeOf.CHARSTRING = function(ops) {
+ return encode.CHARSTRING(ops).length;
+};
+
+// Utility functions ////////////////////////////////////////////////////////
+
+// Convert an object containing name / type / value to bytes.
+encode.OBJECT = function(v) {
+ var encodingFunction = encode[v.type];
+ check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
+ return encodingFunction(v.value);
+};
+
+// Convert a table object to bytes.
+// A table contains a list of fields containing the metadata (name, type and default value).
+// The table itself has the field values set as attributes.
+encode.TABLE = function(table) {
+ var d = [];
+ var length = table.fields.length;
+
+ for (var i = 0; i < length; i += 1) {
+ var field = table.fields[i];
+ var encodingFunction = encode[field.type];
+ check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type);
+ var value = table[field.name];
+ if (value === undefined) {
+ value = field.value;
+ }
+
+ var bytes = encodingFunction(value);
+ d = d.concat(bytes);
+ }
+
+ return d;
+};
+
+// Merge in a list of bytes.
+encode.LITERAL = function(v) {
+ return v;
+};
+
+sizeOf.LITERAL = function(v) {
+ return v.length;
+};
+
+exports.decode = decode;
+exports.encode = encode;
+exports.sizeOf = sizeOf;
+
+},{"./check":2}],27:[function(_dereq_,module,exports){
+/*!
+ * Reqwest! A general purpose XHR connection manager
+ * license MIT (c) Dustin Diaz 2014
+ * https://github.com/ded/reqwest
+ */
+
+!function (name, context, definition) {
+ if (typeof module != 'undefined' && module.exports) module.exports = definition()
+ else if (typeof define == 'function' && define.amd) define(definition)
+ else context[name] = definition()
+}('reqwest', this, function () {
+
+ var win = window
+ , doc = document
+ , httpsRe = /^http/
+ , protocolRe = /(^\w+):\/\//
+ , twoHundo = /^(20\d|1223)$/ //http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
+ , byTag = 'getElementsByTagName'
+ , readyState = 'readyState'
+ , contentType = 'Content-Type'
+ , requestedWith = 'X-Requested-With'
+ , head = doc[byTag]('head')[0]
+ , uniqid = 0
+ , callbackPrefix = 'reqwest_' + (+new Date())
+ , lastValue // data stored by the most recent JSONP callback
+ , xmlHttpRequest = 'XMLHttpRequest'
+ , xDomainRequest = 'XDomainRequest'
+ , noop = function () {}
+
+ , isArray = typeof Array.isArray == 'function'
+ ? Array.isArray
+ : function (a) {
+ return a instanceof Array
+ }
+
+ , defaultHeaders = {
+ 'contentType': 'application/x-www-form-urlencoded'
+ , 'requestedWith': xmlHttpRequest
+ , 'accept': {
+ '*': 'text/javascript, text/html, application/xml, text/xml, */*'
+ , 'xml': 'application/xml, text/xml'
+ , 'html': 'text/html'
+ , 'text': 'text/plain'
+ , 'json': 'application/json, text/javascript'
+ , 'js': 'application/javascript, text/javascript'
+ }
+ }
+
+ , xhr = function(o) {
+ // is it x-domain
+ if (o['crossOrigin'] === true) {
+ var xhr = win[xmlHttpRequest] ? new XMLHttpRequest() : null
+ if (xhr && 'withCredentials' in xhr) {
+ return xhr
+ } else if (win[xDomainRequest]) {
+ return new XDomainRequest()
+ } else {
+ throw new Error('Browser does not support cross-origin requests')
+ }
+ } else if (win[xmlHttpRequest]) {
+ return new XMLHttpRequest()
+ } else {
+ return new ActiveXObject('Microsoft.XMLHTTP')
+ }
+ }
+ , globalSetupOptions = {
+ dataFilter: function (data) {
+ return data
+ }
+ }
+
+ function succeed(r) {
+ var protocol = protocolRe.exec(r.url);
+ protocol = (protocol && protocol[1]) || window.location.protocol;
+ return httpsRe.test(protocol) ? twoHundo.test(r.request.status) : !!r.request.response;
+ }
+
+ function handleReadyState(r, success, error) {
+ return function () {
+ // use _aborted to mitigate against IE err c00c023f
+ // (can't read props on aborted request objects)
+ if (r._aborted) return error(r.request)
+ if (r._timedOut) return error(r.request, 'Request is aborted: timeout')
+ if (r.request && r.request[readyState] == 4) {
+ r.request.onreadystatechange = noop
+ if (succeed(r)) success(r.request)
+ else
+ error(r.request)
+ }
+ }
+ }
+
+ function setHeaders(http, o) {
+ var headers = o['headers'] || {}
+ , h
+
+ headers['Accept'] = headers['Accept']
+ || defaultHeaders['accept'][o['type']]
+ || defaultHeaders['accept']['*']
+
+ var isAFormData = typeof FormData === 'function' && (o['data'] instanceof FormData);
+ // breaks cross-origin requests with legacy browsers
+ if (!o['crossOrigin'] && !headers[requestedWith]) headers[requestedWith] = defaultHeaders['requestedWith']
+ if (!headers[contentType] && !isAFormData) headers[contentType] = o['contentType'] || defaultHeaders['contentType']
+ for (h in headers)
+ headers.hasOwnProperty(h) && 'setRequestHeader' in http && http.setRequestHeader(h, headers[h])
+ }
+
+ function setCredentials(http, o) {
+ if (typeof o['withCredentials'] !== 'undefined' && typeof http.withCredentials !== 'undefined') {
+ http.withCredentials = !!o['withCredentials']
+ }
+ }
+
+ function generalCallback(data) {
+ lastValue = data
+ }
+
+ function urlappend (url, s) {
+ return url + (/\?/.test(url) ? '&' : '?') + s
+ }
+
+ function handleJsonp(o, fn, err, url) {
+ var reqId = uniqid++
+ , cbkey = o['jsonpCallback'] || 'callback' // the 'callback' key
+ , cbval = o['jsonpCallbackName'] || reqwest.getcallbackPrefix(reqId)
+ , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
+ , match = url.match(cbreg)
+ , script = doc.createElement('script')
+ , loaded = 0
+ , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1
+
+ if (match) {
+ if (match[3] === '?') {
+ url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
+ } else {
+ cbval = match[3] // provided callback func name
+ }
+ } else {
+ url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
+ }
+
+ win[cbval] = generalCallback
+
+ script.type = 'text/javascript'
+ script.src = url
+ script.async = true
+ if (typeof script.onreadystatechange !== 'undefined' && !isIE10) {
+ // need this for IE due to out-of-order onreadystatechange(), binding script
+ // execution to an event listener gives us control over when the script
+ // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
+ script.htmlFor = script.id = '_reqwest_' + reqId
+ }
+
+ script.onload = script.onreadystatechange = function () {
+ if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
+ return false
+ }
+ script.onload = script.onreadystatechange = null
+ script.onclick && script.onclick()
+ // Call the user callback with the last value stored and clean up values and scripts.
+ fn(lastValue)
+ lastValue = undefined
+ head.removeChild(script)
+ loaded = 1
+ }
+
+ // Add the script to the DOM head
+ head.appendChild(script)
+
+ // Enable JSONP timeout
+ return {
+ abort: function () {
+ script.onload = script.onreadystatechange = null
+ err({}, 'Request is aborted: timeout', {})
+ lastValue = undefined
+ head.removeChild(script)
+ loaded = 1
+ }
+ }
+ }
+
+ function getRequest(fn, err) {
+ var o = this.o
+ , method = (o['method'] || 'GET').toUpperCase()
+ , url = typeof o === 'string' ? o : o['url']
+ // convert non-string objects to query-string form unless o['processData'] is false
+ , data = (o['processData'] !== false && o['data'] && typeof o['data'] !== 'string')
+ ? reqwest.toQueryString(o['data'])
+ : (o['data'] || null)
+ , http
+ , sendWait = false
+
+ // if we're working on a GET request and we have data then we should append
+ // query string to end of URL and not post data
+ if ((o['type'] == 'jsonp' || method == 'GET') && data) {
+ url = urlappend(url, data)
+ data = null
+ }
+
+ if (o['type'] == 'jsonp') return handleJsonp(o, fn, err, url)
+
+ // get the xhr from the factory if passed
+ // if the factory returns null, fall-back to ours
+ http = (o.xhr && o.xhr(o)) || xhr(o)
+
+ http.open(method, url, o['async'] === false ? false : true)
+ setHeaders(http, o)
+ setCredentials(http, o)
+ if (win[xDomainRequest] && http instanceof win[xDomainRequest]) {
+ http.onload = fn
+ http.onerror = err
+ // NOTE: see
+ // http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/30ef3add-767c-4436-b8a9-f1ca19b4812e
+ http.onprogress = function() {}
+ sendWait = true
+ } else {
+ http.onreadystatechange = handleReadyState(this, fn, err)
+ }
+ o['before'] && o['before'](http)
+ if (sendWait) {
+ setTimeout(function () {
+ http.send(data)
+ }, 200)
+ } else {
+ http.send(data)
+ }
+ return http
+ }
+
+ function Reqwest(o, fn) {
+ this.o = o
+ this.fn = fn
+
+ init.apply(this, arguments)
+ }
+
+ function setType(header) {
+ // json, javascript, text/plain, text/html, xml
+ if (header.match('json')) return 'json'
+ if (header.match('javascript')) return 'js'
+ if (header.match('text')) return 'html'
+ if (header.match('xml')) return 'xml'
+ }
+
+ function init(o, fn) {
+
+ this.url = typeof o == 'string' ? o : o['url']
+ this.timeout = null
+
+ // whether request has been fulfilled for purpose
+ // of tracking the Promises
+ this._fulfilled = false
+ // success handlers
+ this._successHandler = function(){}
+ this._fulfillmentHandlers = []
+ // error handlers
+ this._errorHandlers = []
+ // complete (both success and fail) handlers
+ this._completeHandlers = []
+ this._erred = false
+ this._responseArgs = {}
+
+ var self = this
+
+ fn = fn || function () {}
+
+ if (o['timeout']) {
+ this.timeout = setTimeout(function () {
+ timedOut()
+ }, o['timeout'])
+ }
+
+ if (o['success']) {
+ this._successHandler = function () {
+ o['success'].apply(o, arguments)
+ }
+ }
+
+ if (o['error']) {
+ this._errorHandlers.push(function () {
+ o['error'].apply(o, arguments)
+ })
+ }
+
+ if (o['complete']) {
+ this._completeHandlers.push(function () {
+ o['complete'].apply(o, arguments)
+ })
+ }
+
+ function complete (resp) {
+ o['timeout'] && clearTimeout(self.timeout)
+ self.timeout = null
+ while (self._completeHandlers.length > 0) {
+ self._completeHandlers.shift()(resp)
+ }
+ }
+
+ function success (resp) {
+ var type = o['type'] || resp && setType(resp.getResponseHeader('Content-Type')) // resp can be undefined in IE
+ resp = (type !== 'jsonp') ? self.request : resp
+ // use global data filter on response text
+ var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type)
+ , r = filteredResponse
+ try {
+ resp.responseText = r
+ } catch (e) {
+ // can't assign this in IE<=8, just ignore
+ }
+ if (r) {
+ switch (type) {
+ case 'json':
+ try {
+ resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
+ } catch (err) {
+ return error(resp, 'Could not parse JSON in response', err)
+ }
+ break
+ case 'js':
+ resp = eval(r)
+ break
+ case 'html':
+ resp = r
+ break
+ case 'xml':
+ resp = resp.responseXML
+ && resp.responseXML.parseError // IE trololo
+ && resp.responseXML.parseError.errorCode
+ && resp.responseXML.parseError.reason
+ ? null
+ : resp.responseXML
+ break
+ }
+ }
+
+ self._responseArgs.resp = resp
+ self._fulfilled = true
+ fn(resp)
+ self._successHandler(resp)
+ while (self._fulfillmentHandlers.length > 0) {
+ resp = self._fulfillmentHandlers.shift()(resp)
+ }
+
+ complete(resp)
+ }
+
+ function timedOut() {
+ self._timedOut = true
+ self.request.abort()
+ }
+
+ function error(resp, msg, t) {
+ resp = self.request
+ self._responseArgs.resp = resp
+ self._responseArgs.msg = msg
+ self._responseArgs.t = t
+ self._erred = true
+ while (self._errorHandlers.length > 0) {
+ self._errorHandlers.shift()(resp, msg, t)
+ }
+ complete(resp)
+ }
+
+ this.request = getRequest.call(this, success, error)
+ }
+
+ Reqwest.prototype = {
+ abort: function () {
+ this._aborted = true
+ this.request.abort()
+ }
+
+ , retry: function () {
+ init.call(this, this.o, this.fn)
+ }
+
+ /**
+ * Small deviation from the Promises A CommonJs specification
+ * http://wiki.commonjs.org/wiki/Promises/A
+ */
+
+ /**
+ * `then` will execute upon successful requests
+ */
+ , then: function (success, fail) {
+ success = success || function () {}
+ fail = fail || function () {}
+ if (this._fulfilled) {
+ this._responseArgs.resp = success(this._responseArgs.resp)
+ } else if (this._erred) {
+ fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
+ } else {
+ this._fulfillmentHandlers.push(success)
+ this._errorHandlers.push(fail)
+ }
+ return this
+ }
+
+ /**
+ * `always` will execute whether the request succeeds or fails
+ */
+ , always: function (fn) {
+ if (this._fulfilled || this._erred) {
+ fn(this._responseArgs.resp)
+ } else {
+ this._completeHandlers.push(fn)
+ }
+ return this
+ }
+
+ /**
+ * `fail` will execute when the request fails
+ */
+ , fail: function (fn) {
+ if (this._erred) {
+ fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
+ } else {
+ this._errorHandlers.push(fn)
+ }
+ return this
+ }
+ , 'catch': function (fn) {
+ return this.fail(fn)
+ }
+ }
+
+ function reqwest(o, fn) {
+ return new Reqwest(o, fn)
+ }
+
+ // normalize newline variants according to spec -> CRLF
+ function normalize(s) {
+ return s ? s.replace(/\r?\n/g, '\r\n') : ''
+ }
+
+ function serial(el, cb) {
+ var n = el.name
+ , t = el.tagName.toLowerCase()
+ , optCb = function (o) {
+ // IE gives value="" even where there is no value attribute
+ // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
+ if (o && !o['disabled'])
+ cb(n, normalize(o['attributes']['value'] && o['attributes']['value']['specified'] ? o['value'] : o['text']))
+ }
+ , ch, ra, val, i
+
+ // don't serialize elements that are disabled or without a name
+ if (el.disabled || !n) return
+
+ switch (t) {
+ case 'input':
+ if (!/reset|button|image|file/i.test(el.type)) {
+ ch = /checkbox/i.test(el.type)
+ ra = /radio/i.test(el.type)
+ val = el.value
+ // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
+ ;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
+ }
+ break
+ case 'textarea':
+ cb(n, normalize(el.value))
+ break
+ case 'select':
+ if (el.type.toLowerCase() === 'select-one') {
+ optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
+ } else {
+ for (i = 0; el.length && i < el.length; i++) {
+ el.options[i].selected && optCb(el.options[i])
+ }
+ }
+ break
+ }
+ }
+
+ // collect up all form elements found from the passed argument elements all
+ // the way down to child elements; pass a '
+ *
+ * When passing in multiple options, pass them in as separate parameters,
+ * seperated by commas. For example:
+ *
+ *
+ * loadTable("my_csv_file.csv", "csv", "header")
+ *
+ *
+ *
+ * All files loaded and saved use UTF-8 encoding.
+ *
+ * This method is asynchronous, meaning it may not finish before the next
+ * line in your sketch is executed. Calling loadTable() inside preload()
+ * guarantees to complete the operation before setup() and draw() are called.
+ *
Outside of preload(), you may supply a callback function to handle the
+ * object:
+ *
+ *
+ * @method loadTable
+ * @param {String} filename name of the file or URL to load
+ * @param {String|Strings} [options] "header" "csv" "tsv"
+ * @param {Function} [callback] function to be executed after
+ * loadTable() completes. On success, the
+ * Table object is passed in as the
+ * first argument; otherwise, false
+ * is passed in.
+ * @return {Object} Table object containing data
+ *
+ * @example
+ *
+ *
+ * // Given the following CSV file called "mammals.csv"
+ * // located in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * //the file can be remote
+ * //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
+ * // "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //count the columns
+ * print(table.getRowCount() + " total rows in table");
+ * print(table.getColumnCount() + " total columns in table");
+ *
+ * print(table.getColumn("name"));
+ * //["Goat", "Leopard", "Zebra"]
+ *
+ * //cycle through the table
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++) {
+ * print(table.getString(r, c));
+ * }
+ * }
+ *
+ *
+ *
+ * @alt
+ * randomly generated text from a file, for example "i smell like butter"
+ * randomly generated text from a file, for example "i have three feet"
+ *
+ */
+p5.prototype.loadTable = function (path) {
+ var callback = null;
+ var options = [];
+ var header = false;
+ var sep = ',';
+ var separatorSet = false;
+ var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
+
+ for (var i = 1; i < arguments.length; i++) {
+ if ((typeof (arguments[i]) === 'function') &&
+ (arguments[i] !== decrementPreload)) {
+ callback = arguments[i];
+ } else if (typeof (arguments[i]) === 'string') {
+ options.push(arguments[i]);
+ if (arguments[i] === 'header') {
+ header = true;
+ }
+ if (arguments[i] === 'csv') {
+ if (separatorSet) {
+ throw new Error('Cannot set multiple separator types.');
+ } else {
+ sep = ',';
+ separatorSet = true;
+ }
+ } else if (arguments[i] === 'tsv') {
+ if (separatorSet) {
+ throw new Error('Cannot set multiple separator types.');
+ } else {
+ sep = '\t';
+ separatorSet = true;
+ }
+ }
+ }
+ }
+
+ var t = new p5.Table();
+ reqwest({
+ url: path,
+ crossOrigin: true,
+ type: 'csv'
+ })
+ .then(function (resp) {
+ resp = resp.responseText;
+
+ var state = {};
+
+ // define constants
+ var PRE_TOKEN = 0,
+ MID_TOKEN = 1,
+ POST_TOKEN = 2,
+ POST_RECORD = 4;
+
+ var QUOTE = '\"',
+ CR = '\r',
+ LF = '\n';
+
+ var records = [];
+ var offset = 0;
+ var currentRecord = null;
+ var currentChar;
+
+ var recordBegin = function () {
+ state.escaped = false;
+ currentRecord = [];
+ tokenBegin();
+ };
+
+ var recordEnd = function () {
+ state.currentState = POST_RECORD;
+ records.push(currentRecord);
+ currentRecord = null;
+ };
+
+ var tokenBegin = function () {
+ state.currentState = PRE_TOKEN;
+ state.token = '';
+ };
+
+ var tokenEnd = function () {
+ currentRecord.push(state.token);
+ tokenBegin();
+ };
+
+ while (true) {
+ currentChar = resp[offset++];
+
+ // EOF
+ if (currentChar == null) {
+ if (state.escaped) {
+ throw new Error('Unclosed quote in file.');
+ }
+ if (currentRecord) {
+ tokenEnd();
+ recordEnd();
+ break;
+ }
+ }
+ if (currentRecord === null) {
+ recordBegin();
+ }
+
+ // Handle opening quote
+ if (state.currentState === PRE_TOKEN) {
+ if (currentChar === QUOTE) {
+ state.escaped = true;
+ state.currentState = MID_TOKEN;
+ continue;
+ }
+ state.currentState = MID_TOKEN;
+ }
+
+ // mid-token and escaped, look for sequences and end quote
+ if (state.currentState === MID_TOKEN && state.escaped) {
+ if (currentChar === QUOTE) {
+ if (resp[offset] === QUOTE) {
+ state.token += QUOTE;
+ offset++;
+ } else {
+ state.escaped = false;
+ state.currentState = POST_TOKEN;
+ }
+ } else {
+ state.token += currentChar;
+ }
+ continue;
+ }
+
+ // fall-through: mid-token or post-token, not escaped
+ if (currentChar === CR) {
+ if (resp[offset] === LF) {
+ offset++;
+ }
+ tokenEnd();
+ recordEnd();
+ } else if (currentChar === LF) {
+ tokenEnd();
+ recordEnd();
+ } else if (currentChar === sep) {
+ tokenEnd();
+ } else if (state.currentState === MID_TOKEN) {
+ state.token += currentChar;
+ }
+ }
+
+ // set up column names
+ if (header) {
+ t.columns = records.shift();
+ } else {
+ for (i = 0; i < records[0].length; i++) {
+ t.columns[i] = 'null';
+ }
+ }
+ var row;
+ for (i = 0; i < records.length; i++) {
+ //Handles row of 'undefined' at end of some CSVs
+ if (i === records.length - 1 && records[i].length === 1) {
+ if (records[i][0] === 'undefined') {
+ break;
+ }
+ }
+ row = new p5.TableRow();
+ row.arr = records[i];
+ row.obj = makeObject(records[i], t.columns);
+ t.addRow(row);
+ }
+ if (callback !== null) {
+ callback(t);
+ }
+ if (decrementPreload && (callback !== decrementPreload)) {
+ decrementPreload();
+ }
+ })
+ .fail(function (err, msg) {
+ p5._friendlyFileLoadError(2, path);
+ // don't get error callback mixed up with decrementPreload
+ if ((typeof callback === 'function') &&
+ (callback !== decrementPreload)) {
+ callback(false);
+ }
+ });
+
+ return t;
+};
+
+// helper function to turn a row into a JSON object
+function makeObject(row, headers) {
+ var ret = {};
+ headers = headers || [];
+ if (typeof (headers) === 'undefined') {
+ for (var j = 0; j < row.length; j++) {
+ headers[j.toString()] = j;
+ }
+ }
+ for (var i = 0; i < headers.length; i++) {
+ var key = headers[i];
+ var val = row[i];
+ ret[key] = val;
+ }
+ return ret;
+}
+
+/*global parseXML */
+p5.prototype.parseXML = function (two) {
+ var one = new p5.XML();
+ var i;
+ if (two.children.length) {
+ for ( i = 0; i < two.children.length; i++ ) {
+ var node = parseXML(two.children[i]);
+ one.addChild(node);
+ }
+ one.setName(two.nodeName);
+ one._setCont(two.textContent);
+ one._setAttributes(two);
+ for (var j = 0; j < one.children.length; j++) {
+ one.children[j].parent = one;
+ }
+ return one;
+ }
+ else {
+ one.setName(two.nodeName);
+ one._setCont(two.textContent);
+ one._setAttributes(two);
+ return one;
+ }
+};
+
+/**
+ * Reads the contents of a file and creates an XML object with its values.
+ * If the name of the file is used as the parameter, as in the above example,
+ * the file must be located in the sketch directory/folder.
+ *
+ * Alternatively, the file maybe be loaded from anywhere on the local
+ * computer using an absolute path (something that starts with / on Unix and
+ * Linux, or a drive letter on Windows), or the filename parameter can be a
+ * URL for a file found on a network.
+ *
+ * This method is asynchronous, meaning it may not finish before the next
+ * line in your sketch is executed. Calling loadXML() inside preload()
+ * guarantees to complete the operation before setup() and draw() are called.
+ *
+ * Outside of preload(), you may supply a callback function to handle the
+ * object:
+ *
+ * @method loadXML
+ * @param {String} filename name of the file or URL to load
+ * @param {Function} [callback] function to be executed after loadXML()
+ * completes, XML object is passed in as
+ * first argument
+ * @param {Function} [errorCallback] function to be executed if
+ * there is an error, response is passed
+ * in as first argument
+ * @return {Object} XML object containing data
+ */
+p5.prototype.loadXML = function (path, callback, errorCallback) {
+ var ret = {};
+ var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
+ reqwest({
+ url: path,
+ type: 'xml',
+ crossOrigin: true,
+ error: function (resp) {
+ // pass to error callback if defined
+ if (errorCallback) {
+ errorCallback(resp);
+ } else { // otherwise log error msg
+ console.log(resp.statusText);
+ }
+ //p5._friendlyFileLoadError(1,path);
+ }
+ })
+ .then(function (resp) {
+ var xml = parseXML(resp.documentElement);
+ for(var key in xml) {
+ ret[key] = xml[key];
+ }
+ if (typeof callback !== 'undefined') {
+ callback(ret);
+ }
+ if (decrementPreload && (callback !== decrementPreload)) {
+ decrementPreload();
+ }
+ });
+ return ret;
+};
+
+// name clash with window.open
+// p5.prototype.open = function() {
+// // TODO
+
+// };
+
+p5.prototype.selectFolder = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+p5.prototype.selectInput = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+/**
+ * Method for executing an HTTP GET request. If data type is not specified,
+ * p5 will try to guess based on the URL, defaulting to text.
+ *
+ * @method httpGet
+ * @param {String} path name of the file or url to load
+ * @param {Object} [data] param data passed sent with request
+ * @param {String} [datatype] "json", "jsonp", "xml", or "text"
+ * @param {Function} [callback] function to be executed after
+ * httpGet() completes, data is passed in
+ * as first argument
+ * @param {Function} [errorCallback] function to be executed if
+ * there is an error, response is passed
+ * in as first argument
+ */
+p5.prototype.httpGet = function () {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ args.push('GET');
+ p5.prototype.httpDo.apply(this, args);
+};
+
+/**
+ * Method for executing an HTTP POST request. If data type is not specified,
+ * p5 will try to guess based on the URL, defaulting to text.
+ *
+ * @method httpPost
+ * @param {String} path name of the file or url to load
+ * @param {Object} [data] param data passed sent with request
+ * @param {String} [datatype] "json", "jsonp", "xml", or "text"
+ * @param {Function} [callback] function to be executed after
+ * httpGet() completes, data is passed in
+ * as first argument
+ * @param {Function} [errorCallback] function to be executed if
+ * there is an error, response is passed
+ * in as first argument
+ */
+p5.prototype.httpPost = function () {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ args.push('POST');
+ p5.prototype.httpDo.apply(this, args);
+};
+
+/**
+ * Method for executing an HTTP request. If data type is not specified,
+ * p5 will try to guess based on the URL, defaulting to text.
+ * You may also pass a single object specifying all parameters for the
+ * request following the examples inside the reqwest() calls here:
+ *
+ * https://github.com/ded/reqwest#api
+ *
+ * @method httpDo
+ * @param {String} path name of the file or url to load
+ * @param {String} [method] either "GET", "POST", or "PUT",
+ * defaults to "GET"
+ * @param {Object} [data] param data passed sent with request
+ * @param {String} [datatype] "json", "jsonp", "xml", or "text"
+ * @param {Function} [callback] function to be executed after
+ * httpGet() completes, data is passed in
+ * as first argument
+ * @param {Function} [errorCallback] function to be executed if
+ * there is an error, response is passed
+ * in as first argument
+ */
+p5.prototype.httpDo = function () {
+ if (typeof arguments[0] === 'object') {
+ reqwest(arguments[0]);
+ } else {
+ var method = 'GET';
+ var path = arguments[0];
+ var data = {};
+ var type = '';
+ var callback;
+ var errorCallback;
+
+ for (var i = 1; i < arguments.length; i++) {
+ var a = arguments[i];
+ if (typeof a === 'string') {
+ if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') {
+ method = a;
+ } else {
+ type = a;
+ }
+ } else if (typeof a === 'object') {
+ data = a;
+ } else if (typeof a === 'function') {
+ if (!callback) {
+ callback = a;
+ } else {
+ errorCallback = a;
+ }
+ }
+ }
+
+ // do some sort of smart type checking
+ if (type === '') {
+ if (path.indexOf('json') !== -1) {
+ type = 'json';
+ } else if (path.indexOf('xml') !== -1) {
+ type = 'xml';
+ } else {
+ type = 'text';
+ }
+ }
+
+ reqwest({
+ url: path,
+ method: method,
+ data: data,
+ type: type,
+ crossOrigin: true,
+ success: function (resp) {
+ if (typeof callback !== 'undefined') {
+ if (type === 'text') {
+ callback(resp.response);
+ } else {
+ callback(resp);
+ }
+ }
+ },
+ error: function (resp) {
+ if (errorCallback) {
+ errorCallback(resp);
+ } else {
+ console.log(resp.statusText);
+ }
+ }
+ });
+ }
+};
+
+/**
+ * @module IO
+ * @submodule Output
+ * @for p5
+ */
+
+window.URL = window.URL || window.webkitURL;
+
+// private array of p5.PrintWriter objects
+p5.prototype._pWriters = [];
+
+p5.prototype.beginRaw = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+p5.prototype.beginRecord = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+p5.prototype.createOutput = function () {
+ // TODO
+
+ throw 'not yet implemented';
+};
+
+p5.prototype.createWriter = function (name, extension) {
+ var newPW;
+ // check that it doesn't already exist
+ for (var i in p5.prototype._pWriters) {
+ if (p5.prototype._pWriters[i].name === name) {
+ // if a p5.PrintWriter w/ this name already exists...
+ // return p5.prototype._pWriters[i]; // return it w/ contents intact.
+ // or, could return a new, empty one with a unique name:
+ newPW = new p5.PrintWriter(name + window.millis(), extension);
+ p5.prototype._pWriters.push(newPW);
+ return newPW;
+ }
+ }
+ newPW = new p5.PrintWriter(name, extension);
+ p5.prototype._pWriters.push(newPW);
+ return newPW;
+};
+
+p5.prototype.endRaw = function () {
+ // TODO
+
+ throw 'not yet implemented';
+};
+
+p5.prototype.endRecord = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+p5.PrintWriter = function (filename, extension) {
+ var self = this;
+ this.name = filename;
+ this.content = '';
+ this.print = function (data) {
+ this.content += data;
+ };
+ this.print = function (data) {
+ this.content += data + '\n';
+ };
+ this.flush = function () {
+ this.content = '';
+ };
+ this.close = function () {
+ // convert String to Array for the writeFile Blob
+ var arr = [];
+ arr.push(this.content);
+ p5.prototype.writeFile(arr, filename, extension);
+ // remove from _pWriters array and delete self
+ for (var i in p5.prototype._pWriters) {
+ if (p5.prototype._pWriters[i].name === this.name) {
+ // remove from _pWriters array
+ p5.prototype._pWriters.splice(i, 1);
+ }
+ }
+ self.flush();
+ self = {};
+ };
+};
+
+p5.prototype.saveBytes = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+// object, filename, options --> saveJSON, saveStrings, saveTable
+// filename, [extension] [canvas] --> saveImage
+
+/**
+ * Save an image, text, json, csv, wav, or html. Prompts download to
+ * the client's computer. Note that it is not recommended to call save()
+ * within draw if it's looping, as the save() function will open a new save
+ * dialog every frame.
+ * The default behavior is to save the canvas as an image. You can
+ * optionally specify a filename.
+ * For example:
+ *
+ * save();
+ * save('myCanvas.jpg'); // save a specific canvas with a filename
+ *
+ *
+ * Alternately, the first parameter can be a pointer to a canvas
+ * p5.Element, an Array of Strings,
+ * an Array of JSON, a JSON object, a p5.Table, a p5.Image, or a
+ * p5.SoundFile (requires p5.sound). The second parameter is a filename
+ * (including extension). The third parameter is for options specific
+ * to this type of object. This method will save a file that fits the
+ * given paramaters. For example:
+ *
+ *
+ *
+ * save('myCanvas.jpg'); // Saves canvas as an image
+ *
+ * var cnv = createCanvas(100, 100);
+ * save(cnv, 'myCanvas.jpg'); // Saves canvas as an image
+ *
+ * var gb = createGraphics(100, 100);
+ * save(gb, 'myGraphics.jpg'); // Saves p5.Renderer object as an image
+ *
+ * save(myTable, 'myTable.html'); // Saves table as html file
+ * save(myTable, 'myTable.csv',); // Comma Separated Values
+ * save(myTable, 'myTable.tsv'); // Tab Separated Values
+ *
+ * save(myJSON, 'my.json'); // Saves pretty JSON
+ * save(myJSON, 'my.json', true); // Optimizes JSON filesize
+ *
+ * save(img, 'my.png'); // Saves pImage as a png image
+ *
+ * save(arrayOfStrings, 'my.txt'); // Saves strings to a text file with line
+ * // breaks after each item in the array
+ *
+ *
+ * @method save
+ * @param {[Object|String]} objectOrFilename If filename is provided, will
+ * save canvas as an image with
+ * either png or jpg extension
+ * depending on the filename.
+ * If object is provided, will
+ * save depending on the object
+ * and filename (see examples
+ * above).
+ * @param {[String]} filename If an object is provided as the first
+ * parameter, then the second parameter
+ * indicates the filename,
+ * and should include an appropriate
+ * file extension (see examples above).
+ * @param {[Boolean/String]} options Additional options depend on
+ * filetype. For example, when saving JSON,
+ * true indicates that the
+ * output will be optimized for filesize,
+ * rather than readability.
+ */
+p5.prototype.save = function (object, _filename, _options) {
+ // parse the arguments and figure out which things we are saving
+ var args = arguments;
+ // =================================================
+ // OPTION 1: saveCanvas...
+
+ // if no arguments are provided, save canvas
+ var cnv = this._curElement.elt;
+ if (args.length === 0) {
+ p5.prototype.saveCanvas(cnv);
+ return;
+ }
+ // otherwise, parse the arguments
+
+ // if first param is a p5Graphics, then saveCanvas
+ else if (args[0] instanceof p5.Renderer ||
+ args[0] instanceof p5.Graphics) {
+ p5.prototype.saveCanvas(args[0].elt, args[1], args[2]);
+ return;
+ }
+
+ // if 1st param is String and only one arg, assume it is canvas filename
+ else if (args.length === 1 && typeof (args[0]) === 'string') {
+ p5.prototype.saveCanvas(cnv, args[0]);
+ }
+
+ // =================================================
+ // OPTION 2: extension clarifies saveStrings vs. saveJSON
+ else {
+ var extension = _checkFileExtension(args[1], args[2])[1];
+ switch (extension) {
+ case 'json':
+ p5.prototype.saveJSON(args[0], args[1], args[2]);
+ return;
+ case 'txt':
+ p5.prototype.saveStrings(args[0], args[1], args[2]);
+ return;
+ // =================================================
+ // OPTION 3: decide based on object...
+ default:
+ if (args[0] instanceof Array) {
+ p5.prototype.saveStrings(args[0], args[1], args[2]);
+ } else if (args[0] instanceof p5.Table) {
+ p5.prototype.saveTable(args[0], args[1], args[2], args[3]);
+ } else if (args[0] instanceof p5.Image) {
+ p5.prototype.saveCanvas(args[0].canvas, args[1]);
+ } else if (args[0] instanceof p5.SoundFile) {
+ p5.prototype.saveSound(args[0], args[1], args[2], args[3]);
+ }
+ }
+ }
+};
+
+/**
+ * Writes the contents of an Array or a JSON object to a .json file.
+ * The file saving process and location of the saved file will
+ * vary between web browsers.
+ *
+ * @method saveJSON
+ * @param {Array|Object} json
+ * @param {String} filename
+ * @param {Boolean} [optimize] If true, removes line breaks
+ * and spaces from the output
+ * file to optimize filesize
+ * (but not readability).
+ * @example
+ *
+ * var json;
+ *
+ * function setup() {
+ *
+ * json = {}; // new JSON Object
+ *
+ * json.id = 0;
+ * json.species = 'Panthera leo';
+ * json.name = 'Lion';
+ *
+ * // To save, un-comment the line below, then click 'run'
+ * // saveJSON(json, 'lion.json');
+ * }
+ *
+ * // Saves the following to a file called "lion.json":
+ * // {
+ * // "id": 0,
+ * // "species": "Panthera leo",
+ * // "name": "Lion"
+ * // }
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.prototype.saveJSON = function (json, filename, opt) {
+ var stringify;
+ if (opt) {
+ stringify = JSON.stringify(json);
+ } else {
+ stringify = JSON.stringify(json, undefined, 2);
+ }
+ console.log(stringify);
+ this.saveStrings(stringify.split('\n'), filename, 'json');
+};
+
+p5.prototype.saveJSONObject = p5.prototype.saveJSON;
+p5.prototype.saveJSONArray = p5.prototype.saveJSON;
+
+p5.prototype.saveStream = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+/**
+ * Writes an array of Strings to a text file, one line per String.
+ * The file saving process and location of the saved file will
+ * vary between web browsers.
+ *
+ * @method saveStrings
+ * @param {Array} list string array to be written
+ * @param {String} filename filename for output
+ * @example
+ *
+ * var words = 'apple bear cat dog';
+ *
+ * // .split() outputs an Array
+ * var list = split(words, ' ');
+ *
+ * // To save the file, un-comment next line and click 'run'
+ * // saveStrings(list, 'nouns.txt');
+ *
+ * // Saves the following to a file called 'nouns.txt':
+ * //
+ * // apple
+ * // bear
+ * // cat
+ * // dog
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.prototype.saveStrings = function (list, filename, extension) {
+ var ext = extension || 'txt';
+ var pWriter = this.createWriter(filename, ext);
+ for (var i = 0; i < list.length; i++) {
+ if (i < list.length - 1) {
+ pWriter.print(list[i]);
+ } else {
+ pWriter.print(list[i]);
+ }
+ }
+ pWriter.close();
+ pWriter.flush();
+};
+
+p5.prototype.saveXML = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+p5.prototype.selectOutput = function () {
+ // TODO
+ throw 'not yet implemented';
+
+};
+
+// =======
+// HELPERS
+// =======
+
+function escapeHelper(content) {
+ return content
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+}
+
+/**
+ * Writes the contents of a Table object to a file. Defaults to a
+ * text file with comma-separated-values ('csv') but can also
+ * use tab separation ('tsv'), or generate an HTML table ('html').
+ * The file saving process and location of the saved file will
+ * vary between web browsers.
+ *
+ * @method saveTable
+ * @param {p5.Table} Table the Table object to save to a file
+ * @param {String} filename the filename to which the Table should be saved
+ * @param {String} [options] can be one of "tsv", "csv", or "html"
+ * @example
+ *
+ * var table;
+ *
+ * function setup() {
+ * table = new p5.Table();
+ *
+ * table.addColumn('id');
+ * table.addColumn('species');
+ * table.addColumn('name');
+ *
+ * var newRow = table.addRow();
+ * newRow.setNum('id', table.getRowCount() - 1);
+ * newRow.setString('species', 'Panthera leo');
+ * newRow.setString('name', 'Lion');
+ *
+ * // To save, un-comment next line then click 'run'
+ * // saveTable(table, 'new.csv');
+ * }
+ *
+ * // Saves the following to a file called 'new.csv':
+ * // id,species,name
+ * // 0,Panthera leo,Lion
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.prototype.saveTable = function (table, filename, options) {
+ var pWriter = this.createWriter(filename, options);
+
+ var header = table.columns;
+
+ var sep = ','; // default to CSV
+ if (options === 'tsv') {
+ sep = '\t';
+ }
+ if (options !== 'html') {
+ // make header if it has values
+ if (header[0] !== '0') {
+ for (var h = 0; h < header.length; h++) {
+ if (h < header.length - 1) {
+ pWriter.print(header[h] + sep);
+ } else {
+ pWriter.print(header[h]);
+ }
+ }
+ }
+
+ // make rows
+ for (var i = 0; i < table.rows.length; i++) {
+ var j;
+ for (j = 0; j < table.rows[i].arr.length; j++) {
+ if (j < table.rows[i].arr.length - 1) {
+ pWriter.print(table.rows[i].arr[j] + sep);
+ } else if (i < table.rows.length - 1) {
+ pWriter.print(table.rows[i].arr[j]);
+ } else {
+ pWriter.print(table.rows[i].arr[j]); // no line break
+ }
+ }
+ }
+ }
+
+ // otherwise, make HTML
+ else {
+ pWriter.print('');
+ pWriter.print('');
+ var str = ' ';
+ pWriter.print(str);
+ pWriter.print('');
+
+ pWriter.print('');
+ pWriter.print(' ');
+
+ // make header if it has values
+ if (header[0] !== '0') {
+ pWriter.print(' ');
+ for (var k = 0; k < header.length; k++) {
+ var e = escapeHelper(header[k]);
+ pWriter.print(' | ' + e);
+ pWriter.print(' | ');
+ }
+ pWriter.print('
');
+ }
+
+ // make rows
+ for (var row = 0; row < table.rows.length; row++) {
+ pWriter.print(' ');
+ for (var col = 0; col < table.columns.length; col++) {
+ var entry = table.rows[row].getString(col);
+ var htmlEntry = escapeHelper(entry);
+ pWriter.print(' | ' + htmlEntry);
+ pWriter.print(' | ');
+ }
+ pWriter.print('
');
+ }
+ pWriter.print('
');
+ pWriter.print('');
+ pWriter.print('');
+ }
+ // close and flush the pWriter
+ pWriter.close();
+ pWriter.flush();
+}; // end saveTable()
+
+/**
+ * Generate a blob of file data as a url to prepare for download.
+ * Accepts an array of data, a filename, and an extension (optional).
+ * This is a private function because it does not do any formatting,
+ * but it is used by saveStrings, saveJSON, saveTable etc.
+ *
+ * @param {Array} dataToDownload
+ * @param {String} filename
+ * @param {[String]} extension
+ * @private
+ */
+p5.prototype.writeFile = function (dataToDownload, filename, extension) {
+ var type = 'application\/octet-stream';
+ if (p5.prototype._isSafari()) {
+ type = 'text\/plain';
+ }
+ var blob = new Blob(dataToDownload, {
+ 'type': type
+ });
+ var href = window.URL.createObjectURL(blob);
+ p5.prototype.downloadFile(href, filename, extension);
+};
+
+/**
+ * Forces download. Accepts a url to filedata/blob, a filename,
+ * and an extension (optional).
+ * This is a private function because it does not do any formatting,
+ * but it is used by saveStrings, saveJSON, saveTable etc.
+ *
+ * @param {String} href i.e. an href generated by createObjectURL
+ * @param {[String]} filename
+ * @param {[String]} extension
+ */
+p5.prototype.downloadFile = function (href, fName, extension) {
+ var fx = _checkFileExtension(fName, extension);
+ var filename = fx[0];
+ var ext = fx[1];
+
+ var a = document.createElement('a');
+ a.href = href;
+ a.download = filename;
+
+ // Firefox requires the link to be added to the DOM before click()
+ a.onclick = function(e) {
+ destroyClickedElement(e);
+ e.stopPropagation();
+ };
+
+ a.style.display = 'none';
+ document.body.appendChild(a);
+
+ // Safari will open this file in the same page as a confusing Blob.
+ if (p5.prototype._isSafari()) {
+ var aText = 'Hello, Safari user! To download this file...\n';
+ aText += '1. Go to File --> Save As.\n';
+ aText += '2. Choose "Page Source" as the Format.\n';
+ aText += '3. Name it with this extension: .\"' + ext + '\"';
+ alert(aText);
+ }
+ a.click();
+ href = null;
+};
+
+/**
+ * Returns a file extension, or another string
+ * if the provided parameter has no extension.
+ *
+ * @param {String} filename
+ * @return {Array} [fileName, fileExtension]
+ *
+ * @private
+ */
+function _checkFileExtension(filename, extension) {
+ if (!extension || extension === true || extension === 'true') {
+ extension = '';
+ }
+ if (!filename) {
+ filename = 'untitled';
+ }
+ var ext = '';
+ // make sure the file will have a name, see if filename needs extension
+ if (filename && filename.indexOf('.') > -1) {
+ ext = filename.split('.').pop();
+ }
+ // append extension if it doesn't exist
+ if (extension) {
+ if (ext !== extension) {
+ ext = extension;
+ filename = filename + '.' + ext;
+ }
+ }
+ return [filename, ext];
+}
+p5.prototype._checkFileExtension = _checkFileExtension;
+
+/**
+ * Returns true if the browser is Safari, false if not.
+ * Safari makes trouble for downloading files.
+ *
+ * @return {Boolean} [description]
+ * @private
+ */
+p5.prototype._isSafari = function () {
+ var x = Object.prototype.toString.call(window.HTMLElement);
+ return x.indexOf('Constructor') > 0;
+};
+
+/**
+ * Helper function, a callback for download that deletes
+ * an invisible anchor element from the DOM once the file
+ * has been automatically downloaded.
+ *
+ * @private
+ */
+function destroyClickedElement(event) {
+ document.body.removeChild(event.target);
+}
+
+module.exports = p5;
+
+},{"../core/core":37,"../core/error_helpers":40,"opentype.js":8,"reqwest":27}],60:[function(_dereq_,module,exports){
+/**
+ * @module IO
+ * @submodule Table
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+
+/**
+ * Table Options
+ * Generic class for handling tabular data, typically from a
+ * CSV, TSV, or other sort of spreadsheet file.
+ * CSV files are
+ *
+ * comma separated values, often with the data in quotes. TSV
+ * files use tabs as separators, and usually don't bother with the
+ * quotes.
+ * File names should end with .csv if they're comma separated.
+ * A rough "spec" for CSV can be found
+ * here.
+ * To load files, use the loadTable method.
+ * To save tables to your computer, use the save method
+ * or the saveTable method.
+ *
+ * Possible options include:
+ *
+ * - csv - parse the table as comma-separated values
+ *
- tsv - parse the table as tab-separated values
+ *
- header - this table has a header (title) row
+ *
+ */
+
+/**
+ * Table objects store data with multiple rows and columns, much
+ * like in a traditional spreadsheet. Tables can be generated from
+ * scratch, dynamically, or using data from an existing file.
+ *
+ * @class p5.Table
+ * @constructor
+ * @param {Array} [rows] An array of p5.TableRow objects
+ * @return {p5.Table} p5.Table generated
+ */
+p5.Table = function (rows) {
+ /**
+ * @property columns
+ * @type {Array}
+ */
+ this.columns = [];
+
+ /**
+ * @property rows
+ * @type {Array}
+ */
+ this.rows = [];
+};
+
+/**
+ * Use addRow() to add a new row of data to a p5.Table object. By default,
+ * an empty row is created. Typically, you would store a reference to
+ * the new row in a TableRow object (see newRow in the example above),
+ * and then set individual values using set().
+ *
+ * If a p5.TableRow object is included as a parameter, then that row is
+ * duplicated and added to the table.
+ *
+ * @method addRow
+ * @param {p5.TableRow} [row] row to be added to the table
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //add a row
+ * var newRow = table.addRow();
+ * newRow.setString("id", table.getRowCount() - 1);
+ * newRow.setString("species", "Canis Lupus");
+ * newRow.setString("name", "Wolf");
+ *
+ * //print the results
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(table.getString(r, c));
+ * }
+ *
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.addRow = function(row) {
+ // make sure it is a valid TableRow
+ var r = row || new p5.TableRow();
+
+ if (typeof(r.arr) === 'undefined' || typeof(r.obj) === 'undefined') {
+ //r = new p5.prototype.TableRow(r);
+ throw 'invalid TableRow: ' + r;
+ }
+ r.table = this;
+ this.rows.push(r);
+ return r;
+};
+
+/**
+ * Removes a row from the table object.
+ *
+ * @method removeRow
+ * @param {Number} id ID number of the row to remove
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //remove the first row
+ * var r = table.removeRow(0);
+ *
+ * //print the results
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(table.getString(r, c));
+ * }
+ *
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.removeRow = function(id) {
+ this.rows[id].table = null; // remove reference to table
+ var chunk = this.rows.splice(id+1, this.rows.length);
+ this.rows.pop();
+ this.rows = this.rows.concat(chunk);
+};
+
+
+/**
+ * Returns a reference to the specified p5.TableRow. The reference
+ * can then be used to get and set values of the selected row.
+ *
+ * @method getRow
+ * @param {Number} rowID ID number of the row to get
+ * @return {TableRow} p5.TableRow object
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * var row = table.getRow(1);
+ * //print it column by column
+ * //note: a row is an object, not an array
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(row.getString(c));
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getRow = function(r) {
+ return this.rows[r];
+};
+
+/**
+ * Gets all rows from the table. Returns an array of p5.TableRows.
+ *
+ * @method getRows
+ * @return {Array} Array of p5.TableRows
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * var rows = table.getRows();
+ *
+ * //warning: rows is an array of objects
+ * for (var r = 0; r < rows.length; r++)
+ * rows[r].set("name", "Unicorn");
+ *
+ * //print the results
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(table.getString(r, c));
+ * }
+ *
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getRows = function() {
+ return this.rows;
+};
+
+/**
+ * Finds the first row in the Table that contains the value
+ * provided, and returns a reference to that row. Even if
+ * multiple rows are possible matches, only the first matching
+ * row is returned. The column to search may be specified by
+ * either its ID or title.
+ *
+ * @method findRow
+ * @param {String} value The value to match
+ * @param {Number|String} column ID number or title of the
+ * column to search
+ * @return {TableRow}
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //find the animal named zebra
+ * var row = table.findRow("Zebra", "name");
+ * //find the corresponding species
+ * print(row.getString("species"));
+ * }
+ *
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.findRow = function(value, column) {
+ // try the Object
+ if (typeof(column) === 'string') {
+ for (var i = 0; i < this.rows.length; i++){
+ if (this.rows[i].obj[column] === value) {
+ return this.rows[i];
+ }
+ }
+ }
+ // try the Array
+ else {
+ for (var j = 0; j < this.rows.length; j++){
+ if (this.rows[j].arr[column] === value) {
+ return this.rows[j];
+ }
+ }
+ }
+ // otherwise...
+ return null;
+};
+
+/**
+ * Finds the rows in the Table that contain the value
+ * provided, and returns references to those rows. Returns an
+ * Array, so for must be used to iterate through all the rows,
+ * as shown in the example above. The column to search may be
+ * specified by either its ID or title.
+ *
+ * @method findRows
+ * @param {String} value The value to match
+ * @param {Number|String} column ID number or title of the
+ * column to search
+ * @return {Array} An Array of TableRow objects
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //add another goat
+ * var newRow = table.addRow();
+ * newRow.setString("id", table.getRowCount() - 1);
+ * newRow.setString("species", "Scape Goat");
+ * newRow.setString("name", "Goat");
+ *
+ * //find the rows containing animals named Goat
+ * var rows = table.findRows("Goat", "name");
+ * print(rows.length + " Goats found");
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.findRows = function(value, column) {
+ var ret = [];
+ if (typeof(column) === 'string') {
+ for (var i = 0; i < this.rows.length; i++){
+ if (this.rows[i].obj[column] === value) {
+ ret.push( this.rows[i] );
+ }
+ }
+ }
+ // try the Array
+ else {
+ for (var j = 0; j < this.rows.length; j++){
+ if (this.rows[j].arr[column] === value) {
+ ret.push( this.rows[j] );
+ }
+ }
+ }
+ return ret;
+};
+
+/**
+ * Finds the first row in the Table that matches the regular
+ * expression provided, and returns a reference to that row.
+ * Even if multiple rows are possible matches, only the first
+ * matching row is returned. The column to search may be
+ * specified by either its ID or title.
+ *
+ * @method matchRow
+ * @param {String} regexp The regular expression to match
+ * @param {String|Number} column The column ID (number) or
+ * title (string)
+ * @return {TableRow} TableRow object
+ */
+p5.Table.prototype.matchRow = function(regexp, column) {
+ if (typeof(column) === 'number') {
+ for (var j = 0; j < this.rows.length; j++) {
+ if ( this.rows[j].arr[column].match(regexp) ) {
+ return this.rows[j];
+ }
+ }
+ }
+
+ else {
+ for (var i = 0; i < this.rows.length; i++) {
+ if ( this.rows[i].obj[column].match(regexp) ) {
+ return this.rows[i];
+ }
+ }
+ }
+ return null;
+};
+
+/**
+ * Finds the rows in the Table that match the regular expression provided,
+ * and returns references to those rows. Returns an array, so for must be
+ * used to iterate through all the rows, as shown in the example. The
+ * column to search may be specified by either its ID or title.
+ *
+ * @method matchRows
+ * @param {String} regexp The regular expression to match
+ * @param {String|Number} [column] The column ID (number) or
+ * title (string)
+ * @return {Array} An Array of TableRow objects
+ * @example
+ * var table;
+ *
+ * function setup() {
+ *
+ * table = new p5.Table();
+ *
+ * table.addColumn('name');
+ * table.addColumn('type');
+ *
+ * var newRow = table.addRow();
+ * newRow.setString('name', 'Lion');
+ * newRow.setString('type', 'Mammal');
+ *
+ * newRow = table.addRow();
+ * newRow.setString('name', 'Snake');
+ * newRow.setString('type', 'Reptile');
+ *
+ * newRow = table.addRow();
+ * newRow.setString('name', 'Mosquito');
+ * newRow.setString('type', 'Insect');
+ *
+ * newRow = table.addRow();
+ * newRow.setString('name', 'Lizard');
+ * newRow.setString('type', 'Reptile');
+ *
+ * var rows = table.matchRows('R.*', 'type');
+ * for (var i = 0; i < rows.length; i++) {
+ * print(rows[i].getString('name') + ': ' + rows[i].getString('type'));
+ * }
+ * }
+ * // Sketch prints:
+ * // Snake: Reptile
+ * // Lizard: Reptile
+ */
+p5.Table.prototype.matchRows = function(regexp, column) {
+ var ret = [];
+ if (typeof(column) === 'number') {
+ for (var j = 0; j < this.rows.length; j++) {
+ if ( this.rows[j].arr[column].match(regexp) ) {
+ ret.push( this.rows[j] );
+ }
+ }
+ }
+
+ else {
+ for (var i = 0; i < this.rows.length; i++) {
+ if ( this.rows[i].obj[column].match(regexp) ) {
+ ret.push( this.rows[i] );
+ }
+ }
+ }
+ return ret;
+};
+
+
+/**
+ * Retrieves all values in the specified column, and returns them
+ * as an array. The column may be specified by either its ID or title.
+ *
+ * @method getColumn
+ * @param {String|Number} column String or Number of the column to return
+ * @return {Array} Array of column values
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * //getColumn returns an array that can be printed directly
+ * print(table.getColumn("species"));
+ * //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getColumn = function(value) {
+ var ret = [];
+ if (typeof(value) === 'string'){
+ for (var i = 0; i < this.rows.length; i++){
+ ret.push (this.rows[i].obj[value]);
+ }
+ } else {
+ for (var j = 0; j < this.rows.length; j++){
+ ret.push (this.rows[j].arr[value]);
+ }
+ }
+ return ret;
+};
+
+/**
+ * Removes all rows from a Table. While all rows are removed,
+ * columns and column titles are maintained.
+ *
+ * @method clearRows
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * table.clearRows();
+ * print(table.getRowCount() + " total rows in table");
+ * print(table.getColumnCount() + " total columns in table");
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.clearRows = function() {
+ delete this.rows;
+ this.rows = [];
+};
+
+/**
+ * Use addColumn() to add a new column to a Table object.
+ * Typically, you will want to specify a title, so the column
+ * may be easily referenced later by name. (If no title is
+ * specified, the new column's title will be null.)
+ *
+ * @method addColumn
+ * @param {String} [title] title of the given column
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * table.addColumn("carnivore");
+ * table.set(0, "carnivore", "no");
+ * table.set(1, "carnivore", "yes");
+ * table.set(2, "carnivore", "no");
+ *
+ * //print the results
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(table.getString(r, c));
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.addColumn = function(title) {
+ var t = title || null;
+ this.columns.push(t);
+};
+
+/**
+ * Returns the total number of columns in a Table.
+ *
+ * @return {Number} Number of columns in this table
+ */
+p5.Table.prototype.getColumnCount = function() {
+ return this.columns.length;
+};
+
+/**
+ * Returns the total number of rows in a Table.
+ *
+ * @method getRowCount
+ * @return {Number} Number of rows in this table
+
+ */
+p5.Table.prototype.getRowCount = function() {
+ return this.rows.length;
+};
+
+/**
+ * Removes any of the specified characters (or "tokens").
+ *
+ * If no column is specified, then the values in all columns and
+ * rows are processed. A specific column may be referenced by
+ * either its ID or title.
+ *
+ * @method removeTokens
+ * @param {String} chars String listing characters to be removed
+ * @param {String|Number} [column] Column ID (number)
+ * or name (string)
+ */
+p5.Table.prototype.removeTokens = function(chars, column) {
+ var escape= function(s) {
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+ };
+ var charArray = [];
+ for (var i = 0; i < chars.length; i++) {
+ charArray.push( escape( chars.charAt(i) ) );
+ }
+ var regex = new RegExp(charArray.join('|'), 'g');
+
+ if (typeof(column) === 'undefined'){
+ for (var c = 0; c < this.columns.length; c++) {
+ for (var d = 0; d < this.rows.length; d++) {
+ var s = this.rows[d].arr[c];
+ s = s.replace(regex, '');
+ this.rows[d].arr[c] = s;
+ this.rows[d].obj[this.columns[c]] = s;
+ }
+ }
+ }
+ else if (typeof(column) === 'string'){
+ for (var j = 0; j < this.rows.length; j++) {
+ var val = this.rows[j].obj[column];
+ val = val.replace(regex, '');
+ this.rows[j].obj[column] = val;
+ var pos = this.columns.indexOf(column);
+ this.rows[j].arr[pos] = val;
+ }
+ }
+ else {
+ for (var k = 0; k < this.rows.length; k++) {
+ var str = this.rows[k].arr[column];
+ str = str.replace(regex, '');
+ this.rows[k].arr[column] = str;
+ this.rows[k].obj[this.columns[column]] = str;
+ }
+ }
+};
+
+/**
+ * Trims leading and trailing whitespace, such as spaces and tabs,
+ * from String table values. If no column is specified, then the
+ * values in all columns and rows are trimmed. A specific column
+ * may be referenced by either its ID or title.
+ *
+ * @method trim
+ * @param {String|Number} column Column ID (number)
+ * or name (string)
+ */
+p5.Table.prototype.trim = function(column) {
+ var regex = new RegExp( (' '), 'g');
+
+ if (typeof(column) === 'undefined'){
+ for (var c = 0; c < this.columns.length; c++) {
+ for (var d = 0; d < this.rows.length; d++) {
+ var s = this.rows[d].arr[c];
+ s = s.replace(regex, '');
+ this.rows[d].arr[c] = s;
+ this.rows[d].obj[this.columns[c]] = s;
+ }
+ }
+ }
+ else if (typeof(column) === 'string'){
+ for (var j = 0; j < this.rows.length; j++) {
+ var val = this.rows[j].obj[column];
+ val = val.replace(regex, '');
+ this.rows[j].obj[column] = val;
+ var pos = this.columns.indexOf(column);
+ this.rows[j].arr[pos] = val;
+ }
+ }
+ else {
+ for (var k = 0; k < this.rows.length; k++) {
+ var str = this.rows[k].arr[column];
+ str = str.replace(regex, '');
+ this.rows[k].arr[column] = str;
+ this.rows[k].obj[this.columns[column]] = str;
+ }
+ }
+};
+
+/**
+ * Use removeColumn() to remove an existing column from a Table
+ * object. The column to be removed may be identified by either
+ * its title (a String) or its index value (an int).
+ * removeColumn(0) would remove the first column, removeColumn(1)
+ * would remove the second column, and so on.
+ *
+ * @method removeColumn
+ * @param {String|Number} column columnName (string) or ID (number)
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * table.removeColumn("id");
+ * print(table.getColumnCount());
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.removeColumn = function(c) {
+ var cString;
+ var cNumber;
+ if (typeof(c) === 'string') {
+ // find the position of c in the columns
+ cString = c;
+ cNumber = this.columns.indexOf(c);
+ console.log('string');
+ }
+ else{
+ cNumber = c;
+ cString = this.columns[c];
+ }
+
+ var chunk = this.columns.splice(cNumber+1, this.columns.length);
+ this.columns.pop();
+ this.columns = this.columns.concat(chunk);
+
+ for (var i = 0; i < this.rows.length; i++){
+ var tempR = this.rows[i].arr;
+ var chip = tempR.splice(cNumber+1, tempR.length);
+ tempR.pop();
+ this.rows[i].arr = tempR.concat(chip);
+ delete this.rows[i].obj[cString];
+ }
+
+};
+
+
+/**
+ * Stores a value in the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified
+ * by either its ID or title.
+ *
+ * @method set
+ * @param {String|Number} column column ID (Number)
+ * or title (String)
+ * @param {String|Number} value value to assign
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * table.set(0, "species", "Canis Lupus");
+ * table.set(0, "name", "Wolf");
+ *
+ * //print the results
+ * for (var r = 0; r < table.getRowCount(); r++)
+ * for (var c = 0; c < table.getColumnCount(); c++)
+ * print(table.getString(r, c));
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.set = function(row, column, value) {
+ this.rows[row].set(column, value);
+};
+
+/**
+ * Stores a Float value in the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified
+ * by either its ID or title.
+ *
+ * @method setNum
+ * @param {Number} row row ID
+ * @param {String|Number} column column ID (Number)
+ * or title (String)
+ * @param {Number} value value to assign
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * table.setNum(1, "id", 1);
+ *
+ * print(table.getColumn(0));
+ * //["0", 1, "2"]
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ */
+p5.Table.prototype.setNum = function(row, column, value){
+ this.rows[row].setNum(column, value);
+};
+
+
+/**
+ * Stores a String value in the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified
+ * by either its ID or title.
+ *
+ * @method setString
+ * @param {Number} row row ID
+ * @param {String|Number} column column ID (Number)
+ * or title (String)
+ * @param {String} value value to assign
+ */
+p5.Table.prototype.setString = function(row, column, value){
+ this.rows[row].setString(column, value);
+};
+
+/**
+ * Retrieves a value from the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified by
+ * either its ID or title.
+ *
+ * @method get
+ * @param {Number} row row ID
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {String|Number}
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * print(table.get(0, 1));
+ * //Capra hircus
+ * print(table.get(0, "species"));
+ * //Capra hircus
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.get = function(row, column) {
+ return this.rows[row].get(column);
+};
+
+/**
+ * Retrieves a Float value from the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified by
+ * either its ID or title.
+ *
+ * @method getNum
+ * @param {Number} row row ID
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {Number}
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * print(table.getNum(1, 0) + 100);
+ * //id 1 + 100 = 101
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getNum = function(row, column) {
+ return this.rows[row].getNum(column);
+};
+
+/**
+ * Retrieves a String value from the Table's specified row and column.
+ * The row is specified by its ID, while the column may be specified by
+ * either its ID or title.
+ *
+ * @method getString
+ * @param {Number} row row ID
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {String}
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * var tableArray = table.getArray();
+ *
+ * //output each row as array
+ * for (var i = 0; i < tableArray.length; i++)
+ * print(tableArray[i]);
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getString = function(row, column) {
+ return this.rows[row].getString(column);
+};
+
+/**
+ * Retrieves all table data and returns as an object. If a column name is
+ * passed in, each row object will be stored with that attribute as its
+ * title.
+ *
+ * @method getObject
+ * @param {String} headerColumn Name of the column which should be used to
+ * title each row object (optional)
+ * @return {Object}
+ *
+ * @example
+ *
+ *
+ * // Given the CSV file "mammals.csv"
+ * // in the project's "assets" folder:
+ * //
+ * // id,species,name
+ * // 0,Capra hircus,Goat
+ * // 1,Panthera pardus,Leopard
+ * // 2,Equus zebra,Zebra
+ *
+ * var table;
+ *
+ * function preload() {
+ * //my table is comma separated value "csv"
+ * //and has a header specifying the columns labels
+ * table = loadTable("assets/mammals.csv", "csv", "header");
+ * }
+ *
+ * function setup() {
+ * var tableObject = table.getObject();
+ *
+ * print(tableObject);
+ * //outputs an object
+ * }
+ *
+ *
+ *
+ *@alt
+ * no image displayed
+ *
+ */
+p5.Table.prototype.getObject = function (headerColumn) {
+ var tableObject = {};
+ var obj, cPos, index;
+
+ for(var i = 0; i < this.rows.length; i++) {
+ obj = this.rows[i].obj;
+
+ if (typeof(headerColumn) === 'string'){
+ cPos = this.columns.indexOf(headerColumn); // index of columnID
+ if (cPos >= 0) {
+ index = obj[headerColumn];
+ tableObject[index] = obj;
+ } else {
+ throw 'This table has no column named "' + headerColumn +'"';
+ }
+ } else {
+ tableObject[i] = this.rows[i].obj;
+ }
+ }
+ return tableObject;
+};
+
+/**
+ * Retrieves all table data and returns it as a multidimensional array.
+ *
+ * @method getArray
+ * @return {Array}
+ */
+p5.Table.prototype.getArray = function () {
+ var tableArray = [];
+ for(var i = 0; i < this.rows.length; i++) {
+ tableArray.push(this.rows[i].arr);
+ }
+ return tableArray;
+};
+
+module.exports = p5.Table;
+
+},{"../core/core":37}],61:[function(_dereq_,module,exports){
+/**
+ * @module IO
+ * @submodule Table
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * A TableRow object represents a single row of data values,
+ * stored in columns, from a table.
+ *
+ * A Table Row contains both an ordered array, and an unordered
+ * JSON object.
+ *
+ * @class p5.TableRow
+ * @constructor
+ * @param {String} [str] optional: populate the row with a
+ * string of values, separated by the
+ * separator
+ * @param {String} [separator] comma separated values (csv) by default
+ */
+p5.TableRow = function (str, separator) {
+ var arr = [];
+ var obj = {};
+ if (str){
+ separator = separator || ',';
+ arr = str.split(separator);
+ }
+ for (var i = 0; i < arr.length; i++){
+ var key = i;
+ var val = arr[i];
+ obj[key] = val;
+ }
+ this.arr = arr;
+ this.obj = obj;
+ this.table = null;
+};
+
+/**
+ * Stores a value in the TableRow's specified column.
+ * The column may be specified by either its ID or title.
+ *
+ * @method set
+ * @param {String|Number} column Column ID (Number)
+ * or Title (String)
+ * @param {String|Number} value The value to be stored
+ */
+p5.TableRow.prototype.set = function(column, value) {
+ // if typeof column is string, use .obj
+ if (typeof(column) === 'string'){
+ var cPos = this.table.columns.indexOf(column); // index of columnID
+ if (cPos >= 0) {
+ this.obj[column] = value;
+ this.arr[cPos] = value;
+ }
+ else {
+ throw 'This table has no column named "' + column +'"';
+ }
+ }
+
+ // if typeof column is number, use .arr
+ else {
+ if (column < this.table.columns.length) {
+ this.arr[column] = value;
+ var cTitle = this.table.columns[column];
+ this.obj[cTitle] = value;
+ }
+ else {
+ throw 'Column #' + column + ' is out of the range of this table';
+ }
+ }
+};
+
+
+/**
+ * Stores a Float value in the TableRow's specified column.
+ * The column may be specified by either its ID or title.
+ *
+ * @method setNum
+ * @param {String|Number} column Column ID (Number)
+ * or Title (String)
+ * @param {Number} value The value to be stored
+ * as a Float
+ */
+p5.TableRow.prototype.setNum = function(column, value){
+ var floatVal = parseFloat(value, 10);
+ this.set(column, floatVal);
+};
+
+
+/**
+ * Stores a String value in the TableRow's specified column.
+ * The column may be specified by either its ID or title.
+ *
+ * @method setString
+ * @param {String|Number} column Column ID (Number)
+ * or Title (String)
+ * @param {String} value The value to be stored
+ * as a String
+ */
+p5.TableRow.prototype.setString = function(column, value){
+ var stringVal = value.toString();
+ this.set(column, stringVal);
+};
+
+/**
+ * Retrieves a value from the TableRow's specified column.
+ * The column may be specified by either its ID or title.
+ *
+ * @method get
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {String|Number}
+ */
+p5.TableRow.prototype.get = function(column) {
+ if (typeof(column) === 'string'){
+ return this.obj[column];
+ } else {
+ return this.arr[column];
+ }
+};
+
+/**
+ * Retrieves a Float value from the TableRow's specified
+ * column. The column may be specified by either its ID or
+ * title.
+ *
+ * @method getNum
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {Number} Float Floating point number
+ */
+p5.TableRow.prototype.getNum = function(column) {
+ var ret;
+ if (typeof(column) === 'string'){
+ ret = parseFloat(this.obj[column], 10);
+ } else {
+ ret = parseFloat(this.arr[column], 10);
+ }
+
+ if (ret.toString() === 'NaN') {
+ throw 'Error: ' + this.obj[column]+ ' is NaN (Not a Number)';
+ }
+ return ret;
+};
+
+/**
+ * Retrieves an String value from the TableRow's specified
+ * column. The column may be specified by either its ID or
+ * title.
+ *
+ * @method getString
+ * @param {String|Number} column columnName (string) or
+ * ID (number)
+ * @return {String} String
+ */
+p5.TableRow.prototype.getString = function(column) {
+ if (typeof(column) === 'string'){
+ return this.obj[column].toString();
+ } else {
+ return this.arr[column].toString();
+ }
+};
+
+module.exports = p5.TableRow;
+
+},{"../core/core":37}],62:[function(_dereq_,module,exports){
+/**
+ * @module IO
+ * @submodule XML
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * XML is a representation of an XML object, able to parse XML code. Use
+ * loadXML() to load external XML files and create XML objects.
+ *
+ * @class p5.XML
+ * @constructor
+ * @return {p5.XML} p5.XML object generated
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var children = xml.getChildren("animal");
+ *
+ * for (var i = 0; i < children.length; i++) {
+ * var id = children[i].getNumber("id");
+ * var coloring = children[i].getString("species");
+ * var name = children[i].getContent();
+ * print(id + ", " + coloring + ", " + name);
+ * }
+ * }
+ *
+ * // Sketch prints:
+ * // 0, Capra hircus, Goat
+ * // 1, Panthera pardus, Leopard
+ * // 2, Equus zebra, Zebra
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.XML = function () {
+ this.name = null; //done
+ this.attributes = {}; //done
+ this.children = [];
+ this.parent = null;
+ this.content = null; //done
+};
+
+
+/**
+ * Gets a copy of the element's parent. Returns the parent as another
+ * p5.XML object.
+ *
+ * @method getParent
+ * @return {Object} element parent
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var children = xml.getChildren("animal");
+ * var parent = children[1].getParent();
+ * print(parent.getName());
+ * }
+ *
+ * // Sketch prints:
+ * // mammals
+ *
+ */
+p5.XML.prototype.getParent = function() {
+ return this.parent;
+};
+
+/**
+ * Gets the element's full name, which is returned as a String.
+ *
+ * @method getName
+ * @return {String} the name of the node
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * print(xml.getName());
+ * }
+ *
+ * // Sketch prints:
+ * // mammals
+ *
+ */
+p5.XML.prototype.getName = function() {
+ return this.name;
+};
+
+/**
+ * Sets the element's name, which is specified as a String.
+ *
+ * @method setName
+ * @param {String} the new name of the node
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * print(xml.getName());
+ * xml.setName("fish");
+ * print(xml.getName());
+ * }
+ *
+ * // Sketch prints:
+ * // mammals
+ * // fish
+ *
+ */
+p5.XML.prototype.setName = function(name) {
+ this.name = name;
+};
+
+/**
+ * Checks whether or not the element has any children, and returns the result
+ * as a boolean.
+ *
+ * @method hasChildren
+ * @return {boolean}
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * print(xml.hasChildren());
+ * }
+ *
+ * // Sketch prints:
+ * // true
+ *
+ */
+p5.XML.prototype.hasChildren = function() {
+ return this.children.length > 0;
+};
+
+/**
+ * Get the names of all of the element's children, and returns the names as an
+ * array of Strings. This is the same as looping through and calling getName()
+ * on each child element individually.
+ *
+ * @method listChildren
+ * @return {Array} names of the children of the element
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * print(xml.listChildren());
+ * }
+ *
+ * // Sketch prints:
+ * // ["animal", "animal", "animal"]
+ *
+ */
+p5.XML.prototype.listChildren = function() {
+ return this.children.map(function(c) { return c.name; });
+};
+
+/**
+ * Returns all of the element's children as an array of p5.XML objects. When
+ * the name parameter is specified, then it will return all children that match
+ * that name.
+ *
+ * @method getChildren
+ * @param {String} [name] element name
+ * @return {Array} children of the element
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var animals = xml.getChildren("animal");
+ *
+ * for (var i = 0; i < animals.length; i++) {
+ * print(animals[i].getContent());
+ * }
+ * }
+ *
+ * // Sketch prints:
+ * // "Goat"
+ * // "Leopard"
+ * // "Zebra"
+ *
+ */
+p5.XML.prototype.getChildren = function(param) {
+ if (param) {
+ return this.children.filter(function(c) { return c.name === param; });
+ }
+ else {
+ return this.children;
+ }
+};
+
+/**
+ * Returns the first of the element's children that matches the name parameter
+ * or the child of the given index.It returns undefined if no matching
+ * child is found.
+ *
+ * @method getChild
+ * @param {String|Number} name element name or index
+ * @return {p5.XML}
+ * @example<animal
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getContent());
+ * }
+ *
+ * // Sketch prints:
+ * // "Goat"
+ *
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var secondChild = xml.getChild(1);
+ * print(secondChild.getContent());
+ * }
+ *
+ * // Sketch prints:
+ * // "Leopard"
+ *
+ */
+p5.XML.prototype.getChild = function(param) {
+ if(typeof param === 'string') {
+ return this.children.find(function(c) {
+ return c.name === param;
+ });
+ }
+ else {
+ return this.children[param];
+ }
+};
+
+/**
+ * Appends a new child to the element. The child can be specified with
+ * either a String, which will be used as the new tag's name, or as a
+ * reference to an existing p5.XML object.
+ * A reference to the newly created child is returned as an p5.XML object.
+ *
+ * @method addChild
+ * @param {Object} a p5.XML Object which will be the child to be added
+ */
+p5.XML.prototype.addChild = function(node) {
+ if (node instanceof p5.XML) {
+ this.children.push(node);
+ } else {
+ // PEND
+ }
+};
+
+/**
+ * Removes the element specified by name or index.
+ *
+ * @method removeChild
+ * @param {String|Number} name element name or index
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * xml.removeChild("animal");
+ * var children = xml.getChildren();
+ * for (var i=0; i
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * xml.removeChild(1);
+ * var children = xml.getChildren();
+ * for (var i=0; i
+ */
+p5.XML.prototype.removeChild = function(param) {
+ var ind = -1;
+ if(typeof param === 'string') {
+ for (var i=0; i
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getAttributeCount());
+ * }
+ *
+ * // Sketch prints:
+ * // 2
+ *
+ */
+p5.XML.prototype.getAttributeCount = function() {
+ return Object.keys(this.attributes).length;
+};
+
+/**
+ * Gets all of the specified element's attributes, and returns them as an
+ * array of Strings.
+ *
+ * @method listAttributes
+ * @return {Array} an array of strings containing the names of attributes
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.listAttributes());
+ * }
+ *
+ * // Sketch prints:
+ * // ["id", "species"]
+ *
+ */
+p5.XML.prototype.listAttributes = function() {
+ return Object.keys(this.attributes);
+};
+
+/**
+ * Checks whether or not an element has the specified attribute.
+ *
+ * @method hasAttribute
+ * @param {String} the attribute to be checked
+ * @return {boolean} true if attribute found else false
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.hasAttribute("species"));
+ * print(firstChild.hasAttribute("color"));
+ * }
+ *
+ * // Sketch prints:
+ * // true
+ * // false
+ *
+ */
+p5.XML.prototype.hasAttribute = function(name) {
+ return this.attributes[name] ? true : false;
+};
+
+/**
+ * Returns an attribute value of the element as an Number. If the defaultValue
+ * parameter is specified and the attribute doesn't exist, then defaultValue
+ * is returned. If no defaultValue is specified and the attribute doesn't
+ * exist, the value 0 is returned.
+ *
+ * @method getNumber
+ * @param {String} name the non-null full name of the attribute
+ * @param {Number} [defaultValue] the default value of the attribute
+ * @return {Number}
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getNumber("id"));
+ * }
+ *
+ * // Sketch prints:
+ * // 0
+ *
+ */
+p5.XML.prototype.getNumber = function(name, defaultValue) {
+ return Number(this.attributes[name]) || defaultValue || 0;
+};
+
+/**
+ * Returns an attribute value of the element as an String. If the defaultValue
+ * parameter is specified and the attribute doesn't exist, then defaultValue
+ * is returned. If no defaultValue is specified and the attribute doesn't
+ * exist, null is returned.
+ *
+ * @method getString
+ * @param {String} name the non-null full name of the attribute
+ * @param {Number} [defaultValue] the default value of the attribute
+ * @return {Number}
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getString("species"));
+ * }
+ *
+ * // Sketch prints:
+ * // "Capra hircus"
+ *
+ */
+p5.XML.prototype.getString = function(name, defaultValue) {
+ return String(this.attributes[name]) || defaultValue || null;
+};
+
+/**
+ * Sets the content of an element's attribute. The first parameter specifies
+ * the attribute name, while the second specifies the new content.
+ *
+ * @method setAttribute
+ * @param {String} name the full name of the attribute
+ * @param {Number} value the value of the attribute
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getString("species"));
+ * firstChild.setAttribute("species", "Jamides zebra");
+ * print(firstChild.getString("species"));
+ * }
+ *
+ * // Sketch prints:
+ * // "Capra hircus"
+ * // "Jamides zebra"
+ *
+ */
+p5.XML.prototype.setAttribute = function(name, value) {
+ if (this.attributes[name]) {
+ this.attributes[name] = value;
+ }
+};
+
+/**
+ * Returns the content of an element. If there is no such content,
+ * defaultValue is returned if specified, otherwise null is returned.
+ *
+ * @method getContent
+ * @param {String} [defaultValue] value returned if no content is found
+ * @return {String}
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getContent());
+ * }
+ *
+ * // Sketch prints:
+ * // "Goat"
+ *
+ */
+p5.XML.prototype.getContent = function(defaultValue) {
+ return this.content || defaultValue || null;
+};
+
+/**
+ * Sets the element's content.
+ *
+ * @method setContent
+ * @param {String} text the new content
+ * @example
+ *
+ * // The following short XML file called "mammals.xml" is parsed
+ * // in the code below.
+ * //
+ * //
+ * // <mammals>
+ * // <animal id="0" species="Capra hircus">Goat</animal>
+ * // <animal id="1" species="Panthera pardus">Leopard</animal>
+ * // <animal id="2" species="Equus zebra">Zebra</animal>
+ * // </mammals>
+ *
+ * var xml;
+ *
+ * function preload() {
+ * xml = loadXML("assets/mammals.xml");
+ * }
+ *
+ * function setup() {
+ * var firstChild = xml.getChild("animal");
+ * print(firstChild.getContent());
+ * firstChild.setContent("Mountain Goat");
+ * print(firstChild.getContent());
+ * }
+ *
+ * // Sketch prints:
+ * // "Goat"
+ * // "Mountain Goat"
+ *
+ */
+p5.XML.prototype.setContent = function( content ) {
+ if(!this.children.length) {
+ this.content = content;
+ }
+};
+
+/* HELPERS */
+/**
+ * This method is called while the parsing of XML (when loadXML() is
+ * called). The difference between this method and the setContent()
+ * method defined later is that this one is used to set the content
+ * when the node in question has more nodes under it and so on and
+ * not directly text content. While in the other one is used when
+ * the node in question directly has text inside it.
+ *
+ */
+p5.XML.prototype._setCont = function(content) {
+ var str;
+ str = content;
+ str = str.replace(/\s\s+/g, ',');
+ //str = str.split(',');
+ this.content = str;
+};
+
+/**
+ * This method is called while the parsing of XML (when loadXML() is
+ * called). The XML node is passed and its attributes are stored in the
+ * p5.XML's attribute Object.
+ *
+ */
+p5.XML.prototype._setAttributes = function(node) {
+ var i, att = {};
+ for( i = 0; i < node.attributes.length; i++) {
+ att[node.attributes[i].nodeName] = node.attributes[i].nodeValue;
+ }
+ this.attributes = att;
+};
+
+module.exports = p5.XML;
+},{"../core/core":37}],63:[function(_dereq_,module,exports){
+/**
+ * @module Math
+ * @submodule Calculation
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
+ * The absolute value of a number is always positive.
+ *
+ * @method abs
+ * @param {Number} n number to compute
+ * @return {Number} absolute value of given number
+ * @example
+ *
+ * function setup() {
+ * var x = -3;
+ * var y = abs(x);
+ *
+ * print(x); // -3
+ * print(y); // 3
+ * }
+ *
+ *
+ * @alt
+ * no image displayed
+ *
+ */
+p5.prototype.abs = Math.abs;
+
+/**
+ * Calculates the closest int value that is greater than or equal to the
+ * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
+ * returns the value 10.
+ *
+ * @method ceil
+ * @param {Number} n number to round up
+ * @return {Number} rounded up number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * // map, mouseX between 0 and 5.
+ * var ax = map(mouseX, 0, 100, 0, 5);
+ * var ay = 66;
+ *
+ * //Get the ceiling of the mapped number.
+ * var bx = ceil(map(mouseX, 0, 100, 0,5));
+ * var by = 33;
+ *
+ * // Multiply the mapped numbers by 20 to more easily
+ * // see the changes.
+ * stroke(0);
+ * fill(0);
+ * line(0, ay, ax * 20, ay);
+ * line(0, by, bx * 20, by);
+ *
+ * // Reformat the float returned by map and draw it.
+ * noStroke();
+ * text(nfc(ax, 2,2), ax, ay - 5);
+ * text(nfc(bx,1,1), bx, by - 5);
+ * }
+ *
+ *
+ * @alt
+ * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
+ *
+ */
+p5.prototype.ceil = Math.ceil;
+
+/**
+ * Constrains a value between a minimum and maximum value.
+ *
+ * @method constrain
+ * @param {Number} n number to constrain
+ * @param {Number} low minimum limit
+ * @param {Number} high maximum limit
+ * @return {Number} constrained number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ *
+ * var leftWall = 25;
+ * var rightWall = 75;
+ *
+ * // xm is just the mouseX, while
+ * // xc is the mouseX, but constrained
+ * // between the leftWall and rightWall!
+ * var xm = mouseX;
+ * var xc = constrain(mouseX, leftWall, rightWall);
+ *
+ * // Draw the walls.
+ * stroke(150);
+ * line(leftWall, 0, leftWall, height);
+ * line(rightWall, 0, rightWall, height);
+ *
+ * // Draw xm and xc as circles.
+ * noStroke();
+ * fill(150);
+ * ellipse(xm, 33, 9,9); // Not Constrained
+ * fill(0);
+ * ellipse(xc, 66, 9,9); // Constrained
+ * }
+ *
+ *
+ * @alt
+ * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines
+ *
+ */
+p5.prototype.constrain = function(n, low, high) {
+ return Math.max(Math.min(n, high), low);
+};
+
+/**
+ * Calculates the distance between two points.
+ *
+ * @method dist
+ * @param {Number} x1 x-coordinate of the first point
+ * @param {Number} y1 y-coordinate of the first point
+ * @param {Number} [z1] z-coordinate of the first point
+ * @param {Number} x2 x-coordinate of the second point
+ * @param {Number} y2 y-coordinate of the second point
+ * @param {Number} [z2] z-coordinate of the second point
+ * @return {Number} distance between the two points
+ * @example
+ *
+ * // Move your mouse inside the canvas to see the
+ * // change in distance between two points!
+ * function draw() {
+ * background(200);
+ * fill(0);
+ *
+ * var x1 = 10;
+ * var y1 = 90;
+ * var x2 = mouseX;
+ * var y2 = mouseY;
+ *
+ * line(x1, y1, x2, y2);
+ * ellipse(x1, y1, 7, 7);
+ * ellipse(x2, y2, 7, 7);
+ *
+ * // d is the length of the line
+ * // the distance from point 1 to point 2.
+ * var d = int(dist(x1, y1, x2, y2));
+ *
+ * // Let's write d along the line we are drawing!
+ * push();
+ * translate( (x1+x2)/2, (y1+y2)/2 );
+ * rotate( atan2(y2-y1,x2-x1) );
+ * text(nfc(d,1,1), 0, -5);
+ * pop();
+ * // Fancy!
+ * }
+ *
+ *
+ * @alt
+ * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.
+ *
+ */
+p5.prototype.dist = function(x1, y1, z1, x2, y2, z2) {
+ if (arguments.length === 4) {
+ // In the case of 2d: z1 means x2 and x2 means y2
+ return hypot(z1-x1, x2-y1);
+ } else if (arguments.length === 6) {
+ return hypot(x2-x1, y2-y1, z2-z1);
+ }
+};
+
+/**
+ * Returns Euler's number e (2.71828...) raised to the power of the n
+ * parameter. Maps to Math.exp().
+ *
+ * @method exp
+ * @param {Number} n exponent to raise
+ * @return {Number} e^n
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ *
+ * // Compute the exp() function with a value between 0 and 2
+ * var xValue = map(mouseX, 0, width, 0, 2);
+ * var yValue = exp(xValue);
+ *
+ * var y = map(yValue, 0, 8, height, 0);
+ *
+ * var legend = "exp (" + nfc(xValue, 3) +")\n= " + nf(yValue, 1, 4);
+ * stroke(150);
+ * line(mouseX, y, mouseX, height);
+ * fill(0);
+ * text(legend, 5, 15);
+ * noStroke();
+ * ellipse (mouseX,y, 7, 7);
+ *
+ * // Draw the exp(x) curve,
+ * // over the domain of x from 0 to 2
+ * noFill();
+ * stroke(0);
+ * beginShape();
+ * for (var x = 0; x < width; x++) {
+ * xValue = map(x, 0, width, 0, 2);
+ * yValue = exp(xValue);
+ * y = map(yValue, 0, 8, height, 0);
+ * vertex(x, y);
+ * }
+ *
+ * endShape();
+ * line(0, 0, 0, height);
+ * line(0, height-1, width, height-1);
+ * }
+ *
+ *
+ * @alt
+ * ellipse moves along a curve with mouse x. e^n displayed.
+ *
+ */
+p5.prototype.exp = Math.exp;
+
+/**
+ * Calculates the closest int value that is less than or equal to the
+ * value of the parameter. Maps to Math.floor().
+ *
+ * @method floor
+ * @param {Number} n number to round down
+ * @return {Number} rounded down number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * //map, mouseX between 0 and 5.
+ * var ax = map(mouseX, 0, 100, 0, 5);
+ * var ay = 66;
+ *
+ * //Get the floor of the mapped number.
+ * var bx = floor(map(mouseX, 0, 100, 0,5));
+ * var by = 33;
+ *
+ * // Multiply the mapped numbers by 20 to more easily
+ * // see the changes.
+ * stroke(0);
+ * fill(0);
+ * line(0, ay, ax * 20, ay);
+ * line(0, by, bx * 20, by);
+ *
+ * // Reformat the float returned by map and draw it.
+ * noStroke();
+ * text(nfc(ax, 2,2), ax, ay - 5);
+ * text(nfc(bx,1,1), bx, by - 5);
+ * }
+ *
+ *
+ * @alt
+ * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
+ *
+ */
+p5.prototype.floor = Math.floor;
+
+/**
+ * Calculates a number between two numbers at a specific increment. The amt
+ * parameter is the amount to interpolate between the two values where 0.0
+ * equal to the first point, 0.1 is very near the first point, 0.5 is
+ * half-way in between, etc. The lerp function is convenient for creating
+ * motion along a straight path and for drawing dotted lines.
+ *
+ * @method lerp
+ * @param {Number} start first value
+ * @param {Number} stop second value
+ * @param {Number} amt number between 0.0 and 1.0
+ * @return {Number} lerped value
+ * @example
+ *
+ * function setup() {
+ * background(200);
+ * var a = 20;
+ * var b = 80;
+ * var c = lerp(a,b, .2);
+ * var d = lerp(a,b, .5);
+ * var e = lerp(a,b, .8);
+ *
+ * var y = 50
+ *
+ * strokeWeight(5);
+ * stroke(0); // Draw the original points in black
+ * point(a, y);
+ * point(b, y);
+ *
+ * stroke(100); // Draw the lerp points in gray
+ * point(c, y);
+ * point(d, y);
+ * point(e, y);
+ * }
+ *
+ *
+ * @alt
+ * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black
+ *
+ */
+p5.prototype.lerp = function(start, stop, amt) {
+ return amt*(stop-start)+start;
+};
+
+/**
+ * Calculates the natural logarithm (the base-e logarithm) of a number. This
+ * function expects the n parameter to be a value greater than 0.0. Maps to
+ * Math.log().
+ *
+ * @method log
+ * @param {Number} n number greater than 0
+ * @return {Number} natural logarithm of n
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * var maxX = 2.8;
+ * var maxY = 1.5;
+ *
+ * // Compute the natural log of a value between 0 and maxX
+ * var xValue = map(mouseX, 0, width, 0, maxX);
+ * if (xValue > 0) { // Cannot take the log of a negative number.
+ * var yValue = log(xValue);
+ * var y = map(yValue, -maxY, maxY, height, 0);
+ *
+ * // Display the calculation occurring.
+ * var legend = "log(" + nf(xValue, 1, 2) + ")\n= " + nf(yValue, 1, 3);
+ * stroke(150);
+ * line(mouseX, y, mouseX, height);
+ * fill(0);
+ * text (legend, 5, 15);
+ * noStroke();
+ * ellipse (mouseX, y, 7, 7);
+ * }
+ *
+ * // Draw the log(x) curve,
+ * // over the domain of x from 0 to maxX
+ * noFill();
+ * stroke(0);
+ * beginShape();
+ * for(var x=0; x < width; x++) {
+ * xValue = map(x, 0, width, 0, maxX);
+ * yValue = log(xValue);
+ * y = map(yValue, -maxY, maxY, height, 0);
+ * vertex(x, y);
+ * }
+ * endShape();
+ * line(0,0,0,height);
+ * line(0,height/2,width, height/2);
+ * }
+ *
+ *
+ * @alt
+ * ellipse moves along a curve with mouse x. natural logarithm of n displayed.
+ *
+ */
+p5.prototype.log = Math.log;
+
+/**
+ * Calculates the magnitude (or length) of a vector. A vector is a direction
+ * in space commonly used in computer graphics and linear algebra. Because it
+ * has no "start" position, the magnitude of a vector can be thought of as
+ * the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is
+ * a shortcut for writing dist(0, 0, x, y).
+ *
+ * @method mag
+ * @param {Number} a first value
+ * @param {Number} b second value
+ * @return {Number} magnitude of vector from (0,0) to (a,b)
+ * @example
+ *
+ * function setup() {
+ * var x1 = 20;
+ * var x2 = 80;
+ * var y1 = 30;
+ * var y2 = 70;
+ *
+ * line(0, 0, x1, y1);
+ * print(mag(x1, y1)); // Prints "36.05551275463989"
+ * line(0, 0, x2, y1);
+ * print(mag(x2, y1)); // Prints "85.44003745317531"
+ * line(0, 0, x1, y2);
+ * print(mag(x1, y2)); // Prints "72.80109889280519"
+ * line(0, 0, x2, y2);
+ * print(mag(x2, y2)); // Prints "106.3014581273465"
+ * }
+ *
+ *
+ * @alt
+ * 4 lines of different length radiate from top left of canvas.
+ *
+ */
+p5.prototype.mag = function(x, y) {
+ return hypot(x, y);
+};
+
+/**
+ * Re-maps a number from one range to another.
+ *
+ * In the first example above, the number 25 is converted from a value in the
+ * range of 0 to 100 into a value that ranges from the left edge of the
+ * window (0) to the right edge (width).
+ *
+ * @method map
+ * @param {Number} value the incoming value to be converted
+ * @param {Number} start1 lower bound of the value's current range
+ * @param {Number} stop1 upper bound of the value's current range
+ * @param {Number} start2 lower bound of the value's target range
+ * @param {Number} stop2 upper bound of the value's target range
+ * @return {Number} remapped number
+ * @example
+ *
+ * var value = 25;
+ * var m = map(value, 0, 100, 0, width);
+ * ellipse(m, 50, 10, 10);
+ *
+ *
+ *
+ * function setup() {
+ * noStroke();
+ * }
+ *
+ * function draw() {
+ * background(204);
+ * var x1 = map(mouseX, 0, width, 25, 75);
+ * ellipse(x1, 25, 25, 25);
+ * var x2 = map(mouseX, 0, width, 0, 100);
+ * ellipse(x2, 75, 25, 25);
+ * }
+ *
+ *
+ * @alt
+ * 10 by 10 white ellipse with in mid left canvas
+ * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X
+ *
+ */
+p5.prototype.map = function(n, start1, stop1, start2, stop2) {
+ return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
+};
+
+/**
+ * Determines the largest value in a sequence of numbers, and then returns
+ * that value. max() accepts any number of Number parameters, or an Array
+ * of any length.
+ *
+ * @method max
+ * @param {Number|Array} n0 Numbers to compare
+ * @return {Number} maximum Number
+ * @example
+ *
+ * function setup() {
+ * // Change the elements in the array and run the sketch
+ * // to show how max() works!
+ * numArray = new Array(2,1,5,4,8,9);
+ * fill(0);
+ * noStroke();
+ * text("Array Elements", 0, 10);
+ * // Draw all numbers in the array
+ * var spacing = 15;
+ * var elemsY = 25;
+ * for(var i = 0; i < numArray.length; i++) {
+ * text(numArray[i], i * spacing, elemsY);
+ * }
+ * maxX = 33;
+ * maxY = 80;
+ * // Draw the Maximum value in the array.
+ * textSize(32);
+ * text(max(numArray), maxX, maxY);
+ * }
+ *
+ *
+ * @alt
+ * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9
+ *
+ */
+p5.prototype.max = function() {
+ if (arguments[0] instanceof Array) {
+ return Math.max.apply(null,arguments[0]);
+ } else {
+ return Math.max.apply(null,arguments);
+ }
+};
+
+/**
+ * Determines the smallest value in a sequence of numbers, and then returns
+ * that value. min() accepts any number of Number parameters, or an Array
+ * of any length.
+ *
+ * @method min
+ * @param {Number|Array} n0 Numbers to compare
+ * @return {Number} minimum Number
+ * @example
+ *
+ * function setup() {
+ * // Change the elements in the array and run the sketch
+ * // to show how min() works!
+ * numArray = new Array(2,1,5,4,8,9);
+ * fill(0);
+ * noStroke();
+ * text("Array Elements", 0, 10);
+ * // Draw all numbers in the array
+ * var spacing = 15;
+ * var elemsY = 25;
+ * for(var i = 0; i < numArray.length; i++) {
+ * text(numArray[i], i * spacing, elemsY);
+ * }
+ * maxX = 33;
+ * maxY = 80;
+ * // Draw the Minimum value in the array.
+ * textSize(32);
+ * text(min(numArray), maxX, maxY);
+ * }
+ *
+ *
+ * @alt
+ * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1
+ *
+ */
+p5.prototype.min = function() {
+ if (arguments[0] instanceof Array) {
+ return Math.min.apply(null,arguments[0]);
+ } else {
+ return Math.min.apply(null,arguments);
+ }
+};
+
+/**
+ * Normalizes a number from another range into a value between 0 and 1.
+ * Identical to map(value, low, high, 0, 1).
+ * Numbers outside of the range are not clamped to 0 and 1, because
+ * out-of-range values are often intentional and useful. (See the second
+ * example above.)
+ *
+ * @method norm
+ * @param {Number} value incoming value to be normalized
+ * @param {Number} start lower bound of the value's current range
+ * @param {Number} stop upper bound of the value's current range
+ * @return {Number} normalized number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * currentNum = mouseX;
+ * lowerBound = 0;
+ * upperBound = width; //100;
+ * normalized = norm(currentNum, lowerBound, upperBound);
+ * lineY = 70
+ * line(0, lineY, width, lineY);
+ * //Draw an ellipse mapped to the non-normalized value.
+ * noStroke();
+ * fill(50)
+ * var s = 7; // ellipse size
+ * ellipse(currentNum, lineY, s, s);
+ *
+ * // Draw the guide
+ * guideY = lineY + 15;
+ * text("0", 0, guideY);
+ * textAlign(RIGHT);
+ * text("100", width, guideY);
+ *
+ * // Draw the normalized value
+ * textAlign(LEFT);
+ * fill(0);
+ * textSize(32);
+ * normalY = 40;
+ * normalX = 20;
+ * text(normalized, normalX, normalY);
+ * }
+ *
+ *
+ * @alt
+ * ellipse moves with mouse. 0 shown left & 100 right and updating values center
+ *
+ */
+p5.prototype.norm = function(n, start, stop) {
+ return this.map(n, start, stop, 0, 1);
+};
+
+/**
+ * Facilitates exponential expressions. The pow() function is an efficient
+ * way of multiplying numbers by themselves (or their reciprocals) in large
+ * quantities. For example, pow(3, 5) is equivalent to the expression
+ * 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to
+ * Math.pow().
+ *
+ * @method pow
+ * @param {Number} n base of the exponential expression
+ * @param {Number} e power by which to raise the base
+ * @return {Number} n^e
+ * @example
+ *
+ * function setup() {
+ * //Exponentially increase the size of an ellipse.
+ * eSize = 3; // Original Size
+ * eLoc = 10; // Original Location
+ *
+ * ellipse(eLoc, eLoc, eSize, eSize);
+ *
+ * ellipse(eLoc*2, eLoc*2, pow(eSize, 2), pow(eSize, 2));
+ *
+ * ellipse(eLoc*4, eLoc*4, pow(eSize, 3), pow(eSize, 3));
+ *
+ * ellipse(eLoc*8, eLoc*8, pow(eSize, 4), pow(eSize, 4));
+ * }
+ *
+ *
+ * @alt
+ * small to large ellipses radiating from top left of canvas
+ *
+ */
+p5.prototype.pow = Math.pow;
+
+/**
+ * Calculates the integer closest to the n parameter. For example,
+ * round(133.8) returns the value 134. Maps to Math.round().
+ *
+ * @method round
+ * @param {Number} n number to round
+ * @return {Number} rounded number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * //map, mouseX between 0 and 5.
+ * var ax = map(mouseX, 0, 100, 0, 5);
+ * var ay = 66;
+ *
+ * // Round the mapped number.
+ * var bx = round(map(mouseX, 0, 100, 0,5));
+ * var by = 33;
+ *
+ * // Multiply the mapped numbers by 20 to more easily
+ * // see the changes.
+ * stroke(0);
+ * fill(0);
+ * line(0, ay, ax * 20, ay);
+ * line(0, by, bx * 20, by);
+ *
+ * // Reformat the float returned by map and draw it.
+ * noStroke();
+ * text(nfc(ax, 2,2), ax, ay - 5);
+ * text(nfc(bx,1,1), bx, by - 5);
+ * }
+ *
+ *
+ * @alt
+ * horizontal center line squared values displayed on top and regular on bottom.
+ *
+ */
+p5.prototype.round = Math.round;
+
+/**
+ * Squares a number (multiplies a number by itself). The result is always a
+ * positive number, as multiplying two negative numbers always yields a
+ * positive result. For example, -1 * -1 = 1.
+ *
+ * @method sq
+ * @param {Number} n number to square
+ * @return {Number} squared number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * eSize = 7;
+ * x1 = map(mouseX, 0, width, 0, 10);
+ * y1 = 80;
+ * x2 = sq(x1);
+ * y2 = 20;
+ *
+ * // Draw the non-squared.
+ * line(0, y1, width, y1);
+ * ellipse(x1, y1, eSize, eSize);
+ *
+ * // Draw the squared.
+ * line(0, y2, width, y2);
+ * ellipse(x2, y2, eSize, eSize);
+ *
+ * // Draw dividing line.
+ * stroke(100)
+ * line(0, height/2, width, height/2);
+ *
+ * // Draw text.
+ * var spacing = 15;
+ * noStroke();
+ * fill(0);
+ * text("x = " + x1, 0, y1 + spacing);
+ * text("sq(x) = " + x2, 0, y2 + spacing);
+ * }
+ *
+ *
+ * @alt
+ * horizontal center line squared values displayed on top and regular on bottom.
+ *
+ */
+p5.prototype.sq = function(n) { return n*n; };
+
+/**
+ * Calculates the square root of a number. The square root of a number is
+ * always positive, even though there may be a valid negative root. The
+ * square root s of number a is such that s*s = a. It is the opposite of
+ * squaring. Maps to Math.sqrt().
+ *
+ * @method sqrt
+ * @param {Number} n non-negative number to square root
+ * @return {Number} square root of number
+ * @example
+ *
+ * function draw() {
+ * background(200);
+ * eSize = 7;
+ * x1 = mouseX;
+ * y1 = 80;
+ * x2 = sqrt(x1);
+ * y2 = 20;
+ *
+ * // Draw the non-squared.
+ * line(0, y1, width, y1);
+ * ellipse(x1, y1, eSize, eSize);
+ *
+ * // Draw the squared.
+ * line(0, y2, width, y2);
+ * ellipse(x2, y2, eSize, eSize);
+ *
+ * // Draw dividing line.
+ * stroke(100)
+ * line(0, height/2, width, height/2);
+ *
+ * // Draw text.
+ * noStroke();
+ * fill(0);
+ * var spacing = 15;
+ * text("x = " + x1, 0, y1 + spacing);
+ * text("sqrt(x) = " + x2, 0, y2 + spacing);
+ * }
+ *
+ *
+ * @alt
+ * horizontal center line squareroot values displayed on top and regular on bottom.
+ *
+ */
+p5.prototype.sqrt = Math.sqrt;
+
+// Calculate the length of the hypotenuse of a right triangle
+// This won't under- or overflow in intermediate steps
+// https://en.wikipedia.org/wiki/Hypot
+function hypot(x, y, z) {
+ // Use the native implementation if it's available
+ if (typeof Math.hypot === 'function') {
+ return Math.hypot.apply(null, arguments);
+ }
+
+ // Otherwise use the V8 implementation
+ // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217
+ var length = arguments.length;
+ var args = [];
+ var max = 0;
+ for (var i = 0; i < length; i++) {
+ var n = arguments[i];
+ n = +n;
+ if (n === Infinity || n === -Infinity) {
+ return Infinity;
+ }
+ n = Math.abs(n);
+ if (n > max) {
+ max = n;
+ }
+ args[i] = n;
+ }
+
+ if (max === 0) {
+ max = 1;
+ }
+ var sum = 0;
+ var compensation = 0;
+ for (var j = 0; j < length; j++) {
+ var m = args[j] / max;
+ var summand = m * m - compensation;
+ var preliminary = sum + summand;
+ compensation = (preliminary - sum) - summand;
+ sum = preliminary;
+ }
+ return Math.sqrt(sum) * max;
+}
+
+module.exports = p5;
+
+},{"../core/core":37}],64:[function(_dereq_,module,exports){
+/**
+ * @module Math
+ * @submodule Math
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+
+/**
+ * Creates a new p5.Vector (the datatype for storing vectors). This provides a
+ * two or three dimensional vector, specifically a Euclidean (also known as
+ * geometric) vector. A vector is an entity that has both magnitude and
+ * direction.
+ *
+ * @method createVector
+ * @param {Number} [x] x component of the vector
+ * @param {Number} [y] y component of the vector
+ * @param {Number} [z] z component of the vector
+ */
+p5.prototype.createVector = function (x, y, z) {
+ if (this instanceof p5) {
+ return new p5.Vector(this, arguments);
+ } else {
+ return new p5.Vector(x, y, z);
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],65:[function(_dereq_,module,exports){
+//////////////////////////////////////////////////////////////
+
+// http://mrl.nyu.edu/~perlin/noise/
+// Adapting from PApplet.java
+// which was adapted from toxi
+// which was adapted from the german demo group farbrausch
+// as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
+
+// someday we might consider using "improved noise"
+// http://mrl.nyu.edu/~perlin/paper445.pdf
+// See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
+// blob/master/introduction/Noise1D/noise.js
+
+/**
+ * @module Math
+ * @submodule Noise
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+var PERLIN_YWRAPB = 4;
+var PERLIN_YWRAP = 1<random() function.
+ * It was invented by Ken Perlin in the 1980s and been used since in
+ * graphical applications to produce procedural textures, natural motion,
+ * shapes, terrains etc.
The main difference to the
+ * random() function is that Perlin noise is defined in an infinite
+ * n-dimensional space where each pair of coordinates corresponds to a
+ * fixed semi-random value (fixed only for the lifespan of the program; see
+ * the noiseSeed() function). p5.js can compute 1D, 2D and 3D noise,
+ * depending on the number of coordinates given. The resulting value will
+ * always be between 0.0 and 1.0. The noise value can be animated by moving
+ * through the noise space as demonstrated in the example above. The 2nd
+ * and 3rd dimension can also be interpreted as time.
The actual
+ * noise is structured similar to an audio signal, in respect to the
+ * function's use of frequencies. Similar to the concept of harmonics in
+ * physics, perlin noise is computed over several octaves which are added
+ * together for the final result.
Another way to adjust the
+ * character of the resulting sequence is the scale of the input
+ * coordinates. As the function works within an infinite space the value of
+ * the coordinates doesn't matter as such, only the distance between
+ * successive coordinates does (eg. when using noise() within a
+ * loop). As a general rule the smaller the difference between coordinates,
+ * the smoother the resulting noise sequence will be. Steps of 0.005-0.03
+ * work best for most applications, but this will differ depending on use.
+ *
+ *
+ * @method noise
+ * @param {Number} x x-coordinate in noise space
+ * @param {Number} y y-coordinate in noise space
+ * @param {Number} z z-coordinate in noise space
+ * @return {Number} Perlin noise value (between 0 and 1) at specified
+ * coordinates
+ * @example
+ *
+ * var xoff = 0.0;
+ *
+ * function draw() {
+ * background(204);
+ * xoff = xoff + .01;
+ * var n = noise(xoff) * width;
+ * line(n, 0, n, height);
+ * }
+ *
+ *
+ *
+ * var noiseScale=0.02;
+ *
+ * function draw() {
+ * background(0);
+ * for (var x=0; x < width; x++) {
+ * var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
+ * stroke(noiseVal*255);
+ * line(x, mouseY+noiseVal*80, x, height);
+ * }
+ * }
+ *
+ *
+ *
+ * @alt
+ * vertical line moves left to right with updating noise values.
+ * horizontal wave pattern effected by mouse x-position & updating noise values.
+ *
+ */
+
+p5.prototype.noise = function(x,y,z) {
+ y = y || 0;
+ z = z || 0;
+
+ if (perlin == null) {
+ perlin = new Array(PERLIN_SIZE + 1);
+ for (var i = 0; i < PERLIN_SIZE + 1; i++) {
+ perlin[i] = Math.random();
+ }
+ }
+
+ if (x<0) { x=-x; }
+ if (y<0) { y=-y; }
+ if (z<0) { z=-z; }
+
+ var xi=Math.floor(x), yi=Math.floor(y), zi=Math.floor(z);
+ var xf = x - xi;
+ var yf = y - yi;
+ var zf = z - zi;
+ var rxf, ryf;
+
+ var r=0;
+ var ampl=0.5;
+
+ var n1,n2,n3;
+
+ for (var o=0; o=1.0) { xi++; xf--; }
+ if (yf>=1.0) { yi++; yf--; }
+ if (zf>=1.0) { zi++; zf--; }
+ }
+ return r;
+};
+
+
+/**
+ *
+ * Adjusts the character and level of detail produced by the Perlin noise
+ * function. Similar to harmonics in physics, noise is computed over
+ * several octaves. Lower octaves contribute more to the output signal and
+ * as such define the overall intensity of the noise, whereas higher octaves
+ * create finer grained details in the noise sequence.
+ *
+ * By default, noise is computed over 4 octaves with each octave contributing
+ * exactly half than its predecessor, starting at 50% strength for the 1st
+ * octave. This falloff amount can be changed by adding an additional function
+ * parameter. Eg. a falloff factor of 0.75 means each octave will now have
+ * 75% impact (25% less) of the previous lower octave. Any value between
+ * 0.0 and 1.0 is valid, however note that values greater than 0.5 might
+ * result in greater than 1.0 values returned by noise().
+ *
+ * By changing these parameters, the signal created by the noise()
+ * function can be adapted to fit very specific needs and characteristics.
+ *
+ * @method noiseDetail
+ * @param {Number} lod number of octaves to be used by the noise
+ * @param {Number} falloff falloff factor for each octave
+ * @example
+ *
+ *
+ *
+ * var noiseVal;
+ * var noiseScale=0.02;
+ *
+ * function setup() {
+ * createCanvas(100,100);
+ * }
+ *
+ * function draw() {
+ * background(0);
+ * for (var y = 0; y < height; y++) {
+ * for (var x = 0; x < width/2; x++) {
+ * noiseDetail(2,0.2);
+ * noiseVal = noise((mouseX+x) * noiseScale,
+ * (mouseY+y) * noiseScale);
+ * stroke(noiseVal*255);
+ * point(x,y);
+ * noiseDetail(8,0.65);
+ * noiseVal = noise((mouseX + x + width/2) * noiseScale,
+ * (mouseY + y) * noiseScale);
+ * stroke(noiseVal*255);
+ * point(x + width/2, y);
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ * @alt
+ * 2 vertical grey smokey patterns affected my mouse x-position and noise.
+ *
+ */
+p5.prototype.noiseDetail = function(lod, falloff) {
+ if (lod>0) { perlin_octaves=lod; }
+ if (falloff>0) { perlin_amp_falloff=falloff; }
+};
+
+/**
+ * Sets the seed value for noise(). By default, noise()
+ * produces different results each time the program is run. Set the
+ * value parameter to a constant to return the same pseudo-random
+ * numbers each time the software is run.
+ *
+ * @method noiseSeed
+ * @param {Number} seed the seed value
+ * @example
+ *
+ * var xoff = 0.0;
+ *
+ * function setup() {
+ * noiseSeed(99);
+ * stroke(0, 10);
+ * }
+ *
+ * function draw() {
+ * xoff = xoff + .01;
+ * var n = noise(xoff) * width;
+ * line(n, 0, n, height);
+ * }
+ *
+ *
+ *
+ * @alt
+ * vertical grey lines drawing in pattern affected by noise.
+ *
+ */
+p5.prototype.noiseSeed = function(seed) {
+ // Linear Congruential Generator
+ // Variant of a Lehman Generator
+ var lcg = (function() {
+ // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
+ // m is basically chosen to be large (as it is the max period)
+ // and for its relationships to a and c
+ var m = 4294967296,
+ // a - 1 should be divisible by m's prime factors
+ a = 1664525,
+ // c and m should be co-prime
+ c = 1013904223,
+ seed, z;
+ return {
+ setSeed : function(val) {
+ // pick a random seed if val is undefined or null
+ // the >>> 0 casts the seed to an unsigned 32-bit integer
+ z = seed = (val == null ? Math.random() * m : val) >>> 0;
+ },
+ getSeed : function() {
+ return seed;
+ },
+ rand : function() {
+ // define the recurrence relationship
+ z = (a * z + c) % m;
+ // return a float in [0, 1)
+ // if z = m then z / m = 0 therefore (z % m) / m < 1 always
+ return z / m;
+ }
+ };
+ }());
+
+ lcg.setSeed(seed);
+ perlin = new Array(PERLIN_SIZE + 1);
+ for (var i = 0; i < PERLIN_SIZE + 1; i++) {
+ perlin[i] = lcg.rand();
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],66:[function(_dereq_,module,exports){
+/**
+ * @module Math
+ * @submodule Math
+ * @requires constants
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var polarGeometry = _dereq_('./polargeometry');
+var constants = _dereq_('../core/constants');
+
+/**
+ * A class to describe a two or three dimensional vector, specifically
+ * a Euclidean (also known as geometric) vector. A vector is an entity
+ * that has both magnitude and direction. The datatype, however, stores
+ * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
+ * and direction can be accessed via the methods mag() and heading().
+ *
+ * In many of the p5.js examples, you will see p5.Vector used to describe a
+ * position, velocity, or acceleration. For example, if you consider a rectangle
+ * moving across the screen, at any given instant it has a position (a vector
+ * that points from the origin to its location), a velocity (the rate at which
+ * the object's position changes per time unit, expressed as a vector), and
+ * acceleration (the rate at which the object's velocity changes per time
+ * unit, expressed as a vector).
+ *
+ * Since vectors represent groupings of values, we cannot simply use
+ * traditional addition/multiplication/etc. Instead, we'll need to do some
+ * "vector" math, which is made easy by the methods inside the p5.Vector class.
+ *
+ * @class p5.Vector
+ * @constructor
+ * @param {Number} [x] x component of the vector
+ * @param {Number} [y] y component of the vector
+ * @param {Number} [z] z component of the vector
+ * @example
+ *
+ *
+ * var v1 = createVector(40, 50);
+ * var v2 = createVector(40, 50);
+ *
+ * ellipse(v1.x, v1.y, 50, 50);
+ * ellipse(v2.x, v2.y, 50, 50);
+ * v1.add(v2);
+ * ellipse(v1.x, v1.y, 50, 50);
+ *
+ *
+ *
+ * @alt
+ * 2 white ellipses. One center-left the other bottom right and off canvas
+ *
+ */
+p5.Vector = function() {
+ var x,y,z;
+ // This is how it comes in with createVector()
+ if(arguments[0] instanceof p5) {
+ // save reference to p5 if passed in
+ this.p5 = arguments[0];
+ x = arguments[1][0] || 0;
+ y = arguments[1][1] || 0;
+ z = arguments[1][2] || 0;
+ // This is what we'll get with new p5.Vector()
+ } else {
+ x = arguments[0] || 0;
+ y = arguments[1] || 0;
+ z = arguments[2] || 0;
+ }
+ /**
+ * The x component of the vector
+ * @property x
+ * @type {Number}
+ */
+ this.x = x;
+ /**
+ * The y component of the vector
+ * @property y
+ * @type {Number}
+ */
+ this.y = y;
+ /**
+ * The z component of the vector
+ * @property z
+ * @type {Number}
+ */
+ this.z = z;
+};
+
+/**
+ * Returns a string representation of a vector v by calling String(v)
+ * or v.toString(). This method is useful for logging vectors in the
+ * console.
+ * @method toString
+ * @example
+ *
+ * function setup() {
+ * var v = createVector(20,30);
+ * print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
+ * }
+ *
+ *
+ */
+p5.Vector.prototype.toString = function p5VectorToString() {
+ return 'p5.Vector Object : ['+ this.x +', '+ this.y +', '+ this.z + ']';
+};
+
+/**
+ * Sets the x, y, and z component of the vector using two or three separate
+ * variables, the data from a p5.Vector, or the values from a float array.
+ * @method set
+ *
+ * @param {Number|p5.Vector|Array} [x] the x component of the vector or a
+ * p5.Vector or an Array
+ * @param {Number} [y] the y component of the vector
+ * @param {Number} [z] the z component of the vector
+ * @example
+ *
+ *
+ * function setup() {
+ * var v = createVector(1, 2, 3);
+ * v.set(4,5,6); // Sets vector to [4, 5, 6]
+ *
+ * var v1 = createVector(0, 0, 0);
+ * var arr = [1, 2, 3];
+ * v1.set(arr); // Sets vector to [1, 2, 3]
+ * }
+ *
+ *
+ */
+p5.Vector.prototype.set = function (x, y, z) {
+ if (x instanceof p5.Vector) {
+ this.x = x.x || 0;
+ this.y = x.y || 0;
+ this.z = x.z || 0;
+ return this;
+ }
+ if (x instanceof Array) {
+ this.x = x[0] || 0;
+ this.y = x[1] || 0;
+ this.z = x[2] || 0;
+ return this;
+ }
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0;
+ return this;
+};
+
+/**
+ * Gets a copy of the vector, returns a p5.Vector object.
+ *
+ * @method copy
+ * @return {p5.Vector} the copy of the p5.Vector object
+ * @example
+ *
+ *
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = v1.copy();
+ * print(v1.x == v2.x && v1.y == v2.y && v1.z == v2.z);
+ * // Prints "true"
+ *
+ *
+ */
+p5.Vector.prototype.copy = function () {
+ if (this.p5) {
+ return new p5.Vector(this.p5,[this.x, this.y, this.z]);
+ } else {
+ return new p5.Vector(this.x,this.y,this.z);
+ }
+};
+
+/**
+ * Adds x, y, and z components to a vector, adds one vector to another, or
+ * adds two independent vectors together. The version of the method that adds
+ * two vectors together is a static method and returns a p5.Vector, the others
+ * acts directly on the vector. See the examples for more context.
+ *
+ * @method add
+ * @chainable
+ * @param {Number|p5.Vector|Array} x the x component of the vector to be
+ * added or a p5.Vector or an Array
+ * @param {Number} [y] the y component of the vector to be
+ * added
+ * @param {Number} [z] the z component of the vector to be
+ * added
+ * @return {p5.Vector} the p5.Vector object.
+ * @example
+ *
+ *
+ * var v = createVector(1, 2, 3);
+ * v.add(4,5,6);
+ * // v's components are set to [5, 7, 9]
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = createVector(2, 3, 4);
+ *
+ * var v3 = p5.Vector.add(v1, v2);
+ * // v3 has components [3, 5, 7]
+ *
+ *
+ */
+p5.Vector.prototype.add = function (x, y, z) {
+ if (x instanceof p5.Vector) {
+ this.x += x.x || 0;
+ this.y += x.y || 0;
+ this.z += x.z || 0;
+ return this;
+ }
+ if (x instanceof Array) {
+ this.x += x[0] || 0;
+ this.y += x[1] || 0;
+ this.z += x[2] || 0;
+ return this;
+ }
+ this.x += x || 0;
+ this.y += y || 0;
+ this.z += z || 0;
+ return this;
+};
+
+/**
+ * Subtracts x, y, and z components from a vector, subtracts one vector from
+ * another, or subtracts two independent vectors. The version of the method
+ * that subtracts two vectors is a static method and returns a p5.Vector, the
+ * other acts directly on the vector. See the examples for more context.
+ *
+ * @method sub
+ * @chainable
+ * @param {Number|p5.Vector|Array} x the x component of the vector or a
+ * p5.Vector or an Array
+ * @param {Number} [y] the y component of the vector
+ * @param {Number} [z] the z component of the vector
+ * @return {p5.Vector} p5.Vector object.
+ * @example
+ *
+ *
+ * var v = createVector(4, 5, 6);
+ * v.sub(1, 1, 1);
+ * // v's components are set to [3, 4, 5]
+ *
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(2, 3, 4);
+ * var v2 = createVector(1, 2, 3);
+ *
+ * var v3 = p5.Vector.sub(v1, v2);
+ * // v3 has components [1, 1, 1]
+ *
+ *
+ */
+p5.Vector.prototype.sub = function (x, y, z) {
+ if (x instanceof p5.Vector) {
+ this.x -= x.x || 0;
+ this.y -= x.y || 0;
+ this.z -= x.z || 0;
+ return this;
+ }
+ if (x instanceof Array) {
+ this.x -= x[0] || 0;
+ this.y -= x[1] || 0;
+ this.z -= x[2] || 0;
+ return this;
+ }
+ this.x -= x || 0;
+ this.y -= y || 0;
+ this.z -= z || 0;
+ return this;
+};
+
+/**
+ * Multiply the vector by a scalar. The static version of this method
+ * creates a new p5.Vector while the non static version acts on the vector
+ * directly. See the examples for more context.
+ *
+ * @method mult
+ * @chainable
+ * @param {Number} n the number to multiply with the vector
+ * @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
+ * @example
+ *
+ *
+ * var v = createVector(1, 2, 3);
+ * v.mult(2);
+ * // v's components are set to [2, 4, 6]
+ *
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = p5.Vector.mult(v1, 2);
+ * // v2 has components [2, 4, 6]
+ *
+ *
+ */
+p5.Vector.prototype.mult = function (n) {
+ this.x *= n || 0;
+ this.y *= n || 0;
+ this.z *= n || 0;
+ return this;
+};
+
+/**
+ * Divide the vector by a scalar. The static version of this method creates a
+ * new p5.Vector while the non static version acts on the vector directly.
+ * See the examples for more context.
+ *
+ * @method div
+ * @chainable
+ * @param {number} n the number to divide the vector by
+ * @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
+ * @example
+ *
+ *
+ * var v = createVector(6, 4, 2);
+ * v.div(2); //v's components are set to [3, 2, 1]
+ *
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(6, 4, 2);
+ * var v2 = p5.Vector.div(v, 2);
+ * // v2 has components [3, 2, 1]
+ *
+ *
+ */
+p5.Vector.prototype.div = function (n) {
+ this.x /= n;
+ this.y /= n;
+ this.z /= n;
+ return this;
+};
+
+/**
+ * Calculates the magnitude (length) of the vector and returns the result as
+ * a float (this is simply the equation sqrt(x*x + y*y + z*z).)
+ *
+ * @method mag
+ * @return {Number} magnitude of the vector
+ * @example
+ *
+ *
+ * var v = createVector(20.0, 30.0, 40.0);
+ * var m = v.mag();
+ * print(m); // Prints "53.85164807134504"
+ *
+ *
+ */
+p5.Vector.prototype.mag = function () {
+ return Math.sqrt(this.magSq());
+};
+
+/**
+ * Calculates the squared magnitude of the vector and returns the result
+ * as a float (this is simply the equation (x*x + y*y + z*z).)
+ * Faster if the real length is not required in the
+ * case of comparing vectors, etc.
+ *
+ * @method magSq
+ * @return {number} squared magnitude of the vector
+ * @example
+ *
+ *
+ * // Static method
+ * var v1 = createVector(6, 4, 2);
+ * print(v1.magSq()); // Prints "56"
+ *
+ *
+ */
+p5.Vector.prototype.magSq = function () {
+ var x = this.x, y = this.y, z = this.z;
+ return (x * x + y * y + z * z);
+};
+
+/**
+ * Calculates the dot product of two vectors. The version of the method
+ * that computes the dot product of two independent vectors is a static
+ * method. See the examples for more context.
+ *
+ *
+ * @method dot
+ * @param {Number|p5.Vector} x x component of the vector or a p5.Vector
+ * @param {Number} [y] y component of the vector
+ * @param {Number} [z] z component of the vector
+ * @return {Number} the dot product
+ *
+ * @example
+ *
+ *
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = createVector(2, 3, 4);
+ *
+ * print(v1.dot(v2)); // Prints "20"
+ *
+ *
+ *
+ *
+ *
+ * //Static method
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = createVector(3, 2, 1);
+ * print (p5.Vector.dot(v1, v2)); // Prints "10"
+ *
+ *
+ */
+p5.Vector.prototype.dot = function (x, y, z) {
+ if (x instanceof p5.Vector) {
+ return this.dot(x.x, x.y, x.z);
+ }
+ return this.x * (x || 0) +
+ this.y * (y || 0) +
+ this.z * (z || 0);
+};
+
+/**
+ * Calculates and returns a vector composed of the cross product between
+ * two vectors. Both the static and non static methods return a new p5.Vector.
+ * See the examples for more context.
+ *
+ * @method cross
+ * @param {p5.Vector} v p5.Vector to be crossed
+ * @return {p5.Vector} p5.Vector composed of cross product
+ * @example
+ *
+ *
+ * var v1 = createVector(1, 2, 3);
+ * var v2 = createVector(1, 2, 3);
+ *
+ * v1.cross(v2); // v's components are [0, 0, 0]
+ *
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(1, 0, 0);
+ * var v2 = createVector(0, 1, 0);
+ *
+ * var crossProduct = p5.Vector.cross(v1, v2);
+ * // crossProduct has components [0, 0, 1]
+ *
+ *
+ */
+p5.Vector.prototype.cross = function (v) {
+ var x = this.y * v.z - this.z * v.y;
+ var y = this.z * v.x - this.x * v.z;
+ var z = this.x * v.y - this.y * v.x;
+ if (this.p5) {
+ return new p5.Vector(this.p5,[x,y,z]);
+ } else {
+ return new p5.Vector(x,y,z);
+ }
+};
+
+/**
+ * Calculates the Euclidean distance between two points (considering a
+ * point as a vector object).
+ *
+ * @method dist
+ * @param {p5.Vector} v the x, y, and z coordinates of a p5.Vector
+ * @return {Number} the distance
+ * @example
+ *
+ *
+ * var v1 = createVector(1, 0, 0);
+ * var v2 = createVector(0, 1, 0);
+ *
+ * var distance = v1.dist(v2); // distance is 1.4142...
+ *
+ *
+ *
+ *
+ * // Static method
+ * var v1 = createVector(1, 0, 0);
+ * var v2 = createVector(0, 1, 0);
+ *
+ * var distance = p5.Vector.dist(v1,v2);
+ * // distance is 1.4142...
+ *
+ *
+ */
+p5.Vector.prototype.dist = function (v) {
+ var d = v.copy().sub(this);
+ return d.mag();
+};
+
+/**
+ * Normalize the vector to length 1 (make it a unit vector).
+ *
+ * @method normalize
+ * @return {p5.Vector} normalized p5.Vector
+ * @example
+ *
+ *
+ * var v = createVector(10, 20, 2);
+ * // v has components [10.0, 20.0, 2.0]
+ * v.normalize();
+ * // v's components are set to
+ * // [0.4454354, 0.8908708, 0.089087084]
+ *
+ *
+ *
+ */
+p5.Vector.prototype.normalize = function () {
+ return this.mag() === 0 ? this : this.div(this.mag());
+};
+
+/**
+ * Limit the magnitude of this vector to the value used for the max
+ * parameter.
+ *
+ * @method limit
+ * @param {Number} max the maximum magnitude for the vector
+ * @return {p5.Vector} the modified p5.Vector
+ * @example
+ *
+ *
+ * var v = createVector(10, 20, 2);
+ * // v has components [10.0, 20.0, 2.0]
+ * v.limit(5);
+ * // v's components are set to
+ * // [2.2271771, 4.4543543, 0.4454354]
+ *
+ *
+ */
+p5.Vector.prototype.limit = function (max) {
+ var mSq = this.magSq();
+ if(mSq > max*max) {
+ this.div(Math.sqrt(mSq)); //normalize it
+ this.mult(max);
+ }
+ return this;
+};
+
+/**
+ * Set the magnitude of this vector to the value used for the len
+ * parameter.
+ *
+ * @method setMag
+ * @param {number} len the new length for this vector
+ * @return {p5.Vector} the modified p5.Vector
+ * @example
+ *
+ *
+ * var v = createVector(10, 20, 2);
+ * // v has components [10.0, 20.0, 2.0]
+ * v.setMag(10);
+ * // v's components are set to [6.0, 8.0, 0.0]
+ *
+ *
+ */
+p5.Vector.prototype.setMag = function (n) {
+ return this.normalize().mult(n);
+};
+
+/**
+ * Calculate the angle of rotation for this vector (only 2D vectors)
+ *
+ * @method heading
+ * @return {Number} the angle of rotation
+ * @example
+ *
+ * function setup() {
+ * var v1 = createVector(30,50);
+ * print(v1.heading()); // 1.0303768265243125
+ *
+ * var v1 = createVector(40,50);
+ * print(v1.heading()); // 0.8960553845713439
+ *
+ * var v1 = createVector(30,70);
+ * print(v1.heading()); // 1.1659045405098132
+ * }
+ *
+ */
+p5.Vector.prototype.heading = function () {
+ var h = Math.atan2(this.y, this.x);
+ if (this.p5) {
+ if (this.p5._angleMode === constants.RADIANS) {
+ return h;
+ } else {
+ return polarGeometry.radiansToDegrees(h);
+ }
+ } else {
+ return h;
+ }
+};
+
+/**
+ * Rotate the vector by an angle (only 2D vectors), magnitude remains the
+ * same
+ *
+ * @method rotate
+ * @param {number} angle the angle of rotation
+ * @return {p5.Vector} the modified p5.Vector
+ * @example
+ *
+ *
+ * var v = createVector(10.0, 20.0);
+ * // v has components [10.0, 20.0, 0.0]
+ * v.rotate(HALF_PI);
+ * // v's components are set to [-20.0, 9.999999, 0.0]
+ *
+ *
+ */
+p5.Vector.prototype.rotate = function (a) {
+ var newHeading = this.heading() + a;
+ if (this.p5) {
+ if (this.p5._angleMode === constants.DEGREES) {
+ newHeading = polarGeometry.degreesToRadians(newHeading);
+ }
+ }
+ var mag = this.mag();
+ this.x = Math.cos(newHeading) * mag;
+ this.y = Math.sin(newHeading) * mag;
+ return this;
+};
+
+/**
+ * Linear interpolate the vector to another vector
+ *
+ * @method lerp
+ * @param {p5.Vector} x the x component or the p5.Vector to lerp to
+ * @param {p5.Vector} [y] y the y component
+ * @param {p5.Vector} [z] z the z component
+ * @param {Number} amt the amount of interpolation; some value between 0.0
+ * (old vector) and 1.0 (new vector). 0.1 is very near
+ * the new vector. 0.5 is halfway in between.
+ * @return {p5.Vector} the modified p5.Vector
+ * @example
+ *
+ *
+ * var v = createVector(1, 1, 0);
+ *
+ * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
+ *
+ *
+ *
+ *
+ *
+ * var v1 = createVector(0, 0, 0);
+ * var v2 = createVector(100, 100, 0);
+ *
+ * var v3 = p5.Vector.lerp(v1, v2, 0.5);
+ * // v3 has components [50,50,0]
+ *
+ *
+ */
+p5.Vector.prototype.lerp = function (x, y, z, amt) {
+ if (x instanceof p5.Vector) {
+ return this.lerp(x.x, x.y, x.z, y);
+ }
+ this.x += (x - this.x) * amt || 0;
+ this.y += (y - this.y) * amt || 0;
+ this.z += (z - this.z) * amt || 0;
+ return this;
+};
+
+/**
+ * Return a representation of this vector as a float array. This is only
+ * for temporary use. If used in any other fashion, the contents should be
+ * copied by using the p5.Vector.copy() method to copy into your own
+ * array.
+ *
+ * @method array
+ * @return {Array} an Array with the 3 values
+ * @example
+ *
+ * function setup() {
+ * var v = createVector(20,30);
+ * print(v.array()); // Prints : Array [20, 30, 0]
+ * }
+ *
+ *
+ *
+ * var v = createVector(10.0, 20.0, 30.0);
+ * var f = v.array();
+ * print(f[0]); // Prints "10.0"
+ * print(f[1]); // Prints "20.0"
+ * print(f[2]); // Prints "30.0"
+ *
+ *
+ */
+p5.Vector.prototype.array = function () {
+ return [this.x || 0, this.y || 0, this.z || 0];
+};
+
+/**
+ * Equality check against a p5.Vector
+ *
+ * @method equals
+ * @param {Number|p5.Vector|Array} [x] the x component of the vector or a
+ * p5.Vector or an Array
+ * @param {Number} [y] the y component of the vector
+ * @param {Number} [z] the z component of the vector
+ * @return {Boolean} whether the vectors are equals
+ * @example
+ *
+ * v1 = createVector(5,10,20);
+ * v2 = createVector(5,10,20);
+ * v3 = createVector(13,10,19);
+ *
+ * print(v1.equals(v2.x,v2.y,v2.z)); // true
+ * print(v1.equals(v3.x,v3.y,v3.z)); // false
+ *
+ *
+ *
+ * var v1 = createVector(10.0, 20.0, 30.0);
+ * var v2 = createVector(10.0, 20.0, 30.0);
+ * var v3 = createVector(0.0, 0.0, 0.0);
+ * print (v1.equals(v2)) // true
+ * print (v1.equals(v3)) // false
+ *
+ *
+ */
+p5.Vector.prototype.equals = function (x, y, z) {
+ var a, b, c;
+ if (x instanceof p5.Vector) {
+ a = x.x || 0;
+ b = x.y || 0;
+ c = x.z || 0;
+ } else if (x instanceof Array) {
+ a = x[0] || 0;
+ b = x[1] || 0;
+ c = x[2] || 0;
+ } else {
+ a = x || 0;
+ b = y || 0;
+ c = z || 0;
+ }
+ return this.x === a && this.y === b && this.z === c;
+};
+
+
+// Static Methods
+
+
+/**
+ * Make a new 2D unit vector from an angle
+ *
+ * @method fromAngle
+ * @static
+ * @param {Number} angle the desired angle
+ * @return {p5.Vector} the new p5.Vector object
+ * @example
+ *
+ *
+ * function draw() {
+ * background (200);
+ *
+ * // Create a variable, proportional to the mouseX,
+ * // varying from 0-360, to represent an angle in degrees.
+ * angleMode(DEGREES);
+ * var myDegrees = map(mouseX, 0,width, 0,360);
+ *
+ * // Display that variable in an onscreen text.
+ * // (Note the nfc() function to truncate additional decimal places,
+ * // and the "\xB0" character for the degree symbol.)
+ * var readout = "angle = " + nfc(myDegrees,1,1) + "\xB0"
+ * noStroke();
+ * fill (0);
+ * text (readout, 5, 15);
+ *
+ * // Create a p5.Vector using the fromAngle function,
+ * // and extract its x and y components.
+ * var v = p5.Vector.fromAngle(radians(myDegrees));
+ * var vx = v.x;
+ * var vy = v.y;
+ *
+ * push();
+ * translate (width/2, height/2);
+ * noFill();
+ * stroke (150);
+ * line (0,0, 30,0);
+ * stroke (0);
+ * line (0,0, 30*vx, 30*vy);
+ * pop()
+ * }
+ *
+ *
+ */
+p5.Vector.fromAngle = function(angle) {
+ if (this.p5) {
+ if (this.p5._angleMode === constants.DEGREES) {
+ angle = polarGeometry.degreesToRadians(angle);
+ }
+ }
+ if (this.p5) {
+ return new p5.Vector(this.p5,[Math.cos(angle),Math.sin(angle),0]);
+ } else {
+ return new p5.Vector(Math.cos(angle),Math.sin(angle),0);
+ }
+};
+
+/**
+ * Make a new 2D unit vector from a random angle
+ *
+ * @method random2D
+ * @static
+ * @return {p5.Vector} the new p5.Vector object
+ * @example
+ *
+ *
+ * var v = p5.Vector.random2D();
+ * // May make v's attributes something like:
+ * // [0.61554617, -0.51195765, 0.0] or
+ * // [-0.4695841, -0.14366731, 0.0] or
+ * // [0.6091097, -0.22805278, 0.0]
+ *
+ *
+ */
+p5.Vector.random2D = function () {
+ var angle;
+ // A lot of nonsense to determine if we know about a
+ // p5 sketch and whether we should make a random angle in degrees or radians
+ if (this.p5) {
+ if (this.p5._angleMode === constants.DEGREES) {
+ angle = this.p5.random(360);
+ } else {
+ angle = this.p5.random(constants.TWO_PI);
+ }
+ } else {
+ angle = Math.random()*Math.PI*2;
+ }
+ return this.fromAngle(angle);
+};
+
+/**
+ * Make a new random 3D unit vector.
+ *
+ * @method random3D
+ * @static
+ * @return {p5.Vector} the new p5.Vector object
+ * @example
+ *
+ *
+ * var v = p5.Vector.random3D();
+ * // May make v's attributes something like:
+ * // [0.61554617, -0.51195765, 0.599168] or
+ * // [-0.4695841, -0.14366731, -0.8711202] or
+ * // [0.6091097, -0.22805278, -0.7595902]
+ *
+ *
+ */
+p5.Vector.random3D = function () {
+ var angle,vz;
+ // If we know about p5
+ if (this.p5) {
+ angle = this.p5.random(0,constants.TWO_PI);
+ vz = this.p5.random(-1,1);
+ } else {
+ angle = Math.random()*Math.PI*2;
+ vz = Math.random()*2-1;
+ }
+ var vx = Math.sqrt(1-vz*vz)*Math.cos(angle);
+ var vy = Math.sqrt(1-vz*vz)*Math.sin(angle);
+ if (this.p5) {
+ return new p5.Vector(this.p5,[vx,vy,vz]);
+ } else {
+ return new p5.Vector(vx,vy,vz);
+ }
+};
+
+
+/**
+ * Adds two vectors together and returns a new one.
+ *
+ * @static
+ * @param {p5.Vector} v1 a p5.Vector to add
+ * @param {p5.Vector} v2 a p5.Vector to add
+ * @param {p5.Vector} target if undefined a new vector will be created
+ * @return {p5.Vector} the resulting p5.Vector
+ *
+ */
+
+p5.Vector.add = function (v1, v2, target) {
+ if (!target) {
+ target = v1.copy();
+ } else {
+ target.set(v1);
+ }
+ target.add(v2);
+ return target;
+};
+
+/**
+ * Subtracts one p5.Vector from another and returns a new one. The second
+ * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
+ *
+ * @static
+ * @param {p5.Vector} v1 a p5.Vector to subtract from
+ * @param {p5.Vector} v2 a p5.Vector to subtract
+ * @param {p5.Vector} target if undefined a new vector will be created
+ * @return {p5.Vector} the resulting p5.Vector
+ */
+
+p5.Vector.sub = function (v1, v2, target) {
+ if (!target) {
+ target = v1.copy();
+ } else {
+ target.set(v1);
+ }
+ target.sub(v2);
+ return target;
+};
+
+
+/**
+ * Multiplies a vector by a scalar and returns a new vector.
+ *
+ * @static
+ * @param {p5.Vector} v the p5.Vector to multiply
+ * @param {Number} n the scalar
+ * @param {p5.Vector} target if undefined a new vector will be created
+ * @return {p5.Vector} the resulting new p5.Vector
+ */
+p5.Vector.mult = function (v, n, target) {
+ if (!target) {
+ target = v.copy();
+ } else {
+ target.set(v);
+ }
+ target.mult(n);
+ return target;
+};
+
+/**
+ * Divides a vector by a scalar and returns a new vector.
+ *
+ * @static
+ * @param {p5.Vector} v the p5.Vector to divide
+ * @param {Number} n the scalar
+ * @param {p5.Vector} target if undefined a new vector will be created
+ * @return {p5.Vector} the resulting new p5.Vector
+ */
+p5.Vector.div = function (v, n, target) {
+ if (!target) {
+ target = v.copy();
+ } else {
+ target.set(v);
+ }
+ target.div(n);
+ return target;
+};
+
+
+/**
+ * Calculates the dot product of two vectors.
+ *
+ * @static
+ * @param {p5.Vector} v1 the first p5.Vector
+ * @param {p5.Vector} v2 the second p5.Vector
+ * @return {Number} the dot product
+ */
+p5.Vector.dot = function (v1, v2) {
+ return v1.dot(v2);
+};
+
+/**
+ * Calculates the cross product of two vectors.
+ *
+ * @static
+ * @param {p5.Vector} v1 the first p5.Vector
+ * @param {p5.Vector} v2 the second p5.Vector
+ * @return {Number} the cross product
+ */
+p5.Vector.cross = function (v1, v2) {
+ return v1.cross(v2);
+};
+
+/**
+ * Calculates the Euclidean distance between two points (considering a
+ * point as a vector object).
+ *
+ * @static
+ * @param {p5.Vector} v1 the first p5.Vector
+ * @param {p5.Vector} v2 the second p5.Vector
+ * @return {Number} the distance
+ */
+p5.Vector.dist = function (v1,v2) {
+ return v1.dist(v2);
+};
+
+/**
+ * Linear interpolate a vector to another vector and return the result as a
+ * new vector.
+ *
+ * @static
+ * @param {p5.Vector} v1 a starting p5.Vector
+ * @param {p5.Vector} v2 the p5.Vector to lerp to
+ * @param {Number} the amount of interpolation; some value between 0.0
+ * (old vector) and 1.0 (new vector). 0.1 is very near
+ * the new vector. 0.5 is halfway in between.
+ */
+p5.Vector.lerp = function (v1, v2, amt, target) {
+ if (!target) {
+ target = v1.copy();
+ } else {
+ target.set(v1);
+ }
+ target.lerp(v2, amt);
+ return target;
+};
+
+/**
+ * Calculates and returns the angle (in radians) between two vectors.
+ * @method angleBetween
+ * @static
+ * @param {p5.Vector} v1 the x, y, and z components of a p5.Vector
+ * @param {p5.Vector} v2 the x, y, and z components of a p5.Vector
+ * @return {Number} the angle between (in radians)
+ * @example
+ *
+ *
+ * var v1 = createVector(1, 0, 0);
+ * var v2 = createVector(0, 1, 0);
+ *
+ * var angle = p5.Vector.angleBetween(v1, v2);
+ * // angle is PI/2
+ *
+ *
+ */
+p5.Vector.angleBetween = function (v1, v2) {
+ var angle = Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()));
+ if (this.p5) {
+ if (this.p5._angleMode === constants.DEGREES) {
+ angle = polarGeometry.radiansToDegrees(angle);
+ }
+ }
+ return angle;
+};
+
+/**
+ * @static
+ */
+p5.Vector.mag = function (vecT){
+ var x = vecT.x,
+ y = vecT.y,
+ z = vecT.z;
+ var magSq = x * x + y * y + z * z;
+ return Math.sqrt(magSq);
+};
+
+module.exports = p5.Vector;
+
+},{"../core/constants":36,"../core/core":37,"./polargeometry":67}],67:[function(_dereq_,module,exports){
+
+module.exports = {
+
+ degreesToRadians: function(x) {
+ return 2 * Math.PI * x / 360;
+ },
+
+ radiansToDegrees: function(x) {
+ return 360 * x / (2 * Math.PI);
+ }
+
+};
+
+},{}],68:[function(_dereq_,module,exports){
+/**
+ * @module Math
+ * @submodule Random
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+var seeded = false;
+var previous = false;
+var y2 = 0;
+
+// Linear Congruential Generator
+// Variant of a Lehman Generator
+var lcg = (function() {
+ // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
+ // m is basically chosen to be large (as it is the max period)
+ // and for its relationships to a and c
+ var m = 4294967296,
+ // a - 1 should be divisible by m's prime factors
+ a = 1664525,
+ // c and m should be co-prime
+ c = 1013904223,
+ seed, z;
+ return {
+ setSeed : function(val) {
+ // pick a random seed if val is undefined or null
+ // the >>> 0 casts the seed to an unsigned 32-bit integer
+ z = seed = (val == null ? Math.random() * m : val) >>> 0;
+ },
+ getSeed : function() {
+ return seed;
+ },
+ rand : function() {
+ // define the recurrence relationship
+ z = (a * z + c) % m;
+ // return a float in [0, 1)
+ // if z = m then z / m = 0 therefore (z % m) / m < 1 always
+ return z / m;
+ }
+ };
+}());
+
+/**
+ * Sets the seed value for random().
+ *
+ * By default, random() produces different results each time the program
+ * is run. Set the seed parameter to a constant to return the same
+ * pseudo-random numbers each time the software is run.
+ *
+ * @method randomSeed
+ * @param {Number} seed the seed value
+ * @example
+ *
+ *
+ * randomSeed(99);
+ * for (var i=0; i < 100; i++) {
+ * var r = random(0, 255);
+ * stroke(r);
+ * line(i, 0, i, 100);
+ * }
+ *
+ *
+ *
+ * @alt
+ * many vertical lines drawn in white, black or grey.
+ *
+ */
+p5.prototype.randomSeed = function(seed) {
+ lcg.setSeed(seed);
+ seeded = true;
+ previous = false;
+};
+
+/**
+ * Return a random floating-point number.
+ *
+ * Takes either 0, 1 or 2 arguments.
+ *
+ * If no argument is given, returns a random number from 0
+ * up to (but not including) 1.
+ *
+ * If one argument is given and it is a number, returns a random number from 0
+ * up to (but not including) the number.
+ *
+ * If one argument is given and it is an array, returns a random element from
+ * that array.
+ *
+ * If two arguments are given, returns a random number from the
+ * first argument up to (but not including) the second argument.
+ *
+ * @method random
+ * @param {Number} [min] the lower bound (inclusive)
+ * @param {Number} [max] the upper bound (exclusive)
+ * @return {Number|mixed} the random number or a random element in choices
+ * @example
+ *
+ *
+ * for (var i = 0; i < 100; i++) {
+ * var r = random(50);
+ * stroke(r*5);
+ * line(50, i, 50+r, i);
+ * }
+ *
+ *
+ *
+ *
+ * for (var i = 0; i < 100; i++) {
+ * var r = random(-50, 50);
+ * line(50,i,50+r,i);
+ * }
+ *
+ *
+ *
+ *
+ * // Get a random element from an array using the random(Array) syntax
+ * var words = [ "apple", "bear", "cat", "dog" ];
+ * var word = random(words); // select random word
+ * text(word,10,50); // draw the word
+ *
+ *
+ *
+ * @alt
+ * 100 horizontal lines from center canvas to right. size+fill change each time
+ * 100 horizontal lines from center of canvas. height & side change each render
+ * word displayed at random. Either apple, bear, cat, or dog
+ *
+ */
+/**
+ * @method random
+ * @param {Array} choices the array to choose from
+ * @return {mixed} the random element from the array
+ * @example
+ */
+p5.prototype.random = function (min, max) {
+
+ var rand;
+
+ if (seeded) {
+ rand = lcg.rand();
+ } else {
+ rand = Math.random();
+ }
+ if (typeof min === 'undefined') {
+ return rand;
+ } else
+ if (typeof max === 'undefined') {
+ if (min instanceof Array) {
+ return min[Math.floor(rand * min.length)];
+ } else {
+ return rand * min;
+ }
+ } else {
+ if (min > max) {
+ var tmp = min;
+ min = max;
+ max = tmp;
+ }
+
+ return rand * (max-min) + min;
+ }
+};
+
+
+/**
+ *
+ * Returns a random number fitting a Gaussian, or
+ * normal, distribution. There is theoretically no minimum or maximum
+ * value that randomGaussian() might return. Rather, there is
+ * just a very low probability that values far from the mean will be
+ * returned; and a higher probability that numbers near the mean will
+ * be returned.
+ *
+ * Takes either 0, 1 or 2 arguments.
+ * If no args, returns a mean of 0 and standard deviation of 1.
+ * If one arg, that arg is the mean (standard deviation is 1).
+ * If two args, first is mean, second is standard deviation.
+ *
+ * @method randomGaussian
+ * @param {Number} mean the mean
+ * @param {Number} sd the standard deviation
+ * @return {Number} the random number
+ * @example
+ *
+ * for (var y = 0; y < 100; y++) {
+ * var x = randomGaussian(50,15);
+ * line(50, y, x, y);
+ *}
+ *
+ *
+ *
+ *
+ *var distribution = new Array(360);
+ *
+ *function setup() {
+ * createCanvas(100, 100);
+ * for (var i = 0; i < distribution.length; i++) {
+ * distribution[i] = floor(randomGaussian(0,15));
+ * }
+ *}
+ *
+ *function draw() {
+ * background(204);
+ *
+ * translate(width/2, width/2);
+ *
+ * for (var i = 0; i < distribution.length; i++) {
+ * rotate(TWO_PI/distribution.length);
+ * stroke(0);
+ * var dist = abs(distribution[i]);
+ * line(0, 0, dist, 0);
+ * }
+ *}
+ *
+ *
+ * @alt
+ * 100 horizontal lines from center of canvas. height & side change each render
+ * black lines radiate from center of canvas. size determined each render
+ */
+p5.prototype.randomGaussian = function(mean, sd) {
+ var y1,x1,x2,w;
+ if (previous) {
+ y1 = y2;
+ previous = false;
+ } else {
+ do {
+ x1 = this.random(2) - 1;
+ x2 = this.random(2) - 1;
+ w = x1 * x1 + x2 * x2;
+ } while (w >= 1);
+ w = Math.sqrt((-2 * Math.log(w))/w);
+ y1 = x1 * w;
+ y2 = x2 * w;
+ previous = true;
+ }
+
+ var m = mean || 0;
+ var s = sd || 1;
+ return y1*s + m;
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],69:[function(_dereq_,module,exports){
+/**
+ * @module Math
+ * @submodule Trigonometry
+ * @for p5
+ * @requires core
+ * @requires polargeometry
+ * @requires constants
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var polarGeometry = _dereq_('./polargeometry');
+var constants = _dereq_('../core/constants');
+
+p5.prototype._angleMode = constants.RADIANS;
+
+/**
+ * The inverse of cos(), returns the arc cosine of a value. This function
+ * expects the values in the range of -1 to 1 and values are returned in
+ * the range 0 to PI (3.1415927).
+ *
+ * @method acos
+ * @param {Number} value the value whose arc cosine is to be returned
+ * @return {Number} the arc cosine of the given value
+ *
+ * @example
+ *
+ *
+ * var a = PI;
+ * var c = cos(a);
+ * var ac = acos(c);
+ * // Prints: "3.1415927 : -1.0 : 3.1415927"
+ * print(a + " : " + c + " : " + ac);
+ *
+ *
+ *
+ *
+ *
+ * var a = PI + PI/4.0;
+ * var c = cos(a);
+ * var ac = acos(c);
+ * // Prints: "3.926991 : -0.70710665 : 2.3561943"
+ * print(a + " : " + c + " : " + ac);
+ *
+ *
+ */
+p5.prototype.acos = function(ratio) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.acos(ratio);
+ } else {
+ return polarGeometry.radiansToDegrees(Math.acos(ratio));
+ }
+};
+
+/**
+ * The inverse of sin(), returns the arc sine of a value. This function
+ * expects the values in the range of -1 to 1 and values are returned
+ * in the range -PI/2 to PI/2.
+ *
+ * @method asin
+ * @param {Number} value the value whose arc sine is to be returned
+ * @return {Number} the arc sine of the given value
+ *
+ * @example
+ *
+ *
+ * var a = PI + PI/3;
+ * var s = sin(a);
+ * var as = asin(s);
+ * // Prints: "1.0471976 : 0.86602545 : 1.0471976"
+ * print(a + " : " + s + " : " + as);
+ *
+ *
+ *
+ *
+ *
+ * var a = PI + PI/3.0;
+ * var s = sin(a);
+ * var as = asin(s);
+ * // Prints: "4.1887903 : -0.86602545 : -1.0471976"
+ * print(a + " : " + s + " : " + as);
+ *
+ *
+ *
+ */
+p5.prototype.asin = function(ratio) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.asin(ratio);
+ } else {
+ return polarGeometry.radiansToDegrees(Math.asin(ratio));
+ }
+};
+
+/**
+ * The inverse of tan(), returns the arc tangent of a value. This function
+ * expects the values in the range of -Infinity to Infinity (exclusive) and
+ * values are returned in the range -PI/2 to PI/2.
+ *
+ * @method atan
+ * @param {Number} value the value whose arc tangent is to be returned
+ * @return {Number} the arc tangent of the given value
+ *
+ * @example
+ *
+ *
+ * var a = PI + PI/3;
+ * var t = tan(a);
+ * var at = atan(t);
+ * // Prints: "1.0471976 : 1.7320509 : 1.0471976"
+ * print(a + " : " + t + " : " + at);
+ *
+ *
+ *
+ *
+ *
+ * var a = PI + PI/3.0;
+ * var t = tan(a);
+ * var at = atan(t);
+ * // Prints: "4.1887903 : 1.7320513 : 1.0471977"
+ * print(a + " : " + t + " : " + at);
+ *
+ *
+ *
+ */
+p5.prototype.atan = function(ratio) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.atan(ratio);
+ } else {
+ return polarGeometry.radiansToDegrees(Math.atan(ratio));
+ }
+};
+
+/**
+ * Calculates the angle (in radians) from a specified point to the coordinate
+ * origin as measured from the positive x-axis. Values are returned as a
+ * float in the range from PI to -PI. The atan2() function is most often used
+ * for orienting geometry to the position of the cursor.
+ *
+ * Note: The y-coordinate of the point is the first parameter, and the
+ * x-coordinate is the second parameter, due the the structure of calculating
+ * the tangent.
+ *
+ * @method atan2
+ * @param {Number} y y-coordinate of the point
+ * @param {Number} x x-coordinate of the point
+ * @return {Number} the arc tangent of the given point
+ *
+ * @example
+ *
+ *
+ * function draw() {
+ * background(204);
+ * translate(width/2, height/2);
+ * var a = atan2(mouseY-height/2, mouseX-width/2);
+ * rotate(a);
+ * rect(-30, -5, 60, 10);
+ * }
+ *
+ *
+ *
+ * @alt
+ * 60 by 10 rect at center of canvas rotates with mouse movements
+ *
+ */
+p5.prototype.atan2 = function (y, x) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.atan2(y, x);
+ } else {
+ return polarGeometry.radiansToDegrees(Math.atan2(y, x));
+ }
+};
+
+/**
+ * Calculates the cosine of an angle. This function takes into account the
+ * current angleMode. Values are returned in the range -1 to 1.
+ *
+ * @method cos
+ * @param {Number} angle the angle
+ * @return {Number} the cosine of the angle
+ *
+ * @example
+ *
+ *
+ * var a = 0.0;
+ * var inc = TWO_PI/25.0;
+ * for (var i = 0; i < 25; i++) {
+ * line(i*4, 50, i*4, 50+cos(a)*40.0);
+ * a = a + inc;
+ * }
+ *
+ *
+ *
+ * @alt
+ * vertical black lines form wave patterns, extend-down on left and right side
+ *
+ */
+p5.prototype.cos = function(angle) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.cos(angle);
+ } else {
+ return Math.cos(this.radians(angle));
+ }
+};
+
+/**
+ * Calculates the sine of an angle. This function takes into account the
+ * current angleMode. Values are returned in the range -1 to 1.
+ *
+ * @method sin
+ * @param {Number} angle the angle
+ * @return {Number} the sine of the angle
+ *
+ * @example
+ *
+ *
+ * var a = 0.0;
+ * var inc = TWO_PI/25.0;
+ * for (var i = 0; i < 25; i++) {
+ * line(i*4, 50, i*4, 50+sin(a)*40.0);
+ * a = a + inc;
+ * }
+ *
+ *
+ *
+ * @alt
+ * vertical black lines extend down and up from center to form wave pattern
+ *
+ */
+p5.prototype.sin = function(angle) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.sin(angle);
+ } else {
+ return Math.sin(this.radians(angle));
+ }
+};
+
+/**
+ * Calculates the tangent of an angle. This function takes into account
+ * the current angleMode. Values are returned in the range -1 to 1.
+ *
+ * @method tan
+ * @param {Number} angle the angle
+ * @return {Number} the tangent of the angle
+ *
+ * @example
+ *
+ *
+ * var a = 0.0;
+ * var inc = TWO_PI/50.0;
+ * for (var i = 0; i < 100; i = i+2) {
+ * line(i, 50, i, 50+tan(a)*2.0);
+ * a = a + inc;
+ * }
+ *
+ *
+ *
+ * @alt
+ * vertical black lines end down and up from center to form spike pattern
+ *
+ */
+p5.prototype.tan = function(angle) {
+ if (this._angleMode === constants.RADIANS) {
+ return Math.tan(angle);
+ } else {
+ return Math.tan(this.radians(angle));
+ }
+};
+
+/**
+ * Converts a radian measurement to its corresponding value in degrees.
+ * Radians and degrees are two ways of measuring the same thing. There are
+ * 360 degrees in a circle and 2*PI radians in a circle. For example,
+ * 90° = PI/2 = 1.5707964.
+ *
+ * @method degrees
+ * @param {Number} radians the radians value to convert to degrees
+ * @return {Number} the converted angle
+ *
+ *
+ * @example
+ *
+ *
+ * var rad = PI/4;
+ * var deg = degrees(rad);
+ * print(rad + " radians is " + deg + " degrees");
+ * // Prints: 0.7853981633974483 radians is 45 degrees
+ *
+ *
+ *
+ */
+p5.prototype.degrees = function(angle) {
+ return polarGeometry.radiansToDegrees(angle);
+};
+
+/**
+ * Converts a degree measurement to its corresponding value in radians.
+ * Radians and degrees are two ways of measuring the same thing. There are
+ * 360 degrees in a circle and 2*PI radians in a circle. For example,
+ * 90° = PI/2 = 1.5707964.
+ *
+ * @method radians
+ * @param {Number} degrees the degree value to convert to radians
+ * @return {Number} the converted angle
+ *
+ * @example
+ *
+ *
+ * var deg = 45.0;
+ * var rad = radians(deg);
+ * print(deg + " degrees is " + rad + " radians");
+ * // Prints: 45 degrees is 0.7853981633974483 radians
+ *
+ *
+ */
+p5.prototype.radians = function(angle) {
+ return polarGeometry.degreesToRadians(angle);
+};
+
+/**
+ * Sets the current mode of p5 to given mode. Default mode is RADIANS.
+ *
+ * @method angleMode
+ * @param {Constant} mode either RADIANS or DEGREES
+ *
+ * @example
+ *
+ *
+ * function draw(){
+ * background(204);
+ * angleMode(DEGREES); // Change the mode to DEGREES
+ * var a = atan2(mouseY-height/2, mouseX-width/2);
+ * translate(width/2, height/2);
+ * push();
+ * rotate(a);
+ * rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
+ * pop();
+ * angleMode(RADIANS); // Change the mode to RADIANS
+ * rotate(a); // var a stays the same
+ * rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
+ * }
+ *
+ *
+ *
+ * @alt
+ * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.
+ *
+ *
+ */
+p5.prototype.angleMode = function(mode) {
+ if (mode === constants.DEGREES || mode === constants.RADIANS) {
+ this._angleMode = mode;
+ }
+};
+
+module.exports = p5;
+
+},{"../core/constants":36,"../core/core":37,"./polargeometry":67}],70:[function(_dereq_,module,exports){
+/**
+ * @module Typography
+ * @submodule Attributes
+ * @for p5
+ * @requires core
+ * @requires constants
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Sets the current alignment for drawing text. Accepts two
+ * arguments: horizAlign (LEFT, CENTER, or RIGHT) and
+ * vertAlign (TOP, BOTTOM, CENTER, or BASELINE).
+ *
+ * The horizAlign parameter is in reference to the x value
+ * of the text() function, while the vertAlign parameter is
+ * in reference to the y value.
+ *
+ * So if you write textAlign(LEFT), you are aligning the left
+ * edge of your text to the x value you give in text(). If you
+ * write textAlign(RIGHT, TOP), you are aligning the right edge
+ * of your text to the x value and the top of edge of the text
+ * to the y value.
+ *
+ * @method textAlign
+ * @param {Constant} horizAlign horizontal alignment, either LEFT,
+ * CENTER, or RIGHT
+ * @param {Constant} vertAlign vertical alignment, either TOP,
+ * BOTTOM, CENTER, or BASELINE
+ * @return {Number}
+ * @example
+ *
+ *
+ * textSize(16);
+ * textAlign(RIGHT);
+ * text("ABCD", 50, 30);
+ * textAlign(CENTER);
+ * text("EFGH", 50, 50);
+ * textAlign(LEFT);
+ * text("IJKL", 50, 70);
+ *
+ *
+ *
+ * @alt
+ *Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.
+ *
+ */
+p5.prototype.textAlign = function(horizAlign, vertAlign) {
+ return this._renderer.textAlign.apply(this._renderer, arguments);
+};
+
+/**
+ * Sets/gets the spacing, in pixels, between lines of text. This
+ * setting will be used in all subsequent calls to the text() function.
+ *
+ * @method textLeading
+ * @param {Number} leading the size in pixels for spacing between lines
+ * @return {Object|Number}
+ * @example
+ *
+ *
+ * // Text to display. The "\n" is a "new line" character
+ * lines = "L1\nL2\nL3";
+ * textSize(12);
+ *
+ * textLeading(10); // Set leading to 10
+ * text(lines, 10, 25);
+ *
+ * textLeading(20); // Set leading to 20
+ * text(lines, 40, 25);
+ *
+ * textLeading(30); // Set leading to 30
+ * text(lines, 70, 25);
+ *
+ *
+ *
+ * @alt
+ *set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set
+ *
+ */
+p5.prototype.textLeading = function(theLeading) {
+ return this._renderer.textLeading.apply(this._renderer, arguments);
+};
+
+/**
+ * Sets/gets the current font size. This size will be used in all subsequent
+ * calls to the text() function. Font size is measured in pixels.
+ *
+ * @method textSize
+ * @param {Number} theSize the size of the letters in units of pixels
+ * @return {Object|Number}
+ * @example
+ *
+ *
+ * textSize(12);
+ * text("Font Size 12", 10, 30);
+ * textSize(14);
+ * text("Font Size 14", 10, 60);
+ * textSize(16);
+ * text("Font Size 16", 10, 90);
+ *
+ *
+ *
+ * @alt
+ *Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large
+ *
+ */
+p5.prototype.textSize = function(theSize) {
+ return this._renderer.textSize.apply(this._renderer, arguments);
+};
+
+/**
+ * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD.
+ * Note: this may be is overridden by CSS styling. For non-system fonts
+ * (opentype, truetype, etc.) please load styled fonts instead.
+ *
+ * @method textStyle
+ * @param {Number/Constant} theStyle styling for text, either NORMAL,
+ * ITALIC, or BOLD
+ * @return {Object|String}
+ * @example
+ *
+ *
+ * strokeWeight(0);
+ * textSize(12);
+ * textStyle(NORMAL);
+ * text("Font Style Normal", 10, 30);
+ * textStyle(ITALIC);
+ * text("Font Style Italic", 10, 60);
+ * textStyle(BOLD);
+ * text("Font Style Bold", 10, 90);
+ *
+ *
+ *
+ * @alt
+ *words Font Style Normal displayed normally, Italic in italic and bold in bold
+ *
+ */
+p5.prototype.textStyle = function(theStyle) {
+ return this._renderer.textStyle.apply(this._renderer, arguments);
+};
+
+/**
+ * Calculates and returns the width of any character or text string.
+ *
+ * @method textWidth
+ * @param {String} theText the String of characters to measure
+ * @return {Number}
+ * @example
+ *
+ *
+ * textSize(28);
+ *
+ * var aChar = 'P';
+ * var cWidth = textWidth(aChar);
+ * text(aChar, 0, 40);
+ * line(cWidth, 0, cWidth, 50);
+ *
+ * var aString = "p5.js";
+ * var sWidth = textWidth(aString);
+ * text(aString, 0, 85);
+ * line(sWidth, 50, sWidth, 100);
+ *
+ *
+ *
+ * @alt
+ *Letter P and p5.js are displayed with vertical lines at end. P is wide
+ *
+ */
+p5.prototype.textWidth = function(theText) {
+ if (theText.length === 0) {
+ return 0;
+ }
+ return this._renderer.textWidth.apply(this._renderer, arguments);
+};
+
+/**
+ * Returns the ascent of the current font at its current size. The ascent
+ * represents the distance, in pixels, of the tallest character above
+ * the baseline.
+ *
+ * @return {Number}
+ * @example
+ *
+ *
+ * var base = height * 0.75;
+ * var scalar = 0.8; // Different for each font
+ *
+ * textSize(32); // Set initial text size
+ * var asc = textAscent() * scalar; // Calc ascent
+ * line(0, base - asc, width, base - asc);
+ * text("dp", 0, base); // Draw text on baseline
+ *
+ * textSize(64); // Increase text size
+ * asc = textAscent() * scalar; // Recalc ascent
+ * line(40, base - asc, width, base - asc);
+ * text("dp", 40, base); // Draw text on baseline
+ *
+ *
+ */
+p5.prototype.textAscent = function() {
+ return this._renderer.textAscent();
+};
+
+/**
+ * Returns the descent of the current font at its current size. The descent
+ * represents the distance, in pixels, of the character with the longest
+ * descender below the baseline.
+ *
+ * @return {Number}
+ * @example
+ *
+ *
+ * var base = height * 0.75;
+ * var scalar = 0.8; // Different for each font
+ *
+ * textSize(32); // Set initial text size
+ * var desc = textDescent() * scalar; // Calc ascent
+ * line(0, base+desc, width, base+desc);
+ * text("dp", 0, base); // Draw text on baseline
+ *
+ * textSize(64); // Increase text size
+ * desc = textDescent() * scalar; // Recalc ascent
+ * line(40, base + desc, width, base + desc);
+ * text("dp", 40, base); // Draw text on baseline
+ *
+ *
+ */
+p5.prototype.textDescent = function() {
+ return this._renderer.textDescent();
+};
+
+/**
+ * Helper function to measure ascent and descent.
+ */
+p5.prototype._updateTextMetrics = function() {
+ return this._renderer._updateTextMetrics();
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],71:[function(_dereq_,module,exports){
+/**
+ * @module Typography
+ * @submodule Loading & Displaying
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var constants = _dereq_('../core/constants');
+
+_dereq_('../core/error_helpers');
+
+
+/**
+ * Draws text to the screen. Displays the information specified in the first
+ * parameter on the screen in the position specified by the additional
+ * parameters. A default font will be used unless a font is set with the
+ * textFont() function and a default size will be used unless a font is set
+ * with textSize(). Change the color of the text with the fill() function.
+ * Change the outline of the text with the stroke() and strokeWeight()
+ * functions.
+ *
+ * The text displays in relation to the textAlign() function, which gives the
+ * option to draw to the left, right, and center of the coordinates.
+ *
+ * The x2 and y2 parameters define a rectangular area to display within and
+ * may only be used with string data. When these parameters are specified,
+ * they are interpreted based on the current rectMode() setting. Text that
+ * does not fit completely within the rectangle specified will not be drawn
+ * to the screen.
+ *
+ * @method text
+ * @param {String} str the alphanumeric symbols to be displayed
+ * @param {Number} x x-coordinate of text
+ * @param {Number} y y-coordinate of text
+ * @param {Number} x2 by default, the width of the text box,
+ * see rectMode() for more info
+ * @param {Number} y2 by default, the height of the text box,
+ * see rectMode() for more info
+ * @return {Object} this
+ * @example
+ *
+ *
+ * textSize(32);
+ * text("word", 10, 30);
+ * fill(0, 102, 153);
+ * text("word", 10, 60);
+ * fill(0, 102, 153, 51);
+ * text("word", 10, 90);
+ *
+ *
+ *
+ *
+ * s = "The quick brown fox jumped over the lazy dog.";
+ * fill(50);
+ * text(s, 10, 10, 70, 80); // Text wraps within text box
+ *
+ *
+ *
+ * @alt
+ *'word' displayed 3 times going from black, blue to translucent blue
+ * The quick brown fox jumped over the lazy dog.
+ *
+ */
+p5.prototype.text = function(str, x, y, maxWidth, maxHeight) {
+ return (!(this._renderer._doFill || this._renderer._doStroke)) ? this :
+ this._renderer.text.apply(this._renderer, arguments);
+};
+
+/**
+ * Sets the current font that will be drawn with the text() function.
+ *
+ * @method textFont
+ * @param {Object|String} f a font loaded via loadFont(), or a String
+ * representing a
web safe font (a font
+ * that is generally available across all systems).
+ * @return {Object} this
+ * @example
+ *
+ *
+ * fill(0);
+ * textSize(12);
+ * textFont("Georgia");
+ * text("Georgia", 12, 30);
+ * textFont("Helvetica");
+ * text("Helvetica", 12, 60);
+ *
+ *
+ *
+ *
+ * var fontRegular, fontItalic, fontBold;
+ * function preload() {
+ * fontRegular = loadFont("assets/Regular.otf");
+ * fontItalic = loadFont("assets/Italic.ttf");
+ * fontBold = loadFont("assets/Bold.ttf");
+ * }
+ * function setup() {
+ * background(210);
+ * fill(0).strokeWeight(0).textSize(10);
+ * textFont(fontRegular);
+ * text("Font Style Normal", 10, 30);
+ * textFont(fontItalic);
+ * text("Font Style Italic", 10, 50);
+ * textFont(fontBold);
+ * text("Font Style Bold", 10, 70);
+ * }
+ *
+ *
+ *
+ * @alt
+ *words Font Style Normal displayed normally, Italic in italic and bold in bold
+ *
+ */
+p5.prototype.textFont = function(theFont, theSize) {
+
+ if (arguments.length) {
+
+ if (!theFont) {
+
+ throw Error('null font passed to textFont');
+ }
+
+ this._renderer._setProperty('_textFont', theFont);
+
+ if (theSize) {
+
+ this._renderer._setProperty('_textSize', theSize);
+ this._renderer._setProperty('_textLeading',
+ theSize * constants._DEFAULT_LEADMULT);
+ }
+
+ return this._renderer._applyTextProperties();
+ }
+
+ return this;
+};
+
+module.exports = p5;
+
+},{"../core/constants":36,"../core/core":37,"../core/error_helpers":40}],72:[function(_dereq_,module,exports){
+/**
+ * This module defines the p5.Font class and functions for
+ * drawing text to the display canvas.
+ * @module Typography
+ * @submodule Font
+ * @requires core
+ * @requires constants
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var constants = _dereq_('../core/constants');
+
+/*
+ * TODO:
+ *
+ * API:
+ * -- textBounds()
+ * -- getPath()
+ * -- getPoints()
+ *
+ * ===========================================
+ * -- PFont functions:
+ * PFont.list()
+ *
+ * -- kerning
+ * -- alignment: justified?
+ * -- integrate p5.dom? (later)
+ */
+
+/**
+ * Base class for font handling
+ * @class p5.Font
+ * @constructor
+ * @param {Object} [pInst] pointer to p5 instance
+ */
+p5.Font = function(p) {
+
+ this.parent = p;
+
+ this.cache = {};
+
+ /**
+ * Underlying opentype font implementation
+ * @property font
+ */
+ this.font = undefined;
+};
+
+p5.Font.prototype.list = function() {
+
+ // TODO
+ throw 'not yet implemented';
+};
+
+/**
+ * Returns a tight bounding box for the given text string using this
+ * font (currently only supports single lines)
+ *
+ * @method textBounds
+ * @param {String} line a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Number} fontSize font size to use (optional)
+ * @param {Object} options opentype options (optional)
+ *
+ * @return {Object} a rectangle object with properties: x, y, w, h
+ *
+ * @example
+ *
+ *
+ * var font;
+ * var textString = 'Lorem ipsum dolor sit amet.';
+ * function preload() {
+ * font = loadFont('./assets/Regular.otf');
+ * };
+ * function setup() {
+ * background(210);
+ *
+ * var bbox = font.textBounds(textString, 10, 30, 12);
+ * fill(255);
+ * stroke(0);
+ * rect(bbox.x, bbox.y, bbox.w, bbox.h);
+ * fill(0);
+ * noStroke();
+ *
+ * textFont(font);
+ * textSize(12);
+ * text(textString, 10, 30);
+ * };
+ *
+ *
+ *
+ * @alt
+ *words Lorem ipsum dol go off canvas and contained by white bounding box
+ *
+ */
+p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
+
+ x = x !== undefined ? x : 0;
+ y = y !== undefined ? y : 0;
+ fontSize = fontSize || this.parent._renderer._textSize;
+
+ // Check cache for existing bounds. Take into consideration the text alignment
+ // settings. Default alignment should match opentype's origin: left-aligned &
+ // alphabetic baseline.
+ var p = (options && options.renderer && options.renderer._pInst) ||
+ this.parent,
+ ctx = p._renderer.drawingContext,
+ alignment = ctx.textAlign || constants.LEFT,
+ baseline = ctx.textBaseline || constants.BASELINE;
+ var result = this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
+ baseline)];
+
+ if (!result) {
+
+ var xCoords = [], yCoords = [], self = this,
+ scale = this._scale(fontSize), minX, minY, maxX, maxY;
+
+ this.font.forEachGlyph(str, x, y, fontSize, options,
+ function(glyph, gX, gY, gFontSize) {
+
+ xCoords.push(gX);
+ yCoords.push(gY);
+
+ var gm = glyph.getMetrics();
+
+ if (glyph.name !== 'space' && glyph.unicode !== 32) {
+
+ xCoords.push(gX + (gm.xMax * scale));
+ yCoords.push(gY + (-gm.yMin * scale));
+ yCoords.push(gY + (-gm.yMax * scale));
+
+ } else { // NOTE: deals with broken metrics for spaces in opentype.js
+
+ xCoords.push(gX + self.font.charToGlyph(' ').advanceWidth *
+ self._scale(fontSize));
+ }
+ });
+
+ // fix to #1409 (not sure why these max() functions were here)
+ /*minX = Math.max(0, Math.min.apply(null, xCoords));
+ minY = Math.max(0, Math.min.apply(null, yCoords));
+ maxX = Math.max(0, Math.max.apply(null, xCoords));
+ maxY = Math.max(0, Math.max.apply(null, yCoords));*/
+ minX = Math.min.apply(null, xCoords);
+ minY = Math.min.apply(null, yCoords);
+ maxX = Math.max.apply(null, xCoords);
+ maxY = Math.max.apply(null, yCoords);
+
+ result = {
+ x: minX,
+ y: minY,
+ h: maxY - minY,
+ w: maxX - minX,
+ advance: minX - x
+ };
+
+ // Bounds are now calculated, so shift the x & y to match alignment settings
+ var textWidth = result.w + result.advance;
+ var pos = this._handleAlignment(p, ctx, str, result.x, result.y, textWidth);
+ result.x = pos.x;
+ result.y = pos.y;
+
+ this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
+ baseline)] = result;
+ }
+ //else console.log('cache-hit');
+
+ return result;
+};
+
+
+/**
+ * Computes an array of points following the path for specified text
+ *
+ * @param {String} txt a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Number} fontSize font size to use (optional)
+ * @param {Object} options an (optional) object that can contain:
+ *
+ *
sampleFactor - the ratio of path-length to number of samples
+ * (default=.25); higher values yield more points and are therefore
+ * more precise
+ *
+ *
simplifyThreshold - if set to a non-zero value, collinear points will be
+ * be removed from the polygon; the value represents the threshold angle to use
+ * when determining whether two edges are collinear
+ *
+ * @return {Array} an array of points, each with x, y, alpha (the path angle)
+ */
+p5.Font.prototype.textToPoints = function(txt, x, y, fontSize, options) {
+
+ var xoff = 0, result = [], glyphs = this._getGlyphs(txt);
+
+ fontSize = fontSize || this.parent._renderer._textSize;
+
+ for (var i = 0; i < glyphs.length; i++) {
+
+ var gpath = glyphs[i].getPath(x, y, fontSize),
+ paths = splitPaths(gpath.commands);
+
+ for (var j = 0; j < paths.length; j++) {
+
+ var pts = pathToPoints(paths[j], options);
+
+ for (var k = 0; k < pts.length; k++) {
+ pts[k].x += xoff;
+ result.push(pts[k]);
+ }
+ }
+
+ xoff += glyphs[i].advanceWidth * this._scale(fontSize);
+ }
+
+ return result;
+};
+
+// ----------------------------- End API ------------------------------
+
+/**
+ * Returns the set of opentype glyphs for the supplied string.
+ *
+ * Note that there is not a strict one-to-one mapping between characters
+ * and glyphs, so the list of returned glyphs can be larger or smaller
+ * than the length of the given string.
+ *
+ * @param {String} str the string to be converted
+ * @return {array} the opentype glyphs
+ */
+p5.Font.prototype._getGlyphs = function(str) {
+
+ return this.font.stringToGlyphs(str);
+};
+
+/**
+ * Returns an opentype path for the supplied string and position.
+ *
+ * @param {String} line a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Object} options opentype options (optional)
+ * @return {Object} the opentype path
+ */
+p5.Font.prototype._getPath = function(line, x, y, options) {
+
+ var p = (options && options.renderer && options.renderer._pInst) ||
+ this.parent,
+ ctx = p._renderer.drawingContext,
+ pos = this._handleAlignment(p, ctx, line, x, y);
+
+ return this.font.getPath(line, pos.x, pos.y, p._renderer._textSize, options);
+};
+
+/*
+ * Creates an SVG-formatted path-data string
+ * (See http://www.w3.org/TR/SVG/paths.html#PathData)
+ * from the given opentype path or string/position
+ *
+ * @param {Object} path an opentype path, OR the following:
+ *
+ * @param {String} line a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Object} options opentype options (optional), set options.decimals
+ * to set the decimal precision of the path-data
+ *
+ * @return {Object} this p5.Font object
+ */
+p5.Font.prototype._getPathData = function(line, x, y, options) {
+
+ var decimals = 3;
+
+ // create path from string/position
+ if (typeof line === 'string' && arguments.length > 2) {
+
+ line = this._getPath(line, x, y, options);
+ }
+ // handle options specified in 2nd arg
+ else if (typeof x === 'object') {
+
+ options = x;
+ }
+
+ // handle svg arguments
+ if (options && typeof options.decimals === 'number') {
+
+ decimals = options.decimals;
+ }
+
+ return line.toPathData(decimals);
+};
+
+/*
+ * Creates an SVG
element, as a string,
+ * from the given opentype path or string/position
+ *
+ * @param {Object} path an opentype path, OR the following:
+ *
+ * @param {String} line a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Object} options opentype options (optional), set options.decimals
+ * to set the decimal precision of the path-data in the element,
+ * options.fill to set the fill color for the element,
+ * options.stroke to set the stroke color for the element,
+ * options.strokeWidth to set the strokeWidth for the element.
+ *
+ * @return {Object} this p5.Font object
+ */
+p5.Font.prototype._getSVG = function(line, x, y, options) {
+
+ var decimals = 3;
+
+ // create path from string/position
+ if (typeof line === 'string' && arguments.length > 2) {
+
+ line = this._getPath(line, x, y, options);
+ }
+ // handle options specified in 2nd arg
+ else if (typeof x === 'object') {
+
+ options = x;
+ }
+
+ // handle svg arguments
+ if (options) {
+ if (typeof options.decimals === 'number') {
+ decimals = options.decimals;
+ }
+ if (typeof options.strokeWidth === 'number') {
+ line.strokeWidth = options.strokeWidth;
+ }
+ if (typeof options.fill !== 'undefined') {
+ line.fill = options.fill;
+ }
+ if (typeof options.stroke !== 'undefined') {
+ line.stroke = options.stroke;
+ }
+ }
+
+ return line.toSVG(decimals);
+};
+
+/*
+ * Renders an opentype path or string/position
+ * to the current graphics context
+ *
+ * @param {Object} path an opentype path, OR the following:
+ *
+ * @param {String} line a line of text
+ * @param {Number} x x-position
+ * @param {Number} y y-position
+ * @param {Object} options opentype options (optional)
+ *
+ * @return {Object} this p5.Font object
+ */
+p5.Font.prototype._renderPath = function(line, x, y, options) {
+
+ var pdata, pg = (options && options.renderer) || this.parent._renderer,
+ ctx = pg.drawingContext;
+
+ if (typeof line === 'object' && line.commands) {
+
+ pdata = line.commands;
+ } else {
+
+ //pos = handleAlignment(p, ctx, line, x, y);
+ pdata = this._getPath(line, x, y, options).commands;
+ }
+
+ ctx.beginPath();
+ for (var i = 0; i < pdata.length; i += 1) {
+
+ var cmd = pdata[i];
+ if (cmd.type === 'M') {
+ ctx.moveTo(cmd.x, cmd.y);
+ } else if (cmd.type === 'L') {
+ ctx.lineTo(cmd.x, cmd.y);
+ } else if (cmd.type === 'C') {
+ ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
+ } else if (cmd.type === 'Q') {
+ ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
+ } else if (cmd.type === 'Z') {
+ ctx.closePath();
+ }
+ }
+
+ // only draw stroke if manually set by user
+ if (pg._doStroke && pg._strokeSet) {
+
+ ctx.stroke();
+ }
+
+ if (pg._doFill) {
+
+ // if fill hasn't been set by user, use default-text-fill
+ ctx.fillStyle = pg._fillSet ? ctx.fillStyle : constants._DEFAULT_TEXT_FILL;
+ ctx.fill();
+ }
+
+ return this;
+};
+
+p5.Font.prototype._textWidth = function(str, fontSize) {
+
+ if (str === ' ') { // special case for now
+
+ return this.font.charToGlyph(' ').advanceWidth * this._scale(fontSize);
+ }
+
+ var bounds = this.textBounds(str, 0, 0, fontSize);
+ return bounds.w + bounds.advance;
+};
+
+p5.Font.prototype._textAscent = function(fontSize) {
+
+ return this.font.ascender * this._scale(fontSize);
+};
+
+p5.Font.prototype._textDescent = function(fontSize) {
+
+ return -this.font.descender * this._scale(fontSize);
+};
+
+p5.Font.prototype._scale = function(fontSize) {
+
+ return (1 / this.font.unitsPerEm) * (fontSize ||
+ this.parent._renderer._textSize);
+};
+
+p5.Font.prototype._handleAlignment = function(p, ctx, line, x, y, textWidth) {
+ var fontSize = p._renderer._textSize,
+ textAscent = this._textAscent(fontSize),
+ textDescent = this._textDescent(fontSize);
+
+ textWidth = textWidth !== undefined ? textWidth :
+ this._textWidth(line, fontSize);
+
+ if (ctx.textAlign === constants.CENTER) {
+ x -= textWidth / 2;
+ } else if (ctx.textAlign === constants.RIGHT) {
+ x -= textWidth;
+ }
+
+ if (ctx.textBaseline === constants.TOP) {
+ y += textAscent;
+ } else if (ctx.textBaseline === constants._CTX_MIDDLE) {
+ y += textAscent / 2;
+ } else if (ctx.textBaseline === constants.BOTTOM) {
+ y -= textDescent;
+ }
+
+ return { x: x, y: y };
+};
+
+// path-utils
+
+function pathToPoints(cmds, options) {
+
+ var opts = parseOpts(options, {
+ sampleFactor: 0.1,
+ simplifyThreshold: 0,
+ });
+
+ var len = pointAtLength(cmds,0,1), // total-length
+ t = len / (len * opts.sampleFactor),
+ pts = [];
+
+ for (var i = 0; i < len; i += t) {
+ pts.push(pointAtLength(cmds, i));
+ }
+
+ if (opts.simplifyThreshold) {
+ /*var count = */simplify(pts, opts.simplifyThreshold);
+ //console.log('Simplify: removed ' + count + ' pts');
+ }
+
+ return pts;
+}
+
+function simplify(pts, angle) {
+
+ angle = (typeof angle === 'undefined') ? 0 : angle;
+
+ var num = 0;
+ for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) {
+
+ if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) {
+
+ // Remove the middle point
+ pts.splice(i % pts.length, 1);
+ num++;
+ }
+ }
+ return num;
+}
+
+function splitPaths(cmds) {
+
+ var paths = [], current;
+ for (var i = 0; i < cmds.length; i++) {
+ if (cmds[i].type === 'M') {
+ if (current) {
+ paths.push(current);
+ }
+ current = [];
+ }
+ current.push(cmdToArr(cmds[i]));
+ }
+ paths.push(current);
+
+ return paths;
+}
+
+function cmdToArr(cmd) {
+
+ var arr = [ cmd.type ];
+ if (cmd.type === 'M' || cmd.type === 'L') { // moveto or lineto
+ arr.push(cmd.x, cmd.y);
+ } else if (cmd.type === 'C') {
+ arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
+ } else if (cmd.type === 'Q') {
+ arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y);
+ }
+ // else if (cmd.type === 'Z') { /* no-op */ }
+ return arr;
+}
+
+function parseOpts(options, defaults) {
+
+ if (typeof options !== 'object') {
+ options = defaults;
+ }
+ else {
+ for (var key in defaults) {
+ if (typeof options[key] === 'undefined') {
+ options[key] = defaults[key];
+ }
+ }
+ }
+ return options;
+}
+
+//////////////////////// Helpers ////////////////////////////
+
+function at(v, i) {
+ var s = v.length;
+ return v[i < 0 ? i % s + s : i % s];
+}
+
+function collinear(a, b, c, thresholdAngle) {
+
+ if (!thresholdAngle) {
+ return areaTriangle(a, b, c) === 0;
+ }
+
+ if (typeof collinear.tmpPoint1 === 'undefined') {
+ collinear.tmpPoint1 = [];
+ collinear.tmpPoint2 = [];
+ }
+
+ var ab = collinear.tmpPoint1, bc = collinear.tmpPoint2;
+ ab.x = b.x - a.x;
+ ab.y = b.y - a.y;
+ bc.x = c.x - b.x;
+ bc.y = c.y - b.y;
+
+ var dot = ab.x * bc.x + ab.y * bc.y,
+ magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y),
+ magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y),
+ angle = Math.acos(dot / (magA * magB));
+
+ return angle < thresholdAngle;
+}
+
+function areaTriangle(a, b, c) {
+ return (((b[0] - a[0]) * (c[1] - a[1])) - ((c[0] - a[0]) * (b[1] - a[1])));
+}
+
+// Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license)
+
+function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+
+ var t1 = 1 - t, t13 = Math.pow(t1, 3), t12 = Math.pow(t1, 2), t2 = t * t,
+ t3 = t2 * t, x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x +
+ t3 * p2x, y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y +
+ t3 * p2y, mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
+ my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
+ nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
+ ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
+ ax = t1 * p1x + t * c1x, ay = t1 * p1y + t * c1y,
+ cx = t1 * c2x + t * p2x, cy = t1 * c2y + t * p2y,
+ alpha = (90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI);
+
+ if (mx > nx || my < ny) { alpha += 180; }
+
+ return { x: x, y: y, m: { x: mx, y: my }, n: { x: nx, y: ny },
+ start: { x: ax, y: ay }, end: { x: cx, y: cy }, alpha: alpha
+ };
+}
+
+function getPointAtSegmentLength(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,length) {
+ return (length == null) ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) :
+ findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y,
+ getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
+}
+
+function pointAtLength(path, length, istotal) {
+ path = path2curve(path);
+ var x, y, p, l, sp = '', subpaths = {}, point, len = 0;
+ for (var i = 0, ii = path.length; i < ii; i++) {
+ p = path[i];
+ if (p[0] === 'M') {
+ x = +p[1];
+ y = +p[2];
+ } else {
+ l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+ if (len + l > length) {
+ if (!istotal) {
+ point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5],
+ p[6], length - len);
+ return { x: point.x, y: point.y, alpha: point.alpha };
+ }
+ }
+ len += l;
+ x = +p[5];
+ y = +p[6];
+ }
+ sp += p.shift() + p;
+ }
+ subpaths.end = sp;
+
+ point = istotal ? len : findDotsAtSegment
+ (x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
+
+ if (point.alpha) {
+ point = { x: point.x, y: point.y, alpha: point.alpha };
+ }
+
+ return point;
+}
+
+function pathToAbsolute(pathArray) {
+
+ var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0;
+ if (pathArray[0][0] === 'M') {
+ x = +pathArray[0][1];
+ y = +pathArray[0][2];
+ mx = x;
+ my = y;
+ start++;
+ res[0] = ['M', x, y];
+ }
+
+ var dots,crz = pathArray.length===3 && pathArray[0][0]==='M' &&
+ pathArray[1][0].toUpperCase()==='R' && pathArray[2][0].toUpperCase()==='Z';
+
+ for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
+ res.push(r = []);
+ pa = pathArray[i];
+ if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) {
+ r[0] = String.prototype.toUpperCase.call(pa[0]);
+ switch (r[0]) {
+ case 'A':
+ r[1] = pa[1];
+ r[2] = pa[2];
+ r[3] = pa[3];
+ r[4] = pa[4];
+ r[5] = pa[5];
+ r[6] = +(pa[6] + x);
+ r[7] = +(pa[7] + y);
+ break;
+ case 'V':
+ r[1] = +pa[1] + y;
+ break;
+ case 'H':
+ r[1] = +pa[1] + x;
+ break;
+ case 'R':
+ dots = [x, y].concat(pa.slice(1));
+ for (var j = 2, jj = dots.length; j < jj; j++) {
+ dots[j] = +dots[j] + x;
+ dots[++j] = +dots[j] + y;
+ }
+ res.pop();
+ res = res.concat(catmullRom2bezier(dots, crz));
+ break;
+ case 'M':
+ mx = +pa[1] + x;
+ my = +pa[2] + y;
+ break;
+ default:
+ for (j = 1, jj = pa.length; j < jj; j++) {
+ r[j] = +pa[j] + ((j % 2) ? x : y);
+ }
+ }
+ } else if (pa[0] === 'R') {
+ dots = [x, y].concat(pa.slice(1));
+ res.pop();
+ res = res.concat(catmullRom2bezier(dots, crz));
+ r = ['R'].concat(pa.slice(-2));
+ } else {
+ for (var k = 0, kk = pa.length; k < kk; k++) {
+ r[k] = pa[k];
+ }
+ }
+ switch (r[0]) {
+ case 'Z':
+ x = mx;
+ y = my;
+ break;
+ case 'H':
+ x = r[1];
+ break;
+ case 'V':
+ y = r[1];
+ break;
+ case 'M':
+ mx = r[r.length - 2];
+ my = r[r.length - 1];
+ break;
+ default:
+ x = r[r.length - 2];
+ y = r[r.length - 1];
+ }
+ }
+ return res;
+}
+
+function path2curve(path, path2) {
+
+ var p = pathToAbsolute(path), p2 = path2 && pathToAbsolute(path2),
+ attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
+ attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
+
+ processPath = function(path, d, pcom) {
+ var nx, ny, tq = { T: 1, Q: 1 };
+ if (!path) { return ['C', d.x, d.y, d.x, d.y, d.x, d.y]; }
+ if (!(path[0] in tq)) { d.qx = d.qy = null; }
+ switch (path[0]) {
+ case 'M':
+ d.X = path[1];
+ d.Y = path[2];
+ break;
+ case 'A':
+ path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
+ break;
+ case 'S':
+ if (pcom === 'C' || pcom === 'S') {
+ nx = d.x * 2 - d.bx;
+ ny = d.y * 2 - d.by;
+ } else {
+ nx = d.x;
+ ny = d.y;
+ }
+ path = ['C', nx, ny].concat(path.slice(1));
+ break;
+ case 'T':
+ if (pcom === 'Q' || pcom === 'T') {
+ d.qx = d.x * 2 - d.qx;
+ d.qy = d.y * 2 - d.qy;
+ } else {
+ d.qx = d.x;
+ d.qy = d.y;
+ }
+ path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
+ break;
+ case 'Q':
+ d.qx = path[1];
+ d.qy = path[2];
+ path = ['C'].concat(q2c(d.x,d.y,path[1],path[2],path[3],path[4]));
+ break;
+ case 'L':
+ path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
+ break;
+ case 'H':
+ path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
+ break;
+ case 'V':
+ path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
+ break;
+ case 'Z':
+ path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
+ break;
+ }
+ return path;
+ },
+
+ fixArc = function(pp, i) {
+ if (pp[i].length > 7) {
+ pp[i].shift();
+ var pi = pp[i];
+ while (pi.length) {
+ pcoms1[i] = 'A';
+ if (p2) { pcoms2[i] = 'A'; }
+ pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
+ }
+ pp.splice(i, 1);
+ ii = Math.max(p.length, p2 && p2.length || 0);
+ }
+ },
+
+ fixM = function(path1, path2, a1, a2, i) {
+ if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
+ path2.splice(i, 0, ['M', a2.x, a2.y]);
+ a1.bx = 0;
+ a1.by = 0;
+ a1.x = path1[i][1];
+ a1.y = path1[i][2];
+ ii = Math.max(p.length, p2 && p2.length || 0);
+ }
+ },
+
+ pcoms1 = [], // path commands of original path p
+ pcoms2 = [], // path commands of original path p2
+ pfirst = '', // temporary holder for original path command
+ pcom = ''; // holder for previous path command of original path
+
+ for (var i = 0, ii = Math.max(p.length, p2 && p2.length || 0); i < ii; i++) {
+ if (p[i]) { pfirst = p[i][0]; } // save current path command
+
+ if (pfirst !== 'C') {
+ pcoms1[i] = pfirst; // Save current path command
+ if (i) { pcom = pcoms1[i - 1]; } // Get previous path command pcom
+ }
+ p[i] = processPath(p[i], attrs, pcom);
+
+ if (pcoms1[i] !== 'A' && pfirst === 'C') { pcoms1[i] = 'C'; }
+
+ fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
+
+ if (p2) { // the same procedures is done to p2
+ if (p2[i]) { pfirst = p2[i][0]; }
+ if (pfirst !== 'C') {
+ pcoms2[i] = pfirst;
+ if (i) { pcom = pcoms2[i - 1]; }
+ }
+ p2[i] = processPath(p2[i], attrs2, pcom);
+
+ if (pcoms2[i] !== 'A' && pfirst === 'C') { pcoms2[i] = 'C'; }
+
+ fixArc(p2, i);
+ }
+ fixM(p, p2, attrs, attrs2, i);
+ fixM(p2, p, attrs2, attrs, i);
+ var seg = p[i], seg2 = p2 && p2[i], seglen = seg.length,
+ seg2len = p2 && seg2.length;
+ attrs.x = seg[seglen - 2];
+ attrs.y = seg[seglen - 1];
+ attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
+ attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
+ attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
+ attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
+ attrs2.x = p2 && seg2[seg2len - 2];
+ attrs2.y = p2 && seg2[seg2len - 1];
+ }
+
+ return p2 ? [p, p2] : p;
+}
+
+function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) {
+ // for more information of where this Math came from visit:
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ var PI = Math.PI, _120 = PI * 120 / 180, f1, f2, cx, cy,
+ rad = PI / 180 * (+angle || 0), res = [], xy,
+ rotate = function (x, y, rad) {
+ var X = x * Math.cos(rad) - y * Math.sin(rad),
+ Y = x * Math.sin(rad) + y * Math.cos(rad);
+ return { x: X, y: Y };
+ };
+ if (!recursive) {
+ xy = rotate(x1, y1, -rad);
+ x1 = xy.x;
+ y1 = xy.y;
+ xy = rotate(x2, y2, -rad);
+ x2 = xy.x;
+ y2 = xy.y;
+ var x = (x1 - x2) / 2, y = (y1 - y2) / 2,
+ h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
+ if (h > 1) {
+ h = Math.sqrt(h);
+ rx = h * rx;
+ ry = h * ry;
+ }
+ var rx2 = rx * rx, ry2 = ry * ry,
+ k = (lac === sweep_flag ? -1 : 1) * Math.sqrt(Math.abs
+ ((rx2 * ry2 - rx2 * y * y - ry2 * x * x)/(rx2 * y * y + ry2 * x * x)));
+
+ cx = k * rx * y / ry + (x1 + x2) / 2;
+ cy = k * -ry * x / rx + (y1 + y2) / 2;
+ f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
+ f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
+
+ f1 = x1 < cx ? PI - f1 : f1;
+ f2 = x2 < cx ? PI - f2 : f2;
+
+ if (f1 < 0) { f1 = PI * 2 + f1; }
+ if (f2 < 0) { f2 = PI * 2 + f2; }
+
+ if (sweep_flag && f1 > f2) {
+ f1 = f1 - PI * 2;
+ }
+ if (!sweep_flag && f2 > f1) {
+ f2 = f2 - PI * 2;
+ }
+ } else {
+ f1 = recursive[0];
+ f2 = recursive[1];
+ cx = recursive[2];
+ cy = recursive[3];
+ }
+ var df = f2 - f1;
+ if (Math.abs(df) > _120) {
+ var f2old = f2, x2old = x2, y2old = y2;
+ f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
+ x2 = cx + rx * Math.cos(f2);
+ y2 = cy + ry * Math.sin(f2);
+ res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old,
+ [f2, f2old, cx, cy]);
+ }
+ df = f2 - f1;
+ var c1 = Math.cos(f1),
+ s1 = Math.sin(f1),
+ c2 = Math.cos(f2),
+ s2 = Math.sin(f2),
+ t = Math.tan(df / 4),
+ hx = 4 / 3 * rx * t,
+ hy = 4 / 3 * ry * t,
+ m1 = [x1, y1],
+ m2 = [x1 + hx * s1, y1 - hy * c1],
+ m3 = [x2 + hx * s2, y2 - hy * c2],
+ m4 = [x2, y2];
+ m2[0] = 2 * m1[0] - m2[0];
+ m2[1] = 2 * m1[1] - m2[1];
+ if (recursive) {
+ return [m2, m3, m4].concat(res);
+ } else {
+ res = [m2, m3, m4].concat(res).join().split(',');
+ var newres = [];
+ for (var i = 0, ii = res.length; i < ii; i++) {
+ newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i],
+ res[i + 1], rad).x;
+ }
+ return newres;
+ }
+}
+
+// http://schepers.cc/getting-to-the-point
+function catmullRom2bezier(crp, z) {
+ var d = [];
+ for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
+ var p = [{
+ x: +crp[i - 2],
+ y: +crp[i - 1]
+ }, {
+ x: +crp[i],
+ y: +crp[i + 1]
+ }, {
+ x: +crp[i + 2],
+ y: +crp[i + 3]
+ }, {
+ x: +crp[i + 4],
+ y: +crp[i + 5]
+ }];
+ if (z) {
+ if (!i) {
+ p[0] = {
+ x: +crp[iLen - 2],
+ y: +crp[iLen - 1]
+ };
+ } else if (iLen - 4 === i) {
+ p[3] = {
+ x: +crp[0],
+ y: +crp[1]
+ };
+ } else if (iLen - 2 === i) {
+ p[2] = {
+ x: +crp[0],
+ y: +crp[1]
+ };
+ p[3] = {
+ x: +crp[2],
+ y: +crp[3]
+ };
+ }
+ } else {
+ if (iLen - 4 === i) {
+ p[3] = p[2];
+ } else if (!i) {
+ p[0] = {
+ x: +crp[i],
+ y: +crp[i + 1]
+ };
+ }
+ }
+ d.push(['C', (-p[0].x + 6 * p[1].x + p[2].x) / 6, (-p[0].y + 6 * p[1].y +
+ p[2].y) / 6, (p[1].x + 6 * p[2].x - p[3].x) / 6, (p[1].y + 6 * p[2].y -
+ p[3].y) / 6, p[2].x, p[2].y ]);
+ }
+
+ return d;
+}
+
+function l2c(x1, y1, x2, y2) { return [x1, y1, x2, y2, x2, y2]; }
+
+function q2c(x1, y1, ax, ay, x2, y2) {
+ var _13 = 1 / 3, _23 = 2 / 3;
+ return [
+ _13 * x1 + _23 * ax, _13 * y1 + _23 * ay,
+ _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2
+ ];
+}
+
+function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
+ if (z == null) { z = 1; }
+ z = z > 1 ? 1 : z < 0 ? 0 : z;
+ var z2 = z / 2,
+ n = 12, Tvalues = [-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873,
+ -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816],
+ sum = 0, Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032,
+ 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472 ];
+ for (var i = 0; i < n; i++) {
+ var ct = z2 * Tvalues[i] + z2,
+ xbase = base3(ct, x1, x2, x3, x4),
+ ybase = base3(ct, y1, y2, y3, y4),
+ comb = xbase * xbase + ybase * ybase;
+ sum += Cvalues[i] * Math.sqrt(comb);
+ }
+ return z2 * sum;
+}
+
+function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
+ if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
+ return;
+ }
+ var t = 1, step = t / 2, t2 = t - step, l, e = 0.01;
+ l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
+ while (Math.abs(l - ll) > e) {
+ step /= 2;
+ t2 += (l < ll ? 1 : -1) * step;
+ l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
+ }
+ return t2;
+}
+
+function base3(t, p1, p2, p3, p4) {
+ var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
+ t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
+ return t * t2 - 3 * p1 + 3 * p2;
+}
+
+function cacheKey() {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ i = args.length;
+ var hash = '';
+ while (i--) {
+ hash += (args[i] === Object(args[i])) ?
+ JSON.stringify(args[i]) : args[i];
+ }
+ return hash;
+}
+
+module.exports = p5.Font;
+
+},{"../core/constants":36,"../core/core":37}],73:[function(_dereq_,module,exports){
+/**
+ * @module Data
+ * @submodule Array Functions
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Adds a value to the end of an array. Extends the length of
+ * the array by one. Maps to Array.push().
+ *
+ * @method append
+ * @param {Array} array Array to append
+ * @param {any} value to be added to the Array
+ * @example
+ *
+ * function setup() {
+ *
+ * var myArray = new Array("Mango", "Apple", "Papaya")
+ * print(myArray) // ["Mango", "Apple", "Papaya"]
+ *
+ * append(myArray, "Peach")
+ * print(myArray) // ["Mango", "Apple", "Papaya", "Peach"]
+ *
+ * }
+ *
+ */
+p5.prototype.append = function(array, value) {
+ array.push(value);
+ return array;
+};
+
+/**
+ * Copies an array (or part of an array) to another array. The src array is
+ * copied to the dst array, beginning at the position specified by
+ * srcPosition and into the position specified by dstPosition. The number of
+ * elements to copy is determined by length. Note that copying values
+ * overwrites existing values in the destination array. To append values
+ * instead of overwriting them, use concat().
+ *
+ * The simplified version with only two arguments, arrayCopy(src, dst),
+ * copies an entire array to another of the same size. It is equivalent to
+ * arrayCopy(src, 0, dst, 0, src.length).
+ *
+ * Using this function is far more efficient for copying array data than
+ * iterating through a for() loop and copying each element individually.
+ *
+ * @method arrayCopy
+ * @param {Array} src the source Array
+ * @param {Number} [srcPosition] starting position in the source Array
+ * @param {Array} dst the destination Array
+ * @param {Number} [dstPosition] starting position in the destination Array
+ * @param {Number} [length] number of Array elements to be copied
+ *
+ * @example
+ *
+ * function setup() {
+ *
+ * var src = new Array("A", "B", "C");
+ * var dst = new Array( 1 , 2 , 3 );
+ * var srcPosition = 1;
+ * var dstPosition = 0;
+ * var length = 2;
+ *
+ * print(src); // ["A", "B", "C"]
+ * print(dst); // [ 1 , 2 , 3 ]
+ *
+ * arrayCopy(src, srcPosition, dst, dstPosition, length);
+ * print(dst); // ["B", "C", 3]
+ *
+ * }
+ *
+ */
+p5.prototype.arrayCopy = function(
+ src,
+ srcPosition,
+ dst,
+ dstPosition,
+ length) {
+
+ // the index to begin splicing from dst array
+ var start,
+ end;
+
+ if (typeof length !== 'undefined') {
+
+ end = Math.min(length, src.length);
+ start = dstPosition;
+ src = src.slice(srcPosition, end + srcPosition);
+
+ } else {
+
+ if (typeof dst !== 'undefined') { // src, dst, length
+ // rename so we don't get confused
+ end = dst;
+ end = Math.min(end, src.length);
+ } else { // src, dst
+ end = src.length;
+ }
+
+ start = 0;
+ // rename so we don't get confused
+ dst = srcPosition;
+ src = src.slice(0, end);
+ }
+
+ // Since we are not returning the array and JavaScript is pass by reference
+ // we must modify the actual values of the array
+ // instead of reassigning arrays
+ Array.prototype.splice.apply(dst, [start, end].concat(src));
+
+};
+
+/**
+ * Concatenates two arrays, maps to Array.concat(). Does not modify the
+ * input arrays.
+ *
+ * @method concat
+ * @param {Array} a first Array to concatenate
+ * @param {Array} b second Array to concatenate
+ * @return {Array} concatenated array
+ *
+ * @example
+ *
+ * function setup() {
+ * var arr1 = new Array("A", "B", "C");
+ * var arr2 = new Array( 1 , 2 , 3 );
+ *
+ * print(arr1); // ["A","B","C"]
+ * print(arr2); // [1,2,3]
+ *
+ * var arr3 = concat(arr1, arr2);
+ *
+ * print(arr1); // ["A","B","C"]
+ * print(arr2); // [1,2,3]
+ * print(arr3); // ["A","B","C",1,2,3]
+ *
+ * }
+ *
+ */
+p5.prototype.concat = function(list0, list1) {
+ return list0.concat(list1);
+};
+
+/**
+ * Reverses the order of an array, maps to Array.reverse()
+ *
+ * @method reverse
+ * @param {Array} list Array to reverse
+ * @example
+ *
+ * function setup() {
+ * var myArray = new Array("A", "B", "C");
+ * print(myArray); // ["A","B","C"]
+ *
+ * reverse(myArray);
+ * print(myArray); // ["C","B","A"]
+ * }
+ *
+ */
+p5.prototype.reverse = function(list) {
+ return list.reverse();
+};
+
+/**
+ * Decreases an array by one element and returns the shortened array,
+ * maps to Array.pop().
+ *
+ * @method shorten
+ * @param {Array} list Array to shorten
+ * @return {Array} shortened Array
+ * @example
+ *
+ * function setup() {
+ * var myArray = new Array("A", "B", "C");
+ * print(myArray); // ["A","B","C"]
+ *
+ * var newArray = shorten(myArray);
+ * print(myArray); // ["A","B","C"]
+ * print(newArray); // ["A","B"]
+ * }
+ *
+ */
+p5.prototype.shorten = function(list) {
+ list.pop();
+ return list;
+};
+
+/**
+ * Randomizes the order of the elements of an array. Implements
+ *
+ * Fisher-Yates Shuffle Algorithm.
+ *
+ * @method shuffle
+ * @param {Array} array Array to shuffle
+ * @param {Boolean} [bool] modify passed array
+ * @return {Array} shuffled Array
+ * @example
+ *
+ * function setup() {
+ * var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
+ * print(regularArr);
+ * shuffle(regularArr, true); // force modifications to passed array
+ * print(regularArr);
+ *
+ * // By default shuffle() returns a shuffled cloned array:
+ * var newArr = shuffle(regularArr);
+ * print(regularArr);
+ * print(newArr);
+ * }
+ *
+ */
+p5.prototype.shuffle = function(arr, bool) {
+ var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr);
+ arr = bool || isView ? arr : arr.slice();
+
+ var rnd, tmp, idx = arr.length;
+ while (idx > 1) {
+ rnd = Math.random()*idx | 0;
+
+ tmp = arr[--idx];
+ arr[idx] = arr[rnd];
+ arr[rnd] = tmp;
+ }
+
+ return arr;
+};
+
+/**
+ * Sorts an array of numbers from smallest to largest, or puts an array of
+ * words in alphabetical order. The original array is not modified; a
+ * re-ordered array is returned. The count parameter states the number of
+ * elements to sort. For example, if there are 12 elements in an array and
+ * count is set to 5, only the first 5 elements in the array will be sorted.
+ *
+ * @method sort
+ * @param {Array} list Array to sort
+ * @param {Number} [count] number of elements to sort, starting from 0
+ *
+ * @example
+ *
+ * function setup() {
+ * var words = new Array("banana", "apple", "pear","lime");
+ * print(words); // ["banana", "apple", "pear", "lime"]
+ * var count = 4; // length of array
+ *
+ * words = sort(words, count);
+ * print(words); // ["apple", "banana", "lime", "pear"]
+ * }
+ *
+ *
+ * function setup() {
+ * var numbers = new Array(2,6,1,5,14,9,8,12);
+ * print(numbers); // [2,6,1,5,14,9,8,12]
+ * var count = 5; // Less than the length of the array
+ *
+ * numbers = sort(numbers, count);
+ * print(numbers); // [1,2,5,6,14,9,8,12]
+ * }
+ *
+ */
+p5.prototype.sort = function(list, count) {
+ var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
+ var rest = count ? list.slice(Math.min(count, list.length)) : [];
+ if (typeof arr[0] === 'string') {
+ arr = arr.sort();
+ } else {
+ arr = arr.sort(function(a,b){return a-b;});
+ }
+ return arr.concat(rest);
+};
+
+/**
+ * Inserts a value or an array of values into an existing array. The first
+ * parameter specifies the initial array to be modified, and the second
+ * parameter defines the data to be inserted. The third parameter is an index
+ * value which specifies the array position from which to insert data.
+ * (Remember that array index numbering starts at zero, so the first position
+ * is 0, the second position is 1, and so on.)
+ *
+ * @method splice
+ * @param {Array} list Array to splice into
+ * @param {any} value value to be spliced in
+ * @param {Number} position in the array from which to insert data
+ *
+ * @example
+ *
+ * function setup() {
+ * var myArray = new Array(0,1,2,3,4);
+ * var insArray = new Array("A","B","C");
+ * print(myArray); // [0,1,2,3,4]
+ * print(insArray); // ["A","B","C"]
+ *
+ * splice(myArray, insArray, 3);
+ * print(myArray); // [0,1,2,"A","B","C",3,4]
+ * }
+ *
+ */
+p5.prototype.splice = function(list, value, index) {
+
+ // note that splice returns spliced elements and not an array
+ Array.prototype.splice.apply(list, [index, 0].concat(value));
+
+ return list;
+};
+
+/**
+ * Extracts an array of elements from an existing array. The list parameter
+ * defines the array from which the elements will be copied, and the start
+ * and count parameters specify which elements to extract. If no count is
+ * given, elements will be extracted from the start to the end of the array.
+ * When specifying the start, remember that the first array element is 0.
+ * This function does not change the source array.
+ *
+ * @method subset
+ * @param {Array} list Array to extract from
+ * @param {Number} start position to begin
+ * @param {Number} [count] number of values to extract
+ * @return {Array} Array of extracted elements
+ *
+ * @example
+ *
+ * function setup() {
+ * var myArray = new Array(1,2,3,4,5);
+ * print(myArray); // [1,2,3,4,5]
+ *
+ * var sub1 = subset(myArray, 0, 3);
+ * var sub2 = subset(myArray, 2, 2);
+ * print(sub1); // [1,2,3]
+ * print(sub2); // [3,4]
+ * }
+ *
+ */
+p5.prototype.subset = function(list, start, count) {
+ if (typeof count !== 'undefined') {
+ return list.slice(start, start + count);
+ } else {
+ return list.slice(start, list.length);
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],74:[function(_dereq_,module,exports){
+/**
+ * @module Data
+ * @submodule Conversion
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Converts a string to its floating point representation. The contents of a
+ * string must resemble a number, or NaN (not a number) will be returned.
+ * For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
+ * will return NaN.
+ *
+ * When an array of values is passed in, then an array of floats of the same
+ * length is returned.
+ *
+ * @method float
+ * @param {String} str float string to parse
+ * @return {Number} floating point representation of string
+ * @example
+ *
+ * var str = '20';
+ * var diameter = float(str);
+ * ellipse(width/2, height/2, diameter, diameter);
+ *
+ *
+ * @alt
+ * 20 by 20 white ellipse in the center of the canvas
+ *
+ */
+p5.prototype.float = function(str) {
+ if (str instanceof Array) {
+ return str.map(parseFloat);
+ }
+ return parseFloat(str);
+};
+
+/**
+ * Converts a boolean, string, or float to its integer representation.
+ * When an array of values is passed in, then an int array of the same length
+ * is returned.
+ *
+ * @method int
+ * @param {String|Boolean|Number|Array} n value to parse
+ * @return {Number} integer representation of value
+ * @example
+ *
+ * print(int("10")); // 10
+ * print(int(10.31)); // 10
+ * print(int(-10)); // -10
+ * print(int(true)); // 1
+ * print(int(false)); // 0
+ * print(int([false, true, "10.3", 9.8])); // [0, 1, 10, 9]
+ *
+ */
+p5.prototype.int = function(n, radix) {
+ radix = radix || 10;
+ if (typeof n === 'string') {
+ return parseInt(n, radix);
+ } else if (typeof n === 'number') {
+ return n | 0;
+ } else if (typeof n === 'boolean') {
+ return n ? 1 : 0;
+ } else if (n instanceof Array) {
+ return n.map(function(n) { return p5.prototype.int(n, radix); });
+ }
+};
+
+/**
+ * Converts a boolean, string or number to its string representation.
+ * When an array of values is passed in, then an array of strings of the same
+ * length is returned.
+ *
+ * @method str
+ * @param {String|Boolean|Number|Array} n value to parse
+ * @return {String} string representation of value
+ * @example
+ *
+ * print(str("10")); // "10"
+ * print(str(10.31)); // "10.31"
+ * print(str(-10)); // "-10"
+ * print(str(true)); // "true"
+ * print(str(false)); // "false"
+ * print(str([true, "10.3", 9.8])); // [ "true", "10.3", "9.8" ]
+ *
+ */
+p5.prototype.str = function(n) {
+ if (n instanceof Array) {
+ return n.map(p5.prototype.str);
+ } else {
+ return String(n);
+ }
+};
+
+/**
+ * Converts a number or string to its boolean representation.
+ * For a number, any non-zero value (positive or negative) evaluates to true,
+ * while zero evaluates to false. For a string, the value "true" evaluates to
+ * true, while any other value evaluates to false. When an array of number or
+ * string values is passed in, then a array of booleans of the same length is
+ * returned.
+ *
+ * @method boolean
+ * @param {String|Boolean|Number|Array} n value to parse
+ * @return {Boolean} boolean representation of value
+ * @example
+ *
+ * print(boolean(0)); // false
+ * print(boolean(1)); // true
+ * print(boolean("true")); // true
+ * print(boolean("abcd")); // false
+ * print(boolean([0, 12, "true"])); // [false, true, false]
+ *
+ */
+p5.prototype.boolean = function(n) {
+ if (typeof n === 'number') {
+ return n !== 0;
+ } else if (typeof n === 'string') {
+ return n.toLowerCase() === 'true';
+ } else if (typeof n === 'boolean') {
+ return n;
+ } else if (n instanceof Array) {
+ return n.map(p5.prototype.boolean);
+ }
+};
+
+/**
+ * Converts a number, string or boolean to its byte representation.
+ * A byte can be only a whole number between -128 and 127, so when a value
+ * outside of this range is converted, it wraps around to the corresponding
+ * byte representation. When an array of number, string or boolean values is
+ * passed in, then an array of bytes the same length is returned.
+ *
+ * @method byte
+ * @param {String|Boolean|Number|Array} n value to parse
+ * @return {Number} byte representation of value
+ * @example
+ *
+ * print(byte(127)); // 127
+ * print(byte(128)); // -128
+ * print(byte(23.4)); // 23
+ * print(byte("23.4")); // 23
+ * print(byte(true)); // 1
+ * print(byte([0, 255, "100"])); // [0, -1, 100]
+ *
+ */
+p5.prototype.byte = function(n) {
+ var nn = p5.prototype.int(n, 10);
+ if (typeof nn === 'number') {
+ return ((nn + 128) % 256) - 128;
+ } else if (nn instanceof Array) {
+ return nn.map(p5.prototype.byte);
+ }
+};
+
+/**
+ * Converts a number or string to its corresponding single-character
+ * string representation. If a string parameter is provided, it is first
+ * parsed as an integer and then translated into a single-character string.
+ * When an array of number or string values is passed in, then an array of
+ * single-character strings of the same length is returned.
+ *
+ * @method char
+ * @param {String|Number|Array} n value to parse
+ * @return {String} string representation of value
+ * @example
+ *
+ * print(char(65)); // "A"
+ * print(char("65")); // "A"
+ * print(char([65, 66, 67])); // [ "A", "B", "C" ]
+ * print(join(char([65, 66, 67]), '')); // "ABC"
+ *
+ */
+p5.prototype.char = function(n) {
+ if (typeof n === 'number' && !isNaN(n)) {
+ return String.fromCharCode(n);
+ } else if (n instanceof Array) {
+ return n.map(p5.prototype.char);
+ } else if (typeof n === 'string') {
+ return p5.prototype.char(parseInt(n, 10));
+ }
+};
+
+/**
+ * Converts a single-character string to its corresponding integer
+ * representation. When an array of single-character string values is passed
+ * in, then an array of integers of the same length is returned.
+ *
+ * @method unchar
+ * @param {String|Array} n value to parse
+ * @return {Number} integer representation of value
+ * @example
+ *
+ * print(unchar("A")); // 65
+ * print(unchar(["A", "B", "C"])); // [ 65, 66, 67 ]
+ * print(unchar(split("ABC", ""))); // [ 65, 66, 67 ]
+ *
+ */
+p5.prototype.unchar = function(n) {
+ if (typeof n === 'string' && n.length === 1) {
+ return n.charCodeAt(0);
+ } else if (n instanceof Array) {
+ return n.map(p5.prototype.unchar);
+ }
+};
+
+/**
+ * Converts a number to a string in its equivalent hexadecimal notation. If a
+ * second parameter is passed, it is used to set the number of characters to
+ * generate in the hexadecimal notation. When an array is passed in, an
+ * array of strings in hexadecimal notation of the same length is returned.
+ *
+ * @method hex
+ * @param {Number|Array} n value to parse
+ * @return {String} hexadecimal string representation of value
+ * @example
+ *
+ * print(hex(255)); // "000000FF"
+ * print(hex(255, 6)); // "0000FF"
+ * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
+ *
+ */
+p5.prototype.hex = function(n, digits) {
+ digits = (digits === undefined || digits === null) ? digits = 8 : digits;
+ if (n instanceof Array) {
+ return n.map(function(n) { return p5.prototype.hex(n, digits); });
+ } else if (typeof n === 'number') {
+ if (n < 0) {
+ n = 0xFFFFFFFF + n + 1;
+ }
+ var hex = Number(n).toString(16).toUpperCase();
+ while (hex.length < digits) {
+ hex = '0' + hex;
+ }
+ if (hex.length >= digits) {
+ hex = hex.substring(hex.length - digits, hex.length);
+ }
+ return hex;
+ }
+};
+
+/**
+ * Converts a string representation of a hexadecimal number to its equivalent
+ * integer value. When an array of strings in hexadecimal notation is passed
+ * in, an array of integers of the same length is returned.
+ *
+ * @method unhex
+ * @param {String|Array} n value to parse
+ * @return {Number} integer representation of hexadecimal value
+ * @example
+ *
+ * print(unhex("A")); // 10
+ * print(unhex("FF")); // 255
+ * print(unhex(["FF", "AA", "00"])); // [ 255, 170, 0 ]
+ *
+ */
+p5.prototype.unhex = function(n) {
+ if (n instanceof Array) {
+ return n.map(p5.prototype.unhex);
+ } else {
+ return parseInt('0x' + n, 16);
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],75:[function(_dereq_,module,exports){
+/**
+ * @module Data
+ * @submodule String Functions
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+//return p5; //LM is this a mistake?
+
+/**
+ * Combines an array of Strings into one String, each separated by the
+ * character(s) used for the separator parameter. To join arrays of ints or
+ * floats, it's necessary to first convert them to Strings using nf() or
+ * nfs().
+ *
+ * @method join
+ * @param {Array} list array of Strings to be joined
+ * @param {String} separator String to be placed between each item
+ * @return {String} joined String
+ * @example
+ *
+ *
+ * var array = ["Hello", "world!"]
+ * var separator = " "
+ * var message = join(array, separator);
+ * text(message, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * "hello world!" displayed middle left of canvas.
+ *
+ */
+p5.prototype.join = function(list, separator) {
+ return list.join(separator);
+};
+
+/**
+ * This function is used to apply a regular expression to a piece of text,
+ * and return matching groups (elements found inside parentheses) as a
+ * String array. If there are no matches, a null value will be returned.
+ * If no groups are specified in the regular expression, but the sequence
+ * matches, an array of length 1 (with the matched text as the first element
+ * of the array) will be returned.
+ *
+ * To use the function, first check to see if the result is null. If the
+ * result is null, then the sequence did not match at all. If the sequence
+ * did match, an array is returned.
+ *
+ * If there are groups (specified by sets of parentheses) in the regular
+ * expression, then the contents of each will be returned in the array.
+ * Element [0] of a regular expression match returns the entire matching
+ * string, and the match groups start at element [1] (the first group is [1],
+ * the second [2], and so on).
+ *
+ * @method match
+ * @param {String} str the String to be searched
+ * @param {String} regexp the regexp to be used for matching
+ * @return {Array} Array of Strings found
+ * @example
+ *
+ *
+ * var string = "Hello p5js*!"
+ * var regexp = "p5js\\*"
+ * var match = match(string, regexp);
+ * text(match, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * "p5js*" displayed middle left of canvas.
+ *
+ */
+p5.prototype.match = function(str, reg) {
+ return str.match(reg);
+};
+
+/**
+ * This function is used to apply a regular expression to a piece of text,
+ * and return a list of matching groups (elements found inside parentheses)
+ * as a two-dimensional String array. If there are no matches, a null value
+ * will be returned. If no groups are specified in the regular expression,
+ * but the sequence matches, a two dimensional array is still returned, but
+ * the second dimension is only of length one.
+ *
+ * To use the function, first check to see if the result is null. If the
+ * result is null, then the sequence did not match at all. If the sequence
+ * did match, a 2D array is returned.
+ *
+ * If there are groups (specified by sets of parentheses) in the regular
+ * expression, then the contents of each will be returned in the array.
+ * Assuming a loop with counter variable i, element [i][0] of a regular
+ * expression match returns the entire matching string, and the match groups
+ * start at element [i][1] (the first group is [i][1], the second [i][2],
+ * and so on).
+ *
+ * @method matchAll
+ * @param {String} str the String to be searched
+ * @param {String} regexp the regexp to be used for matching
+ * @return {Array} 2d Array of Strings found
+ * @example
+ *
+ *
+ * var string = "Hello p5js*! Hello world!"
+ * var regexp = "Hello"
+ * matchAll(string, regexp);
+ *
+ *
+
+ */
+p5.prototype.matchAll = function(str, reg) {
+ var re = new RegExp(reg, 'g');
+ var match = re.exec(str);
+ var matches = [];
+ while (match !== null) {
+ matches.push(match);
+ // matched text: match[0]
+ // match start: match.index
+ // capturing group n: match[n]
+ match = re.exec(str);
+ }
+ return matches;
+};
+
+/**
+ * Utility function for formatting numbers into strings. There are two
+ * versions: one for formatting floats, and one for formatting ints.
+ * The values for the digits, left, and right parameters should always
+ * be positive integers.
+ *
+ * @method nf
+ * @param {Number|Array} num the Number to format
+ * @param {Number} [left] number of digits to the left of the
+ * decimal point
+ * @param {Number} [right] number of digits to the right of the
+ * decimal point
+ * @return {String|Array} formatted String
+ * @example
+ *
+ *
+ * function setup() {
+ * background(200);
+ * var num = 112.53106115;
+ *
+ * noStroke();
+ * fill(0);
+ * textSize(14);
+ * // Draw formatted numbers
+ * text(nf(num, 5, 2), 10, 20);
+ *
+ * text(nf(num, 4, 3), 10, 55);
+ *
+ * text(nf(num, 3, 6), 10, 85);
+ *
+ * // Draw dividing lines
+ * stroke(120);
+ * line(0, 30, width, 30);
+ * line(0, 65, width, 65);
+ * }
+ *
+ *
+ *
+ * @alt
+ * "0011253" top left, "0112.531" mid left, "112.531061" bottom left canvas
+ *
+ */
+p5.prototype.nf = function () {
+ if (arguments[0] instanceof Array) {
+ var a = arguments[1];
+ var b = arguments[2];
+ return arguments[0].map(function (x) {
+ return doNf(x, a, b);
+ });
+ }
+ else{
+ var typeOfFirst = Object.prototype.toString.call(arguments[0]);
+ if(typeOfFirst === '[object Arguments]'){
+ if(arguments[0].length===3){
+ return this.nf(arguments[0][0],arguments[0][1],arguments[0][2]);
+ }
+ else if(arguments[0].length===2){
+ return this.nf(arguments[0][0],arguments[0][1]);
+ }
+ else{
+ return this.nf(arguments[0][0]);
+ }
+ }
+ else {
+ return doNf.apply(this, arguments);
+ }
+ }
+};
+
+function doNf() {
+ var num = arguments[0];
+ var neg = num < 0;
+ var n = neg ? num.toString().substring(1) : num.toString();
+ var decimalInd = n.indexOf('.');
+ var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
+ var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
+ var str = neg ? '-' : '';
+ if (arguments.length === 3) {
+ var decimal = '';
+ if(decimalInd !== -1 || arguments[2] - decPart.length > 0){
+ decimal = '.';
+ }
+ if (decPart.length > arguments[2]) {
+ decPart = decPart.substring(0, arguments[2]);
+ }
+ for (var i = 0; i < arguments[1] - intPart.length; i++) {
+ str += '0';
+ }
+ str += intPart;
+ str += decimal;
+ str += decPart;
+ for (var j = 0; j < arguments[2] - decPart.length; j++) {
+ str += '0';
+ }
+ return str;
+ }
+ else {
+ for (var k = 0; k < Math.max(arguments[1] - intPart.length, 0); k++) {
+ str += '0';
+ }
+ str += n;
+ return str;
+ }
+}
+
+/**
+ * Utility function for formatting numbers into strings and placing
+ * appropriate commas to mark units of 1000. There are two versions: one
+ * for formatting ints, and one for formatting an array of ints. The value
+ * for the right parameter should always be a positive integer.
+ *
+ * @method nfc
+ * @param {Number|Array} num the Number to format
+ * @param {Number} [right] number of digits to the right of the
+ * decimal point
+ * @return {String|Array} formatted String
+ * @example
+ *
+ *
+ * function setup() {
+ * background(200);
+ * var num = 11253106.115;
+ * var numArr = new Array(1,1,2);
+ *
+ * noStroke();
+ * fill(0);
+ * textSize(12);
+ *
+ * // Draw formatted numbers
+ * text(nfc(num, 4, 2), 10, 30);
+ * text(nfc(numArr, 2, 1), 10, 80);
+ *
+ * // Draw dividing line
+ * stroke(120);
+ * line(0, 50, width, 50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid
+ *
+ */
+p5.prototype.nfc = function () {
+ if (arguments[0] instanceof Array) {
+ var a = arguments[1];
+ return arguments[0].map(function (x) {
+ return doNfc(x, a);
+ });
+ } else {
+ return doNfc.apply(this, arguments);
+ }
+};
+function doNfc() {
+ var num = arguments[0].toString();
+ var dec = num.indexOf('.');
+ var rem = dec !== -1 ? num.substring(dec) : '';
+ var n = dec !== -1 ? num.substring(0, dec) : num;
+ n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+ if (arguments[1] === 0) {
+ rem = '';
+ }
+ else if(arguments[1] !== undefined){
+ if(arguments[1] > rem.length){
+ rem+= dec === -1 ? '.' : '';
+ var len = arguments[1] - rem.length + 1;
+ for(var i =0; i< len; i++){
+ rem += '0';
+ }
+ }
+ else{
+ rem = rem.substring(0, arguments[1] + 1);
+ }
+ }
+ return n + rem;
+}
+
+/**
+ * Utility function for formatting numbers into strings. Similar to nf() but
+ * puts a "+" in front of positive numbers and a "-" in front of negative
+ * numbers. There are two versions: one for formatting floats, and one for
+ * formatting ints. The values for left, and right parameters
+ * should always be positive integers.
+ *
+ * @method nfp
+ * @param {Number|Array} num the Number to format
+ * @param {Number} [left] number of digits to the left of the decimal
+ * point
+ * @param {Number} [right] number of digits to the right of the
+ * decimal point
+ * @return {String|Array} formatted String
+ * @example
+ *
+ *
+ * function setup() {
+ * background(200);
+ * var num1 = 11253106.115;
+ * var num2 = -11253106.115;
+ *
+ * noStroke();
+ * fill(0);
+ * textSize(12);
+ *
+ * // Draw formatted numbers
+ * text(nfp(num1, 4, 2), 10, 30);
+ * text(nfp(num2, 4, 2), 10, 80);
+ *
+ * // Draw dividing line
+ * stroke(120);
+ * line(0, 50, width, 50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * "+11253106.11" top middle and "-11253106.11" displayed bottom middle
+ *
+ */
+p5.prototype.nfp = function() {
+ var nfRes = this.nf.apply(this, arguments);
+ if (nfRes instanceof Array) {
+ return nfRes.map(addNfp);
+ } else {
+ return addNfp(nfRes);
+ }
+};
+
+function addNfp() {
+ return (
+ parseFloat(arguments[0]) > 0) ?
+ '+'+arguments[0].toString() :
+ arguments[0].toString();
+}
+
+/**
+ * Utility function for formatting numbers into strings. Similar to nf() but
+ * puts a " " (space) in front of positive numbers and a "-" in front of
+ * negative numbers. There are two versions: one for formatting floats, and
+ * one for formatting ints. The values for the digits, left, and right
+ * parameters should always be positive integers.
+ *
+ * @method nfs
+ * @param {Number|Array} num the Number to format
+ * @param {Number} [left] number of digits to the left of the decimal
+ * point
+ * @param {Number} [right] number of digits to the right of the
+ * decimal point
+ * @return {String|Array} formatted String
+ * @example
+ *
+ *
+ * function setup() {
+ * background(200);
+ * var num1 = 11253106.115;
+ * var num2 = -11253106.115;
+ *
+ * noStroke();
+ * fill(0);
+ * textSize(12);
+ * // Draw formatted numbers
+ * text(nfs(num1, 4, 2), 10, 30);
+ *
+ * text(nfs(num2, 4, 2), 10, 80);
+ *
+ * // Draw dividing line
+ * stroke(120);
+ * line(0, 50, width, 50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * "11253106.11" top middle and "-11253106.11" displayed bottom middle
+ *
+ */
+p5.prototype.nfs = function() {
+ var nfRes = this.nf.apply(this, arguments);
+ if (nfRes instanceof Array) {
+ return nfRes.map(addNfs);
+ } else {
+ return addNfs(nfRes);
+ }
+};
+
+function addNfs() {
+ return (
+ parseFloat(arguments[0]) > 0) ?
+ ' '+arguments[0].toString() :
+ arguments[0].toString();
+}
+
+/**
+ * The split() function maps to String.split(), it breaks a String into
+ * pieces using a character or string as the delimiter. The delim parameter
+ * specifies the character or characters that mark the boundaries between
+ * each piece. A String[] array is returned that contains each of the pieces.
+ *
+ * The splitTokens() function works in a similar fashion, except that it
+ * splits using a range of characters instead of a specific character or
+ * sequence.
+ *
+ * @method split
+ * @param {String} value the String to be split
+ * @param {String} delim the String used to separate the data
+ * @return {Array} Array of Strings
+ * @example
+ *
+ *
+ * var names = "Pat,Xio,Alex"
+ * var splitString = split(names, ",");
+ * text(splitString[0], 5, 30);
+ * text(splitString[1], 5, 50);
+ * text(splitString[2], 5, 70);
+ *
+ *
+ *
+ * @alt
+ * "pat" top left, "Xio" mid left and "Alex" displayed bottom left
+ *
+ */
+p5.prototype.split = function(str, delim) {
+ return str.split(delim);
+};
+
+/**
+ * The splitTokens() function splits a String at one or many character
+ * delimiters or "tokens." The delim parameter specifies the character or
+ * characters to be used as a boundary.
+ *
+ * If no delim characters are specified, any whitespace character is used to
+ * split. Whitespace characters include tab (\t), line feed (\n), carriage
+ * return (\r), form feed (\f), and space.
+ *
+ * @method splitTokens
+ * @param {String} value the String to be split
+ * @param {String} [delim] list of individual Strings that will be used as
+ * separators
+ * @return {Array} Array of Strings
+ * @example
+ *
+ *
+ * function setup() {
+ * var myStr = "Mango, Banana, Lime";
+ * var myStrArr = splitTokens(myStr, ",");
+ *
+ * print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
+ * }
+ *
+ *
+ */
+p5.prototype.splitTokens = function() {
+ var d,sqo,sqc,str;
+ str = arguments[1];
+ if (arguments.length > 1) {
+ sqc = /\]/g.exec(str);
+ sqo = /\[/g.exec(str);
+ if ( sqo && sqc ) {
+ str = str.slice(0, sqc.index) + str.slice(sqc.index+1);
+ sqo = /\[/g.exec(str);
+ str = str.slice(0, sqo.index) + str.slice(sqo.index+1);
+ d = new RegExp('[\\['+str+'\\]]','g');
+ } else if ( sqc ) {
+ str = str.slice(0, sqc.index) + str.slice(sqc.index+1);
+ d = new RegExp('[' + str + '\\]]', 'g');
+ } else if(sqo) {
+ str = str.slice(0, sqo.index) + str.slice(sqo.index+1);
+ d = new RegExp('[' + str + '\\[]', 'g');
+ } else {
+ d = new RegExp('[' + str + ']', 'g');
+ }
+ } else {
+ d = /\s/g;
+ }
+ return arguments[0].split(d).filter(function(n){return n;});
+};
+
+/**
+ * Removes whitespace characters from the beginning and end of a String. In
+ * addition to standard whitespace characters such as space, carriage return,
+ * and tab, this function also removes the Unicode "nbsp" character.
+ *
+ * @method trim
+ * @param {String|Array} str a String or Array of Strings to be trimmed
+ * @return {String|Array} a trimmed String or Array of Strings
+ * @example
+ *
+ *
+ * var string = trim(" No new lines\n ");
+ * text(string +" here", 2, 50);
+ *
+ *
+ *
+ * @alt
+ * "No new lines here" displayed center canvas
+ *
+ */
+p5.prototype.trim = function(str) {
+ if (str instanceof Array) {
+ return str.map(this.trim);
+ } else {
+ return str.trim();
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],76:[function(_dereq_,module,exports){
+/**
+ * @module IO
+ * @submodule Time & Date
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * p5.js communicates with the clock on your computer. The day() function
+ * returns the current day as a value from 1 - 31.
+ *
+ * @method day
+ * @return {Number} the current day
+ * @example
+ *
+ *
+ * var d = day();
+ * text("Current day: \n" + d, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current day is displayed
+ *
+ */
+p5.prototype.day = function() {
+ return new Date().getDate();
+};
+
+/**
+ * p5.js communicates with the clock on your computer. The hour() function
+ * returns the current hour as a value from 0 - 23.
+ *
+ * @method hour
+ * @return {Number} the current hour
+ * @example
+ *
+ *
+ * var h = hour();
+ * text("Current hour:\n" + h, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current hour is displayed
+ *
+ */
+p5.prototype.hour = function() {
+ return new Date().getHours();
+};
+
+/**
+ * p5.js communicates with the clock on your computer. The minute() function
+ * returns the current minute as a value from 0 - 59.
+ *
+ * @method minute
+ * @return {Number} the current minute
+ * @example
+ *
+ *
+ * var m = minute();
+ * text("Current minute: \n" + m, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current minute is displayed
+ *
+ */
+p5.prototype.minute = function() {
+ return new Date().getMinutes();
+};
+
+/**
+ * Returns the number of milliseconds (thousandths of a second) since
+ * starting the program. This information is often used for timing events and
+ * animation sequences.
+ *
+ * @method millis
+ * @return {Number} the number of milliseconds since starting the program
+ * @example
+ *
+ *
+ * var millisecond = millis();
+ * text("Milliseconds \nrunning: \n" + millisecond, 5, 40);
+ *
+ *
+ *
+ * @alt
+ * number of milliseconds since program has started displayed
+ *
+ */
+p5.prototype.millis = function() {
+ return window.performance.now();
+};
+
+/**
+ * p5.js communicates with the clock on your computer. The month() function
+ * returns the current month as a value from 1 - 12.
+ *
+ * @method month
+ * @return {Number} the current month
+ * @example
+ *
+ *
+ * var m = month();
+ * text("Current month: \n" + m, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current month is displayed
+ *
+ */
+p5.prototype.month = function() {
+ return new Date().getMonth() + 1; //January is 0!
+};
+
+/**
+ * p5.js communicates with the clock on your computer. The second() function
+ * returns the current second as a value from 0 - 59.
+ *
+ * @method second
+ * @return {Number} the current second
+ * @example
+ *
+ *
+ * var s = second();
+ * text("Current second: \n" + s, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current second is displayed
+ *
+ */
+p5.prototype.second = function() {
+ return new Date().getSeconds();
+};
+
+/**
+ * p5.js communicates with the clock on your computer. The year() function
+ * returns the current year as an integer (2014, 2015, 2016, etc).
+ *
+ * @method year
+ * @return {Number} the current year
+ * @example
+ *
+ *
+ * var y = year();
+ * text("Current year: \n" + y, 5, 50);
+ *
+ *
+ *
+ * @alt
+ * Current year is displayed
+ *
+ */
+p5.prototype.year = function() {
+ return new Date().getFullYear();
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],77:[function(_dereq_,module,exports){
+/**
+ * @module Lights, Camera
+ * @submodule Camera
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Sets camera position
+ * @method camera
+ * @param {Number} x camera position value on x axis
+ * @param {Number} y camera position value on y axis
+ * @param {Number} z camera position value on z axis
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * //move the camera away from the plane by a sin wave
+ * camera(0, 0, sin(frameCount * 0.01) * 100);
+ * plane(120, 120);
+ * }
+ *
+ *
+ *
+ * @alt
+ * blue square shrinks in size grows to fill canvas. disappears then loops.
+ *
+ */
+p5.prototype.camera = function(x, y, z){
+ //what it manipulates is the model view matrix
+ this._renderer.translate(-x, -y, -z);
+};
+
+/**
+ * Sets perspective camera
+ * @method perspective
+ * @param {Number} fovy camera frustum vertical field of view,
+ * from bottom to top of view, in degrees
+ * @param {Number} aspect camera frustum aspect ratio
+ * @param {Number} near frustum near plane length
+ * @param {Number} far frustum far plane length
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //drag mouse to toggle the world!
+ * //you will see there's a vanish point
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * var fov = 60 / 180 * PI;
+ * var cameraZ = (height/2.0) / tan(fov/2.0);
+ * perspective(60 / 180 * PI, width/height, cameraZ * 0.1, cameraZ * 10);
+ * }
+ * function draw(){
+ * background(200);
+ * orbitControl();
+ * for(var i = -1; i < 2; i++){
+ * for(var j = -2; j < 3; j++){
+ * push();
+ * translate(i*160, 0, j*160);
+ * box(40, 40, 40);
+ * pop();
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ * @alt
+ * colored 3d boxes toggleable with mouse position
+ *
+ */
+p5.prototype.perspective = function(fovy,aspect,near,far) {
+ fovy = fovy || (60 / 180 * this.PI);
+ aspect = aspect || (this.width/this.height);
+ near = near || ((this.height/2.0) / this.tan(fovy/2.0) * 0.1);
+ far = far || ((this.height/2.0) / this.tan(fovy/2.0) * 10);
+ this._renderer.uPMatrix = p5.Matrix.identity();
+ this._renderer.uPMatrix.perspective(fovy,aspect,near,far);
+ this._renderer._curCamera = 'custom';
+};
+
+/**
+ * Setup ortho camera
+ * @method ortho
+ * @param {Number} left camera frustum left plane
+ * @param {Number} right camera frustum right plane
+ * @param {Number} bottom camera frustum bottom plane
+ * @param {Number} top camera frustum top plane
+ * @param {Number} near camera frustum near plane
+ * @param {Number} far camera frustum far plane
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //drag mouse to toggle the world!
+ * //there's no vanish point
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * ortho(-width/2, width/2, height/2, -height/2, 0, 500);
+ * }
+ * function draw(){
+ * background(200);
+ * orbitControl();
+ * for(var i = -1; i < 2; i++){
+ * for(var j = -2; j < 3; j++){
+ * push();
+ * translate(i*160, 0, j*160);
+ * box(40, 40, 40);
+ * pop();
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ * @alt
+ * 3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle
+ *
+ */
+p5.prototype.ortho = function(left,right,bottom,top,near,far) {
+ left = left || (-this.width/2);
+ right = right || (this.width/2);
+ bottom = bottom || (-this.height/2);
+ top = top || (this.height/2);
+ near = near || 0;
+ far = far || Math.max(this.width, this.height);
+ this._renderer.uPMatrix = p5.Matrix.identity();
+ this._renderer.uPMatrix.ortho(left,right,bottom,top,near,far);
+ this._renderer._curCamera = 'custom';
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],78:[function(_dereq_,module,exports){
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+//@TODO: implement full orbit controls including
+//pan, zoom, quaternion rotation, etc.
+p5.prototype.orbitControl = function(){
+ if(this.mouseIsPressed){
+ this.rotateY((this.mouseX - this.width / 2) / (this.width / 2));
+ this.rotateX((this.mouseY - this.height / 2) / (this.width / 2));
+ }
+ return this;
+};
+
+module.exports = p5;
+},{"../core/core":37}],79:[function(_dereq_,module,exports){
+/**
+ * @module Lights, Camera
+ * @submodule Lights
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * Creates an ambient light with a color
+ * @method ambientLight
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * background(0);
+ * ambientLight(150);
+ * ambientMaterial(250);
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * nothing displayed
+ *
+ */
+p5.prototype.ambientLight = function(v1, v2, v3, a){
+ var gl = this._renderer.GL;
+ var shaderProgram = this._renderer._getShader(
+ 'lightVert', 'lightTextureFrag');
+
+ gl.useProgram(shaderProgram);
+ shaderProgram.uAmbientColor = gl.getUniformLocation(
+ shaderProgram,
+ 'uAmbientColor[' + this._renderer.ambientLightCount + ']');
+
+ var color = this._renderer._pInst.color.apply(
+ this._renderer._pInst, arguments);
+ var colors = color._array;
+
+ gl.uniform3f( shaderProgram.uAmbientColor,
+ colors[0], colors[1], colors[2]);
+
+ //in case there's no material color for the geometry
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
+
+ this._renderer.ambientLightCount ++;
+ shaderProgram.uAmbientLightCount =
+ gl.getUniformLocation(shaderProgram, 'uAmbientLightCount');
+ gl.uniform1i(shaderProgram.uAmbientLightCount,
+ this._renderer.ambientLightCount);
+
+ return this;
+};
+
+/**
+ * Creates a directional light with a color and a direction
+ * @method directionalLight
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+ * @param {Number|p5.Vector} x x axis direction or a p5.Vector
+ * @param {Number} [y] optional: y axis direction
+ * @param {Number} [z] optional: z axis direction
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * background(0);
+ * //move your mouse to change light direction
+ * var dirX = (mouseX / width - 0.5) *2;
+ * var dirY = (mouseY / height - 0.5) *(-2);
+ * directionalLight(250, 250, 250, dirX, dirY, 0.25);
+ * ambientMaterial(250);
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * light source on canvas changeable with mouse position
+ *
+ */
+p5.prototype.directionalLight = function(v1, v2, v3, a, x, y, z) {
+ var gl = this._renderer.GL;
+ var shaderProgram = this._renderer._getShader(
+ 'lightVert', 'lightTextureFrag');
+
+ gl.useProgram(shaderProgram);
+ shaderProgram.uDirectionalColor = gl.getUniformLocation(
+ shaderProgram,
+ 'uDirectionalColor[' + this._renderer.directionalLightCount + ']');
+
+ //@TODO: check parameters number
+ var color = this._renderer._pInst.color.apply(
+ this._renderer._pInst, [v1, v2, v3]);
+ var colors = color._array;
+
+ gl.uniform3f( shaderProgram.uDirectionalColor,
+ colors[0], colors[1], colors[2]);
+
+ var _x, _y, _z;
+
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ if(typeof args[args.length-1] === 'number'){
+ _x = args[args.length-3];
+ _y = args[args.length-2];
+ _z = args[args.length-1];
+
+ }else{
+ try{
+ _x = args[args.length-1].x;
+ _y = args[args.length-1].y;
+ _z = args[args.length-1].z;
+ }
+ catch(error){
+ throw error;
+ }
+ }
+
+ shaderProgram.uLightingDirection = gl.getUniformLocation(
+ shaderProgram,
+ 'uLightingDirection[' + this._renderer.directionalLightCount + ']');
+ gl.uniform3f( shaderProgram.uLightingDirection, _x, _y, _z);
+
+ //in case there's no material color for the geometry
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
+
+ this._renderer.directionalLightCount ++;
+ shaderProgram.uDirectionalLightCount =
+ gl.getUniformLocation(shaderProgram, 'uDirectionalLightCount');
+ gl.uniform1i(shaderProgram.uDirectionalLightCount,
+ this._renderer.directionalLightCount);
+
+ return this;
+};
+
+/**
+ * Creates a point light with a color and a light position
+ * @method pointLight
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+ * @param {Number|p5.Vector} x x axis position or a p5.Vector
+ * @param {Number} [y] optional: y axis position
+ * @param {Number} [z] optional: z axis position
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * background(0);
+ * //move your mouse to change light position
+ * var locY = (mouseY / height - 0.5) *(-2);
+ * var locX = (mouseX / width - 0.5) *2;
+ * //to set the light position,
+ * //think of the world's coordinate as:
+ * // -1,1 -------- 1,1
+ * // | |
+ * // | |
+ * // | |
+ * // -1,-1---------1,-1
+ * pointLight(250, 250, 250, locX, locY, 0);
+ * ambientMaterial(250);
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * spot light on canvas changes position with mouse
+ *
+ */
+p5.prototype.pointLight = function(v1, v2, v3, a, x, y, z) {
+ var gl = this._renderer.GL;
+ var shaderProgram = this._renderer._getShader(
+ 'lightVert', 'lightTextureFrag');
+
+ gl.useProgram(shaderProgram);
+ shaderProgram.uPointLightColor = gl.getUniformLocation(
+ shaderProgram,
+ 'uPointLightColor[' + this._renderer.pointLightCount + ']');
+
+ //@TODO: check parameters number
+ var color = this._renderer._pInst.color.apply(
+ this._renderer._pInst, [v1, v2, v3]);
+ var colors = color._array;
+
+ gl.uniform3f( shaderProgram.uPointLightColor,
+ colors[0], colors[1], colors[2]);
+
+ var _x, _y, _z;
+
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ if(typeof args[args.length-1] === 'number'){
+ _x = args[args.length-3];
+ _y = args[args.length-2];
+ _z = args[args.length-1];
+
+ }else{
+ try{
+ _x = args[args.length-1].x;
+ _y = args[args.length-1].y;
+ _z = args[args.length-1].z;
+ }
+ catch(error){
+ throw error;
+ }
+ }
+
+ shaderProgram.uPointLightLocation = gl.getUniformLocation(
+ shaderProgram,
+ 'uPointLightLocation[' + this._renderer.pointLightCount + ']');
+ gl.uniform3f( shaderProgram.uPointLightLocation, _x, _y, _z);
+
+ //in case there's no material color for the geometry
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
+
+ this._renderer.pointLightCount ++;
+ shaderProgram.uPointLightCount =
+ gl.getUniformLocation(shaderProgram, 'uPointLightCount');
+ gl.uniform1i(shaderProgram.uPointLightCount,
+ this._renderer.pointLightCount);
+
+ return this;
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],80:[function(_dereq_,module,exports){
+/**
+ * @module Shape
+ * @submodule 3D Models
+ * @for p5
+ * @requires core
+ * @requires p5.Geometry3D
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+_dereq_('./p5.Geometry');
+
+/**
+ * Load a 3d model from an OBJ file.
+ *
+ * One of the limitations of the OBJ format is that it doesn't have a built-in
+ * sense of scale. This means that models exported from different programs might
+ * be very different sizes. If your model isn't displaying, try calling
+ * loadModel() with the normalized parameter set to true. This will resize the
+ * model to a scale appropriate for p5. You can also make additional changes to
+ * the final size of your model with the scale() function.
+ *
+ * @method loadModel
+ * @param {String} path Path of the model to be loaded
+ * @param {Boolean} [normalize] If true, scale the model to a
+ * standardized size when loading
+ * @param {Function(p5.Geometry3D)} [successCallback] Function to be called
+ * once the model is loaded. Will be passed
+ * the 3D model object.
+ * @param {Function(Event)} [failureCallback] called with event error if
+ * the image fails to load.
+ * @return {p5.Geometry} the p5.Geometry3D object
+ * @example
+ *
+ *
+ * //draw a spinning teapot
+ * var teapot;
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ *
+ * teapot = loadModel('assets/teapot.obj');
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * model(teapot);
+ * }
+ *
+ *
+ *
+ * @alt
+ * Vertically rotating 3-d teapot with red, green and blue gradient.
+ *
+ */
+p5.prototype.loadModel = function () {
+ var path = arguments[0];
+ var normalize;
+ var successCallback;
+ var failureCallback;
+ if(typeof arguments[1] === 'boolean') {
+ normalize = arguments[1];
+ successCallback = arguments[2];
+ failureCallback = arguments[3];
+ } else {
+ normalize = false;
+ successCallback = arguments[1];
+ failureCallback = arguments[2];
+ }
+
+ var model = new p5.Geometry();
+ model.gid = path + '|' + normalize;
+ this.loadStrings(path, function(strings) {
+ parseObj(model, strings);
+
+ if (normalize) {
+ model.normalize();
+ }
+
+ if (typeof successCallback === 'function') {
+ successCallback(model);
+ }
+ }.bind(this), failureCallback);
+
+ return model;
+};
+
+/**
+ * Parse OBJ lines into model. For reference, this is what a simple model of a
+ * square might look like:
+ *
+ * v -0.5 -0.5 0.5
+ * v -0.5 -0.5 -0.5
+ * v -0.5 0.5 -0.5
+ * v -0.5 0.5 0.5
+ *
+ * f 4 3 2 1
+ */
+function parseObj( model, lines ) {
+ // OBJ allows a face to specify an index for a vertex (in the above example),
+ // but it also allows you to specify a custom combination of vertex, UV
+ // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with
+ // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different
+ // parameters must be a different vertex, so loadedVerts is used to
+ // temporarily store the parsed vertices, normals, etc., and indexedVerts is
+ // used to map a specific combination (keyed on, for example, the string
+ // "3/4/3"), to the actual index of the newly created vertex in the final
+ // object.
+ var loadedVerts = {'v' : [],
+ 'vt' : [],
+ 'vn' : []};
+ var indexedVerts = {};
+
+ for (var line = 0; line < lines.length; ++line) {
+ // Each line is a separate object (vertex, face, vertex normal, etc)
+ // For each line, split it into tokens on whitespace. The first token
+ // describes the type.
+ var tokens = lines[line].trim().split(/\b\s+/);
+
+ if (tokens.length > 0) {
+ if (tokens[0] === 'v' || tokens[0] === 'vn') {
+ // Check if this line describes a vertex or vertex normal.
+ // It will have three numeric parameters.
+ var vertex = new p5.Vector(parseFloat(tokens[1]),
+ parseFloat(tokens[2]),
+ parseFloat(tokens[3]));
+ loadedVerts[tokens[0]].push(vertex);
+ } else if (tokens[0] === 'vt') {
+ // Check if this line describes a texture coordinate.
+ // It will have two numeric parameters.
+ var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])];
+ loadedVerts[tokens[0]].push(texVertex);
+ } else if (tokens[0] === 'f') {
+ // Check if this line describes a face.
+ // OBJ faces can have more than three points. Triangulate points.
+ for (var tri = 3; tri < tokens.length; ++tri) {
+ var face = [];
+
+ var vertexTokens = [1, tri - 1, tri];
+
+ for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) {
+ // Now, convert the given token into an index
+ var vertString = tokens[vertexTokens[tokenInd]];
+ var vertIndex = 0;
+
+ // TODO: Faces can technically use negative numbers to refer to the
+ // previous nth vertex. I haven't seen this used in practice, but
+ // it might be good to implement this in the future.
+
+ if (indexedVerts[vertString] !== undefined) {
+ vertIndex = indexedVerts[vertString];
+ } else {
+ var vertParts = vertString.split('/');
+ for (var i = 0; i < vertParts.length; i++) {
+ vertParts[i] = parseInt(vertParts[i]) - 1;
+ }
+
+ vertIndex = indexedVerts[vertString] = model.vertices.length;
+ model.vertices.push(loadedVerts.v[vertParts[0]].copy());
+ if (loadedVerts.vt[vertParts[1]]) {
+ model.uvs.push(loadedVerts.vt[vertParts[1]].slice());
+ } else {
+ model.uvs.push([0, 0]);
+ }
+
+ if (loadedVerts.vn[vertParts[2]]) {
+ model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy());
+ }
+ }
+
+ face.push(vertIndex);
+ }
+
+ model.faces.push(face);
+ }
+ }
+ }
+ }
+
+ // If the model doesn't have normals, compute the normals
+ if(model.vertexNormals.length === 0) {
+ model.computeNormals();
+ }
+
+ return model;
+}
+
+/**
+ * Render a 3d model to the screen.
+ *
+ * @method model
+ * @param {p5.Geometry} model Loaded 3d model to be rendered
+ * @example
+ *
+ *
+ * //draw a spinning teapot
+ * var teapot;
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ *
+ * teapot = loadModel('assets/teapot.obj');
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * model(teapot);
+ * }
+ *
+ *
+ *
+ * @alt
+ * Vertically rotating 3-d teapot with red, green and blue gradient.
+ *
+ */
+p5.prototype.model = function ( model ) {
+ if (model.vertices.length > 0) {
+ if (!this._renderer.geometryInHash(model.gid)) {
+ this._renderer.createBuffers(model.gid, model);
+ }
+
+ this._renderer.drawBuffers(model.gid);
+ }
+};
+
+module.exports = p5;
+
+},{"../core/core":37,"./p5.Geometry":82}],81:[function(_dereq_,module,exports){
+/**
+ * @module Lights, Camera
+ * @submodule Material
+ * @for p5
+ * @requires core
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+//require('./p5.Texture');
+
+/**
+ * Normal material for geometry. You can view all
+ * possible materials in this
+ * example.
+ * @method normalMaterial
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * normalMaterial();
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * Red, green and blue gradient.
+ *
+ */
+p5.prototype.normalMaterial = function(){
+ this._renderer._getShader('normalVert', 'normalFrag');
+ return this;
+};
+
+/**
+ * Texture for geometry. You can view other possible materials in this
+ * example.
+ * @method texture
+ * @param {p5.Image | p5.MediaElement | p5.Graphics} tex 2-dimensional graphics
+ * to render as texture
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * var img;
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * img = loadImage("assets/laDefense.jpg");
+ * }
+ *
+ * function draw(){
+ * background(0);
+ * rotateZ(frameCount * 0.01);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * //pass image as texture
+ * texture(img);
+ * box(200, 200, 200);
+ * }
+ *
+ *
+ *
+ *
+ *
+ * var pg;
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * pg = createGraphics(200, 200);
+ * pg.textSize(100);
+ * }
+ *
+ * function draw(){
+ * background(0);
+ * pg.background(255);
+ * pg.text('hello!', 0, 100);
+ * //pass image as texture
+ * texture(pg);
+ * plane(200);
+ * }
+ *
+ *
+ *
+ *
+ *
+ * var vid;
+ * function preload(){
+ * vid = createVideo("assets/fingers.mov");
+ * vid.hide();
+ * vid.loop();
+ * }
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(0);
+ * //pass video frame as texture
+ * texture(vid);
+ * plane(200);
+ * }
+ *
+ *
+ *
+ * @alt
+ * Rotating view of many images umbrella and grid roof on a 3d plane
+ * black canvas
+ * black canvas
+ *
+ */
+p5.prototype.texture = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var gl = this._renderer.GL;
+ var shaderProgram = this._renderer._getShader('lightVert',
+ 'lightTextureFrag');
+ gl.useProgram(shaderProgram);
+ var textureData;
+ //if argument is not already a texture
+ //create a new one
+ if(!args[0].isTexture){
+ if (args[0] instanceof p5.Image) {
+ textureData = args[0].canvas;
+ }
+ //if param is a video
+ else if (typeof p5.MediaElement !== 'undefined' &&
+ args[0] instanceof p5.MediaElement){
+ if(!args[0].loadedmetadata) {return;}
+ textureData = args[0].elt;
+ }
+ //used with offscreen 2d graphics renderer
+ else if(args[0] instanceof p5.Graphics){
+ textureData = args[0].elt;
+ }
+ var tex = gl.createTexture();
+ args[0]._setProperty('tex', tex);
+ args[0]._setProperty('isTexture', true);
+ this._renderer._bind.call(this, tex, textureData);
+ }
+ else {
+ if(args[0] instanceof p5.Graphics ||
+ (typeof p5.MediaElement !== 'undefined' &&
+ args[0] instanceof p5.MediaElement)){
+ textureData = args[0].elt;
+ }
+ else if(args[0] instanceof p5.Image){
+ textureData = args[0].canvas;
+ }
+ this._renderer._bind.call(this, args[0].tex, textureData);
+ }
+ //this is where we'd activate multi textures
+ //eg. gl.activeTexture(gl.TEXTURE0 + (unit || 0));
+ //but for now we just have a single texture.
+ //@TODO need to extend this functionality
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, args[0].tex);
+ gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), true);
+ gl.uniform1i(gl.getUniformLocation(shaderProgram, 'uSampler'), 0);
+ return this;
+};
+
+/**
+ * Texture Util functions
+ */
+p5.RendererGL.prototype._bind = function(tex, data){
+ var gl = this._renderer.GL;
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0,
+ gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texParameteri(gl.TEXTURE_2D,
+ gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D,
+ gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D,
+ gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D,
+ gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+};
+
+/**
+ * Checks whether val is a pot
+ * more info on power of 2 here:
+ * https://www.opengl.org/wiki/NPOT_Texture
+ * @param {Number} value
+ * @return {Boolean}
+ */
+// function _isPowerOf2 (value){
+// return (value & (value - 1)) === 0;
+// }
+
+/**
+ * returns the next highest power of 2 value
+ * @param {Number} value [description]
+ * @return {Number} [description]
+ */
+// function _nextHighestPOT (value){
+// --value;
+// for (var i = 1; i < 32; i <<= 1) {
+// value = value | value >> i;
+// }
+// return value + 1;
+
+/**
+ * Ambient material for geometry with a given color. You can view all
+ * possible materials in this
+ * example.
+ * @method ambientMaterial
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+* @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * background(0);
+ * ambientLight(100);
+ * pointLight(250, 250, 250, 100, 100, 0);
+ * ambientMaterial(250);
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * radiating light source from top right of canvas
+ *
+ */
+p5.prototype.ambientMaterial = function(v1, v2, v3, a) {
+ var gl = this._renderer.GL;
+ var shaderProgram =
+ this._renderer._getShader('lightVert', 'lightTextureFrag');
+
+ gl.useProgram(shaderProgram);
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ var colors = this._renderer._applyColorBlend.apply(this._renderer, arguments);
+
+ gl.uniform4f(shaderProgram.uMaterialColor,
+ colors[0], colors[1], colors[2], colors[3]);
+
+ shaderProgram.uSpecular = gl.getUniformLocation(
+ shaderProgram, 'uSpecular' );
+ gl.uniform1i(shaderProgram.uSpecular, false);
+
+ gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), false);
+
+ return this;
+};
+
+/**
+ * Specular material for geometry with a given color. You can view all
+ * possible materials in this
+ * example.
+ * @method specularMaterial
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ * function draw(){
+ * background(0);
+ * ambientLight(100);
+ * pointLight(250, 250, 250, 100, 100, 0);
+ * specularMaterial(250);
+ * sphere(50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * diffused radiating light source from top right of canvas
+ *
+ */
+p5.prototype.specularMaterial = function(v1, v2, v3, a) {
+ var gl = this._renderer.GL;
+ var shaderProgram =
+ this._renderer._getShader('lightVert', 'lightTextureFrag');
+ gl.useProgram(shaderProgram);
+ gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), false);
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ var colors = this._renderer._applyColorBlend.apply(this._renderer, arguments);
+ gl.uniform4f(shaderProgram.uMaterialColor,
+ colors[0], colors[1], colors[2], colors[3]);
+ shaderProgram.uSpecular = gl.getUniformLocation(
+ shaderProgram, 'uSpecular' );
+ gl.uniform1i(shaderProgram.uSpecular, true);
+
+ return this;
+};
+
+/**
+ * @private blends colors according to color components.
+ * If alpha value is less than 1, we need to enable blending
+ * on our gl context. Otherwise opaque objects need to a depthMask.
+ * @param {Number} v1 [description]
+ * @param {Number} v2 [description]
+ * @param {Number} v3 [description]
+ * @param {Number} a [description]
+ * @return {[Number]} Normalized numbers array
+ */
+p5.RendererGL.prototype._applyColorBlend = function(v1,v2,v3,a){
+ var gl = this.GL;
+ var color = this._pInst.color.apply(
+ this._pInst, arguments);
+ var colors = color._array;
+ if(colors[colors.length-1] < 1.0){
+ gl.depthMask(false);
+ gl.enable(gl.BLEND);
+ gl.blendEquation( gl.FUNC_ADD );
+ gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
+ } else {
+ gl.depthMask(true);
+ gl.disable(gl.BLEND);
+ }
+ return colors;
+};
+
+module.exports = p5;
+
+},{"../core/core":37}],82:[function(_dereq_,module,exports){
+//some of the functions are adjusted from Three.js(http://threejs.org)
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+
+/**
+ * p5 Geometry class
+ * @constructor
+ * @param {Function | Object} vertData callback function or Object
+ * containing routine(s) for vertex data generation
+ * @param {Number} [detailX] number of vertices on horizontal surface
+ * @param {Number} [detailY] number of vertices on horizontal surface
+ * @param {Function} [callback] function to call upon object instantiation.
+ *
+ */
+p5.Geometry = function
+(detailX, detailY, callback){
+ //an array containing every vertex
+ //@type [p5.Vector]
+ this.vertices = [];
+ //an array containing 1 normal per vertex
+ //@type [p5.Vector]
+ //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...]
+ this.vertexNormals = [];
+ //an array containing each three vertex indices that form a face
+ //[[0, 1, 2], [2, 1, 3], ...]
+ this.faces = [];
+ //a 2D array containing uvs for every vertex
+ //[[0.0,0.0],[1.0,0.0], ...]
+ this.uvs = [];
+ this.detailX = (detailX !== undefined) ? detailX: 1;
+ this.detailY = (detailY !== undefined) ? detailY: 1;
+ if(callback instanceof Function){
+ callback.call(this);
+ }
+ return this;
+};
+
+p5.Geometry.prototype.computeFaces = function(){
+ var sliceCount = this.detailX + 1;
+ var a, b, c, d;
+ for (var i = 0; i < this.detailY; i++){
+ for (var j = 0; j < this.detailX; j++){
+ a = i * sliceCount + j;// + offset;
+ b = i * sliceCount + j + 1;// + offset;
+ c = (i + 1)* sliceCount + j + 1;// + offset;
+ d = (i + 1)* sliceCount + j;// + offset;
+ this.faces.push([a, b, d]);
+ this.faces.push([d, b, c]);
+ }
+ }
+ return this;
+};
+
+p5.Geometry.prototype._getFaceNormal = function(faceId,vertId){
+ //This assumes that vA->vB->vC is a counter-clockwise ordering
+ var face = this.faces[faceId];
+ var vA = this.vertices[face[vertId%3]];
+ var vB = this.vertices[face[(vertId+1)%3]];
+ var vC = this.vertices[face[(vertId+2)%3]];
+ var n = p5.Vector.cross(
+ p5.Vector.sub(vB,vA),
+ p5.Vector.sub(vC,vA));
+ var sinAlpha = p5.Vector.mag(n) /
+ (p5.Vector.mag(p5.Vector.sub(vB,vA))*
+ p5.Vector.mag(p5.Vector.sub(vC,vA)));
+ n = n.normalize();
+ return n.mult(Math.asin(sinAlpha));
+};
+/**
+ * computes smooth normals per vertex as an average of each
+ * face.
+ */
+p5.Geometry.prototype.computeNormals = function (){
+ for(var v=0; v < this.vertices.length; v++){
+ var normal = new p5.Vector();
+ for(var i=0; i < this.faces.length; i++){
+ //if our face contains a given vertex
+ //calculate an average of the normals
+ //of the triangles adjacent to that vertex
+ if(this.faces[i][0] === v ||
+ this.faces[i][1] === v ||
+ this.faces[i][2] === v)
+ {
+ normal = normal.add(this._getFaceNormal(i, v));
+ }
+ }
+ normal = normal.normalize();
+ this.vertexNormals.push(normal);
+ }
+ return this;
+};
+
+/**
+ * Averages the vertex normals. Used in curved
+ * surfaces
+ * @return {p5.Geometry}
+ */
+p5.Geometry.prototype.averageNormals = function() {
+
+ for(var i = 0; i <= this.detailY; i++){
+ var offset = this.detailX + 1;
+ var temp = p5.Vector
+ .add(this.vertexNormals[i*offset],
+ this.vertexNormals[i*offset + this.detailX]);
+ temp = p5.Vector.div(temp, 2);
+ this.vertexNormals[i*offset] = temp;
+ this.vertexNormals[i*offset + this.detailX] = temp;
+ }
+ return this;
+};
+
+/**
+ * Averages pole normals. Used in spherical primitives
+ * @return {p5.Geometry}
+ */
+p5.Geometry.prototype.averagePoleNormals = function() {
+
+ //average the north pole
+ var sum = new p5.Vector(0, 0, 0);
+ for(var i = 0; i < this.detailX; i++){
+ sum.add(this.vertexNormals[i]);
+ }
+ sum = p5.Vector.div(sum, this.detailX);
+
+ for(i = 0; i < this.detailX; i++){
+ this.vertexNormals[i] = sum;
+ }
+
+ //average the south pole
+ sum = new p5.Vector(0, 0, 0);
+ for(i = this.vertices.length - 1;
+ i > this.vertices.length - 1 - this.detailX; i--){
+ sum.add(this.vertexNormals[i]);
+ }
+ sum = p5.Vector.div(sum, this.detailX);
+
+ for(i = this.vertices.length - 1;
+ i > this.vertices.length - 1 - this.detailX; i--){
+ this.vertexNormals[i] = sum;
+ }
+ return this;
+};
+
+/**
+ * Modifies all vertices to be centered within the range -100 to 100.
+ * @return {p5.Geometry}
+ */
+p5.Geometry.prototype.normalize = function() {
+ if(this.vertices.length > 0) {
+ // Find the corners of our bounding box
+ var maxPosition = this.vertices[0].copy();
+ var minPosition = this.vertices[0].copy();
+
+ for(var i = 0; i < this.vertices.length; i++) {
+ maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x);
+ minPosition.x = Math.min(minPosition.x, this.vertices[i].x);
+ maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y);
+ minPosition.y = Math.min(minPosition.y, this.vertices[i].y);
+ maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z);
+ minPosition.z = Math.min(minPosition.z, this.vertices[i].z);
+ }
+
+ var center = p5.Vector.lerp(maxPosition, minPosition, 0.5);
+ var dist = p5.Vector.sub(maxPosition, minPosition);
+ var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z);
+ var scale = 200 / longestDist;
+
+ for(i = 0; i < this.vertices.length; i++) {
+ this.vertices[i].sub(center);
+ this.vertices[i].mult(scale);
+ }
+ }
+ return this;
+};
+
+module.exports = p5.Geometry;
+
+},{"../core/core":37}],83:[function(_dereq_,module,exports){
+/**
+* @requires constants
+* @todo see methods below needing further implementation.
+* future consideration: implement SIMD optimizations
+* when browser compatibility becomes available
+* https://developer.mozilla.org/en-US/docs/Web/JavaScript/
+* Reference/Global_Objects/SIMD
+*/
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var polarGeometry = _dereq_('../math/polargeometry');
+var constants = _dereq_('../core/constants');
+var GLMAT_ARRAY_TYPE = (
+ typeof Float32Array !== 'undefined') ?
+ Float32Array : Array;
+
+/**
+ * A class to describe a 4x4 matrix
+ * for model and view matrix manipulation in the p5js webgl renderer.
+ * class p5.Matrix
+ * @constructor
+ * @param {Array} [mat4] array literal of our 4x4 matrix
+ */
+p5.Matrix = function() {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ // This is default behavior when object
+ // instantiated using createMatrix()
+ // @todo implement createMatrix() in core/math.js
+ if(args[0] instanceof p5) {
+ // save reference to p5 if passed in
+ this.p5 = args[0];
+ if(args[1] === 'mat3'){
+ this.mat3 = args[2] || new GLMAT_ARRAY_TYPE([
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ ]);
+ }
+ else {
+ this.mat4 = args[1] || new GLMAT_ARRAY_TYPE([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ ]);
+ }
+ // default behavior when object
+ // instantiated using new p5.Matrix()
+ } else {
+ if(args[0] === 'mat3'){
+ this.mat3 = args[1] || new GLMAT_ARRAY_TYPE([
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ ]);
+ }
+ else {
+ this.mat4 = args[0] || new GLMAT_ARRAY_TYPE([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ ]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Sets the x, y, and z component of the vector using two or three separate
+ * variables, the data from a p5.Matrix, or the values from a float array.
+ *
+ * @param {p5.Matrix|Array} [inMatrix] the input p5.Matrix or
+ * an Array of length 16
+ */
+p5.Matrix.prototype.set = function (inMatrix) {
+ if (inMatrix instanceof p5.Matrix) {
+ this.mat4 = inMatrix.mat4;
+ return this;
+ }
+ else if (inMatrix instanceof GLMAT_ARRAY_TYPE) {
+ this.mat4 = inMatrix;
+ return this;
+ }
+ return this;
+};
+
+/**
+ * Gets a copy of the vector, returns a p5.Matrix object.
+ *
+ * @return {p5.Matrix} the copy of the p5.Matrix object
+ */
+p5.Matrix.prototype.get = function () {
+ return new p5.Matrix(this.mat4);
+};
+
+/**
+ * return a copy of a matrix
+ * @return {p5.Matrix} the result matrix
+ */
+p5.Matrix.prototype.copy = function(){
+ var copied = new p5.Matrix();
+ copied.mat4[0] = this.mat4[0];
+ copied.mat4[1] = this.mat4[1];
+ copied.mat4[2] = this.mat4[2];
+ copied.mat4[3] = this.mat4[3];
+ copied.mat4[4] = this.mat4[4];
+ copied.mat4[5] = this.mat4[5];
+ copied.mat4[6] = this.mat4[6];
+ copied.mat4[7] = this.mat4[7];
+ copied.mat4[8] = this.mat4[8];
+ copied.mat4[9] = this.mat4[9];
+ copied.mat4[10] = this.mat4[10];
+ copied.mat4[11] = this.mat4[11];
+ copied.mat4[12] = this.mat4[12];
+ copied.mat4[13] = this.mat4[13];
+ copied.mat4[14] = this.mat4[14];
+ copied.mat4[15] = this.mat4[15];
+ return copied;
+};
+
+/**
+ * return an identity matrix
+ * @return {p5.Matrix} the result matrix
+ */
+p5.Matrix.identity = function(){
+ return new p5.Matrix();
+};
+
+/**
+ * transpose according to a given matrix
+ * @param {p5.Matrix | Typed Array} a the matrix to be based on to transpose
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.transpose = function(a){
+ var a01, a02, a03, a12, a13, a23;
+ if(a instanceof p5.Matrix){
+ a01 = a.mat4[1];
+ a02 = a.mat4[2];
+ a03 = a.mat4[3];
+ a12 = a.mat4[6];
+ a13 = a.mat4[7];
+ a23 = a.mat4[11];
+
+ this.mat4[0] = a.mat4[0];
+ this.mat4[1] = a.mat4[4];
+ this.mat4[2] = a.mat4[8];
+ this.mat4[3] = a.mat4[12];
+ this.mat4[4] = a01;
+ this.mat4[5] = a.mat4[5];
+ this.mat4[6] = a.mat4[9];
+ this.mat4[7] = a.mat4[13];
+ this.mat4[8] = a02;
+ this.mat4[9] = a12;
+ this.mat4[10] = a.mat4[10];
+ this.mat4[11] = a.mat4[14];
+ this.mat4[12] = a03;
+ this.mat4[13] = a13;
+ this.mat4[14] = a23;
+ this.mat4[15] = a.mat4[15];
+
+ }else if(a instanceof GLMAT_ARRAY_TYPE){
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a12 = a[6];
+ a13 = a[7];
+ a23 = a[11];
+
+ this.mat4[0] = a[0];
+ this.mat4[1] = a[4];
+ this.mat4[2] = a[8];
+ this.mat4[3] = a[12];
+ this.mat4[4] = a01;
+ this.mat4[5] = a[5];
+ this.mat4[6] = a[9];
+ this.mat4[7] = a[13];
+ this.mat4[8] = a02;
+ this.mat4[9] = a12;
+ this.mat4[10] = a[10];
+ this.mat4[11] = a[14];
+ this.mat4[12] = a03;
+ this.mat4[13] = a13;
+ this.mat4[14] = a23;
+ this.mat4[15] = a[15];
+ }
+ return this;
+};
+
+/**
+ * invert matrix according to a give matrix
+ * @param {p5.Matrix or Typed Array} a the matrix to be based on to invert
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.invert = function(a){
+ var a00, a01, a02, a03, a10, a11, a12, a13,
+ a20, a21, a22, a23, a30, a31, a32, a33;
+ if(a instanceof p5.Matrix){
+ a00 = a.mat4[0];
+ a01 = a.mat4[1];
+ a02 = a.mat4[2];
+ a03 = a.mat4[3];
+ a10 = a.mat4[4];
+ a11 = a.mat4[5];
+ a12 = a.mat4[6];
+ a13 = a.mat4[7];
+ a20 = a.mat4[8];
+ a21 = a.mat4[9];
+ a22 = a.mat4[10];
+ a23 = a.mat4[11];
+ a30 = a.mat4[12];
+ a31 = a.mat4[13];
+ a32 = a.mat4[14];
+ a33 = a.mat4[15];
+ }else if(a instanceof GLMAT_ARRAY_TYPE){
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11];
+ a30 = a[12];
+ a31 = a[13];
+ a32 = a[14];
+ a33 = a[15];
+ }
+ var b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ // Calculate the determinant
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 -
+ b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+
+ return this;
+};
+
+/**
+ * Inverts a 3x3 matrix
+ * @return {[type]} [description]
+ */
+p5.Matrix.prototype.invert3x3 = function (){
+ var a00 = this.mat3[0],
+ a01 = this.mat3[1],
+ a02 = this.mat3[2],
+ a10 = this.mat3[3],
+ a11 = this.mat3[4],
+ a12 = this.mat3[5],
+ a20 = this.mat3[6],
+ a21 = this.mat3[7],
+ a22 = this.mat3[8],
+ b01 = a22 * a11 - a12 * a21,
+ b11 = -a22 * a10 + a12 * a20,
+ b21 = a21 * a10 - a11 * a20,
+
+ // Calculate the determinant
+ det = a00 * b01 + a01 * b11 + a02 * b21;
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+ this.mat3[0] = b01 * det;
+ this.mat3[1] = (-a22 * a01 + a02 * a21) * det;
+ this.mat3[2] = (a12 * a01 - a02 * a11) * det;
+ this.mat3[3] = b11 * det;
+ this.mat3[4] = (a22 * a00 - a02 * a20) * det;
+ this.mat3[5] = (-a12 * a00 + a02 * a10) * det;
+ this.mat3[6] = b21 * det;
+ this.mat3[7] = (-a21 * a00 + a01 * a20) * det;
+ this.mat3[8] = (a11 * a00 - a01 * a10) * det;
+ return this;
+};
+
+/**
+ * transposes a 3x3 p5.Matrix by a mat3
+ * @param {[Number]} mat3 1-dimensional array
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.transpose3x3 = function (mat3){
+ var a01 = mat3[1], a02 = mat3[2], a12 = mat3[5];
+ this.mat3[1] = mat3[3];
+ this.mat3[2] = mat3[6];
+ this.mat3[3] = a01;
+ this.mat3[5] = mat3[7];
+ this.mat3[6] = a02;
+ this.mat3[7] = a12;
+ return this;
+};
+
+/**
+ * converts a 4x4 matrix to its 3x3 inverse tranform
+ * commonly used in MVMatrix to NMatrix conversions.
+ * @param {p5.Matrix} mat4 the matrix to be based on to invert
+ * @return {p5.Matrix} this with mat3
+ * @todo finish implementation
+ */
+p5.Matrix.prototype.inverseTranspose = function (matrix){
+ if(this.mat3 === undefined){
+ console.error('sorry, this function only works with mat3');
+ }
+ else {
+ //convert mat4 -> mat3
+ this.mat3[0] = matrix.mat4[0];
+ this.mat3[1] = matrix.mat4[1];
+ this.mat3[2] = matrix.mat4[2];
+ this.mat3[3] = matrix.mat4[4];
+ this.mat3[4] = matrix.mat4[5];
+ this.mat3[5] = matrix.mat4[6];
+ this.mat3[6] = matrix.mat4[8];
+ this.mat3[7] = matrix.mat4[9];
+ this.mat3[8] = matrix.mat4[10];
+ }
+
+ this.invert3x3().transpose3x3(this.mat3);
+ return this;
+};
+
+/**
+ * inspired by Toji's mat4 determinant
+ * @return {Number} Determinant of our 4x4 matrix
+ */
+p5.Matrix.prototype.determinant = function(){
+ var d00 = (this.mat4[0] * this.mat4[5]) - (this.mat4[1] * this.mat4[4]),
+ d01 = (this.mat4[0] * this.mat4[6]) - (this.mat4[2] * this.mat4[4]),
+ d02 = (this.mat4[0] * this.mat4[7]) - (this.mat4[3] * this.mat4[4]),
+ d03 = (this.mat4[1] * this.mat4[6]) - (this.mat4[2] * this.mat4[5]),
+ d04 = (this.mat4[1] * this.mat4[7]) - (this.mat4[3] * this.mat4[5]),
+ d05 = (this.mat4[2] * this.mat4[7]) - (this.mat4[3] * this.mat4[6]),
+ d06 = (this.mat4[8] * this.mat4[13]) - (this.mat4[9] * this.mat4[12]),
+ d07 = (this.mat4[8] * this.mat4[14]) - (this.mat4[10] * this.mat4[12]),
+ d08 = (this.mat4[8] * this.mat4[15]) - (this.mat4[11] * this.mat4[12]),
+ d09 = (this.mat4[9] * this.mat4[14]) - (this.mat4[10] * this.mat4[13]),
+ d10 = (this.mat4[9] * this.mat4[15]) - (this.mat4[11] * this.mat4[13]),
+ d11 = (this.mat4[10] * this.mat4[15]) - (this.mat4[11] * this.mat4[14]);
+
+ // Calculate the determinant
+ return d00 * d11 - d01 * d10 + d02 * d09 +
+ d03 * d08 - d04 * d07 + d05 * d06;
+};
+
+/**
+ * multiply two mat4s
+ * @param {p5.Matrix | Array} multMatrix The matrix we want to multiply by
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.mult = function(multMatrix){
+ var _dest = new GLMAT_ARRAY_TYPE(16);
+ var _src = new GLMAT_ARRAY_TYPE(16);
+
+ if(multMatrix instanceof p5.Matrix) {
+ _src = multMatrix.mat4;
+ }
+ else if(multMatrix instanceof GLMAT_ARRAY_TYPE){
+ _src = multMatrix;
+ }
+
+ // each row is used for the multiplier
+ var b0 = this.mat4[0], b1 = this.mat4[1],
+ b2 = this.mat4[2], b3 = this.mat4[3];
+ _dest[0] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
+ _dest[1] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
+ _dest[2] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
+ _dest[3] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
+
+ b0 = this.mat4[4];
+ b1 = this.mat4[5];
+ b2 = this.mat4[6];
+ b3 = this.mat4[7];
+ _dest[4] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
+ _dest[5] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
+ _dest[6] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
+ _dest[7] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
+
+ b0 = this.mat4[8];
+ b1 = this.mat4[9];
+ b2 = this.mat4[10];
+ b3 = this.mat4[11];
+ _dest[8] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
+ _dest[9] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
+ _dest[10] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
+ _dest[11] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
+
+ b0 = this.mat4[12];
+ b1 = this.mat4[13];
+ b2 = this.mat4[14];
+ b3 = this.mat4[15];
+ _dest[12] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
+ _dest[13] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
+ _dest[14] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
+ _dest[15] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
+
+ this.mat4 = _dest;
+
+ return this;
+};
+
+/**
+ * scales a p5.Matrix by scalars or a vector
+ * @param {p5.Vector | Array }
+ * vector to scale by
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.scale = function() {
+ var x,y,z;
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ //if our 1st arg is a type p5.Vector
+ if (args[0] instanceof p5.Vector){
+ x = args[0].x;
+ y = args[0].y;
+ z = args[0].z;
+ }
+ //otherwise if it's an array
+ else if (args[0] instanceof Array){
+ x = args[0][0];
+ y = args[0][1];
+ z = args[0][2];
+ }
+ var _dest = new GLMAT_ARRAY_TYPE(16);
+ _dest[0] = this.mat4[0] * x;
+ _dest[1] = this.mat4[1] * x;
+ _dest[2] = this.mat4[2] * x;
+ _dest[3] = this.mat4[3] * x;
+ _dest[4] = this.mat4[4] * y;
+ _dest[5] = this.mat4[5] * y;
+ _dest[6] = this.mat4[6] * y;
+ _dest[7] = this.mat4[7] * y;
+ _dest[8] = this.mat4[8] * z;
+ _dest[9] = this.mat4[9] * z;
+ _dest[10] = this.mat4[10] * z;
+ _dest[11] = this.mat4[11] * z;
+ _dest[12] = this.mat4[12];
+ _dest[13] = this.mat4[13];
+ _dest[14] = this.mat4[14];
+ _dest[15] = this.mat4[15];
+
+ this.mat4 = _dest;
+ return this;
+};
+
+/**
+ * rotate our Matrix around an axis by the given angle.
+ * @param {Number} a The angle of rotation in radians
+ * @param {p5.Vector | Array} axis the axis(es) to rotate around
+ * @return {p5.Matrix} this
+ * inspired by Toji's gl-matrix lib, mat4 rotation
+ */
+p5.Matrix.prototype.rotate = function(a, axis){
+ var x, y, z, _a, len;
+
+ if (this.p5) {
+ if (this.p5._angleMode === constants.DEGREES) {
+ _a = polarGeometry.degreesToRadians(a);
+ }
+ }
+ else {
+ _a = a;
+ }
+ if (axis instanceof p5.Vector) {
+ x = axis.x;
+ y = axis.y;
+ z = axis.z;
+ }
+ else if (axis instanceof Array) {
+ x = axis[0];
+ y = axis[1];
+ z = axis[2];
+ }
+
+ len = Math.sqrt(x * x + y * y + z * z);
+ x *= (1/len);
+ y *= (1/len);
+ z *= (1/len);
+
+ var a00 = this.mat4[0];
+ var a01 = this.mat4[1];
+ var a02 = this.mat4[2];
+ var a03 = this.mat4[3];
+ var a10 = this.mat4[4];
+ var a11 = this.mat4[5];
+ var a12 = this.mat4[6];
+ var a13 = this.mat4[7];
+ var a20 = this.mat4[8];
+ var a21 = this.mat4[9];
+ var a22 = this.mat4[10];
+ var a23 = this.mat4[11];
+
+ //sin,cos, and tan of respective angle
+ var sA = Math.sin(_a);
+ var cA = Math.cos(_a);
+ var tA = 1 - cA;
+ // Construct the elements of the rotation matrix
+ var b00 = x * x * tA + cA;
+ var b01 = y * x * tA + z * sA;
+ var b02 = z * x * tA - y * sA;
+ var b10 = x * y * tA - z * sA;
+ var b11 = y * y * tA + cA;
+ var b12 = z * y * tA + x * sA;
+ var b20 = x * z * tA + y * sA;
+ var b21 = y * z * tA - x * sA;
+ var b22 = z * z * tA + cA;
+
+ // rotation-specific matrix multiplication
+ this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ return this;
+};
+
+/**
+ * @todo finish implementing this method!
+ * translates
+ * @param {Array} v vector to translate by
+ * @return {p5.Matrix} this
+ */
+p5.Matrix.prototype.translate = function(v){
+ var x = v[0],
+ y = v[1],
+ z = v[2] || 0;
+ this.mat4[12] =
+ this.mat4[0] * x +this.mat4[4] * y +this.mat4[8] * z +this.mat4[12];
+ this.mat4[13] =
+ this.mat4[1] * x +this.mat4[5] * y +this.mat4[9] * z +this.mat4[13];
+ this.mat4[14] =
+ this.mat4[2] * x +this.mat4[6] * y +this.mat4[10] * z +this.mat4[14];
+ this.mat4[15] =
+ this.mat4[3] * x +this.mat4[7] * y +this.mat4[11] * z +this.mat4[15];
+};
+
+p5.Matrix.prototype.rotateX = function(a){
+ this.rotate(a, [1,0,0]);
+};
+p5.Matrix.prototype.rotateY = function(a){
+ this.rotate(a, [0,1,0]);
+};
+p5.Matrix.prototype.rotateZ = function(a){
+ this.rotate(a, [0,0,1]);
+};
+
+/**
+ * sets the perspective matrix
+ * @param {Number} fovy [description]
+ * @param {Number} aspect [description]
+ * @param {Number} near near clipping plane
+ * @param {Number} far far clipping plane
+ * @return {void}
+ */
+p5.Matrix.prototype.perspective = function(fovy,aspect,near,far){
+
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf = 1 / (near - far);
+
+ this.mat4[0] = f / aspect;
+ this.mat4[1] = 0;
+ this.mat4[2] = 0;
+ this.mat4[3] = 0;
+ this.mat4[4] = 0;
+ this.mat4[5] = f;
+ this.mat4[6] = 0;
+ this.mat4[7] = 0;
+ this.mat4[8] = 0;
+ this.mat4[9] = 0;
+ this.mat4[10] = (far + near) * nf;
+ this.mat4[11] = -1;
+ this.mat4[12] = 0;
+ this.mat4[13] = 0;
+ this.mat4[14] = (2 * far * near) * nf;
+ this.mat4[15] = 0;
+
+ return this;
+
+};
+
+/**
+ * sets the ortho matrix
+ * @param {Number} left [description]
+ * @param {Number} right [description]
+ * @param {Number} bottom [description]
+ * @param {Number} top [description]
+ * @param {Number} near near clipping plane
+ * @param {Number} far far clipping plane
+ * @return {void}
+ */
+p5.Matrix.prototype.ortho = function(left,right,bottom,top,near,far){
+
+ var lr = 1 / (left - right),
+ bt = 1 / (bottom - top),
+ nf = 1 / (near - far);
+ this.mat4[0] = -2 * lr;
+ this.mat4[1] = 0;
+ this.mat4[2] = 0;
+ this.mat4[3] = 0;
+ this.mat4[4] = 0;
+ this.mat4[5] = -2 * bt;
+ this.mat4[6] = 0;
+ this.mat4[7] = 0;
+ this.mat4[8] = 0;
+ this.mat4[9] = 0;
+ this.mat4[10] = 2 * nf;
+ this.mat4[11] = 0;
+ this.mat4[12] = (left + right) * lr;
+ this.mat4[13] = (top + bottom) * bt;
+ this.mat4[14] = (far + near) * nf;
+ this.mat4[15] = 1;
+
+ return this;
+};
+
+/**
+ * PRIVATE
+ */
+// matrix methods adapted from:
+// https://developer.mozilla.org/en-US/docs/Web/WebGL/
+// gluPerspective
+//
+// function _makePerspective(fovy, aspect, znear, zfar){
+// var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
+// var ymin = -ymax;
+// var xmin = ymin * aspect;
+// var xmax = ymax * aspect;
+// return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
+// }
+
+////
+//// glFrustum
+////
+//function _makeFrustum(left, right, bottom, top, znear, zfar){
+// var X = 2*znear/(right-left);
+// var Y = 2*znear/(top-bottom);
+// var A = (right+left)/(right-left);
+// var B = (top+bottom)/(top-bottom);
+// var C = -(zfar+znear)/(zfar-znear);
+// var D = -2*zfar*znear/(zfar-znear);
+// var frustrumMatrix =[
+// X, 0, A, 0,
+// 0, Y, B, 0,
+// 0, 0, C, D,
+// 0, 0, -1, 0
+//];
+//return frustrumMatrix;
+// }
+
+// function _setMVPMatrices(){
+////an identity matrix
+////@TODO use the p5.Matrix class to abstract away our MV matrices and
+///other math
+//var _mvMatrix =
+//[
+// 1.0,0.0,0.0,0.0,
+// 0.0,1.0,0.0,0.0,
+// 0.0,0.0,1.0,0.0,
+// 0.0,0.0,0.0,1.0
+//];
+
+module.exports = p5.Matrix;
+
+},{"../core/constants":36,"../core/core":37,"../math/polargeometry":67}],84:[function(_dereq_,module,exports){
+/**
+ * Welcome to RendererGL Immediate Mode.
+ * Immediate mode is used for drawing custom shapes
+ * from a set of vertices. Immediate Mode is activated
+ * when you call beginShape() & de-activated when you call endShape().
+ * Immediate mode is a style of programming borrowed
+ * from OpenGL's (now-deprecated) immediate mode.
+ * It differs from p5.js' default, Retained Mode, which caches
+ * geometries and buffers on the CPU to reduce the number of webgl
+ * draw calls. Retained mode is more efficient & performative,
+ * however, Immediate Mode is useful for sketching quick
+ * geometric ideas.
+ */
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var constants = _dereq_('../core/constants');
+
+/**
+ * Begin shape drawing. This is a helpful way of generating
+ * custom shapes quickly. However in WEBGL mode, application
+ * performance will likely drop as a result of too many calls to
+ * beginShape() / endShape(). As a high performance alternative,
+ * please use p5.js geometry primitives.
+ * @param {Number} mode webgl primitives mode. beginShape supports the
+ * following modes:
+ * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
+ * TRIANGLE_STRIP,and TRIANGLE_FAN.
+ * @return {[type]} [description]
+ */
+p5.RendererGL.prototype.beginShape = function(mode){
+ //default shape mode is line_strip
+ this.immediateMode.shapeMode = (mode !== undefined ) ?
+ mode : constants.LINE_STRIP;
+ //if we haven't yet initialized our
+ //immediateMode vertices & buffers, create them now!
+ if(this.immediateMode.vertexPositions === undefined){
+ this.immediateMode.vertexPositions = [];
+ this.immediateMode.vertexColors = [];
+ this.immediateMode.vertexBuffer = this.GL.createBuffer();
+ this.immediateMode.colorBuffer = this.GL.createBuffer();
+ } else {
+ this.immediateMode.vertexPositions.length = 0;
+ this.immediateMode.vertexColors.length = 0;
+ }
+ this.isImmediateDrawing = true;
+ return this;
+};
+/**
+ * adds a vertex to be drawn in a custom Shape.
+ * @param {Number} x x-coordinate of vertex
+ * @param {Number} y y-coordinate of vertex
+ * @param {Number} z z-coordinate of vertex
+ * @return {p5.RendererGL} [description]
+ * @TODO implement handling of p5.Vector args
+ */
+p5.RendererGL.prototype.vertex = function(x, y, z){
+ this.immediateMode.vertexPositions.push(x, y, z);
+ var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
+ this.immediateMode.vertexColors.push(
+ vertexColor[0],
+ vertexColor[1],
+ vertexColor[2],
+ vertexColor[3]);
+ return this;
+};
+
+/**
+ * End shape drawing and render vertices to screen.
+ * @return {p5.RendererGL} [description]
+ */
+p5.RendererGL.prototype.endShape =
+function(mode, isCurve, isBezier,isQuadratic, isContour, shapeKind){
+ var gl = this.GL;
+ this._bindImmediateBuffers(
+ this.immediateMode.vertexPositions,
+ this.immediateMode.vertexColors);
+ if(mode){
+ if(this.drawMode === 'fill'){
+ switch(this.immediateMode.shapeMode){
+ case constants.LINE_STRIP:
+ this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
+ break;
+ case constants.LINES:
+ this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
+ break;
+ case constants.TRIANGLES:
+ this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
+ break;
+ }
+ } else {
+ switch(this.immediateMode.shapeMode){
+ case constants.LINE_STRIP:
+ this.immediateMode.shapeMode = constants.LINE_LOOP;
+ break;
+ case constants.LINES:
+ this.immediateMode.shapeMode = constants.LINE_LOOP;
+ break;
+ }
+ }
+ }
+ //QUADS & QUAD_STRIP are not supported primitives modes
+ //in webgl.
+ if(this.immediateMode.shapeMode === constants.QUADS ||
+ this.immediateMode.shapeMode === constants.QUAD_STRIP){
+ throw new Error('sorry, ' + this.immediateMode.shapeMode+
+ ' not yet implemented in webgl mode.');
+ }
+ else {
+ gl.enable(gl.BLEND);
+ gl.drawArrays(this.immediateMode.shapeMode, 0,
+ this.immediateMode.vertexPositions.length / 3);
+ }
+ //clear out our vertexPositions & colors arrays
+ //after rendering
+ this.immediateMode.vertexPositions.length = 0;
+ this.immediateMode.vertexColors.length = 0;
+ this.isImmediateDrawing = false;
+ return this;
+};
+/**
+ * Bind immediateMode buffers to data,
+ * then draw gl arrays
+ * @param {Array} vertices Numbers array representing
+ * vertex positions
+ * @return {p5.RendererGL}
+ */
+p5.RendererGL.prototype._bindImmediateBuffers = function(vertices, colors){
+ this._setDefaultCamera();
+ var gl = this.GL;
+ var shaderKey = this._getCurShaderId();
+ var shaderProgram = this.mHash[shaderKey];
+ //vertex position Attribute
+ shaderProgram.vertexPositionAttribute =
+ gl.getAttribLocation(shaderProgram, 'aPosition');
+ gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.immediateMode.vertexBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER, new Float32Array(vertices), gl.DYNAMIC_DRAW);
+ gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
+ 3, gl.FLOAT, false, 0, 0);
+
+ shaderProgram.vertexColorAttribute =
+ gl.getAttribLocation(shaderProgram, 'aVertexColor');
+ gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.immediateMode.colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER,
+ new Float32Array(colors),gl.DYNAMIC_DRAW);
+ gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,
+ 4, gl.FLOAT, false, 0, 0);
+ //matrix
+ this._setMatrixUniforms(shaderKey);
+ //@todo implement in all shaders (not just immediateVert)
+ //set our default point size
+ // this._setUniform1f(shaderKey,
+ // 'uPointSize',
+ // this.pointSize);
+ return this;
+};
+
+//////////////////////////////////////////////
+// COLOR
+//////////////////////////////////////////////
+
+p5.RendererGL.prototype._getColorVertexShader = function(){
+ var gl = this.GL;
+ var mId = 'immediateVert|vertexColorFrag';
+ var shaderProgram;
+
+ if(!this.materialInHash(mId)){
+ shaderProgram =
+ this._initShaders('immediateVert', 'vertexColorFrag', true);
+ this.mHash[mId] = shaderProgram;
+ shaderProgram.vertexColorAttribute =
+ gl.getAttribLocation(shaderProgram, 'aVertexColor');
+ gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
+ }else{
+ shaderProgram = this.mHash[mId];
+ }
+ return shaderProgram;
+};
+
+module.exports = p5.RendererGL;
+},{"../core/constants":36,"../core/core":37}],85:[function(_dereq_,module,exports){
+//Retained Mode. The default mode for rendering 3D primitives
+//in WEBGL.
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var hashCount = 0;
+/**
+ * _initBufferDefaults
+ * @description initializes buffer defaults. runs each time a new geometry is
+ * registered
+ * @param {String} gId key of the geometry object
+ */
+p5.RendererGL.prototype._initBufferDefaults = function(gId) {
+ //@TODO remove this limit on hashes in gHash
+ hashCount ++;
+ if(hashCount > 1000){
+ var key = Object.keys(this.gHash)[0];
+ delete this.gHash[key];
+ hashCount --;
+ }
+
+ var gl = this.GL;
+ //create a new entry in our gHash
+ this.gHash[gId] = {};
+ this.gHash[gId].vertexBuffer = gl.createBuffer();
+ this.gHash[gId].normalBuffer = gl.createBuffer();
+ this.gHash[gId].uvBuffer = gl.createBuffer();
+ this.gHash[gId].indexBuffer = gl.createBuffer();
+};
+/**
+ * createBuffers description
+ * @param {String} gId key of the geometry object
+ * @param {p5.Geometry} obj contains geometry data
+ */
+p5.RendererGL.prototype.createBuffers = function(gId, obj) {
+ var gl = this.GL;
+ this._setDefaultCamera();
+ //initialize the gl buffers for our geom groups
+ this._initBufferDefaults(gId);
+ //return the current shaderProgram from our material hash
+ var shaderProgram = this.mHash[this._getCurShaderId()];
+ //@todo rename "numberOfItems" property to something more descriptive
+ //we mult the num geom faces by 3
+ this.gHash[gId].numberOfItems = obj.faces.length * 3;
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].vertexBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array( vToNArray(obj.vertices) ),
+ gl.STATIC_DRAW);
+ //vertex position
+ shaderProgram.vertexPositionAttribute =
+ gl.getAttribLocation(shaderProgram, 'aPosition');
+ gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
+
+ gl.vertexAttribPointer(
+ shaderProgram.vertexPositionAttribute,
+ 3, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].normalBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array( vToNArray(obj.vertexNormals) ),
+ gl.STATIC_DRAW);
+ //vertex normal
+ shaderProgram.vertexNormalAttribute =
+ gl.getAttribLocation(shaderProgram, 'aNormal');
+ gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
+
+ gl.vertexAttribPointer(
+ shaderProgram.vertexNormalAttribute,
+ 3, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].uvBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array( flatten(obj.uvs) ),
+ gl.STATIC_DRAW);
+ //texture coordinate Attribute
+ shaderProgram.textureCoordAttribute =
+ gl.getAttribLocation(shaderProgram, 'aTexCoord');
+ gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
+ gl.vertexAttribPointer(
+ shaderProgram.textureCoordAttribute,
+ 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.gHash[gId].indexBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint16Array( flatten(obj.faces) ),
+ gl.STATIC_DRAW);
+};
+
+/**
+ * Draws buffers given a geometry key ID
+ * @param {String} gId ID in our geom hash
+ * @return {p5.RendererGL} this
+ */
+p5.RendererGL.prototype.drawBuffers = function(gId) {
+ this._setDefaultCamera();
+ var gl = this.GL;
+ var shaderKey = this._getCurShaderId();
+ var shaderProgram = this.mHash[shaderKey];
+ //vertex position buffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].vertexBuffer);
+ gl.vertexAttribPointer(
+ shaderProgram.vertexPositionAttribute,
+ 3, gl.FLOAT, false, 0, 0);
+ //normal buffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].normalBuffer);
+ gl.vertexAttribPointer(
+ shaderProgram.vertexNormalAttribute,
+ 3, gl.FLOAT, false, 0, 0);
+ // uv buffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].uvBuffer);
+ gl.vertexAttribPointer(
+ shaderProgram.textureCoordAttribute,
+ 2, gl.FLOAT, false, 0, 0);
+ //vertex index buffer
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.gHash[gId].indexBuffer);
+ this._setMatrixUniforms(shaderKey);
+ gl.drawElements(
+ gl.TRIANGLES, this.gHash[gId].numberOfItems,
+ gl.UNSIGNED_SHORT, 0);
+ return this;
+};
+///////////////////////////////
+//// UTILITY FUNCTIONS
+//////////////////////////////
+/**
+ * turn a two dimensional array into one dimensional array
+ * @param {Array} arr 2-dimensional array
+ * @return {Array} 1-dimensional array
+ * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6]
+ */
+function flatten(arr){
+ if (arr.length>0){
+ return arr.reduce(function(a, b){
+ return a.concat(b);
+ });
+ } else {
+ return [];
+ }
+}
+
+/**
+ * turn a p5.Vector Array into a one dimensional number array
+ * @param {Array} arr an array of p5.Vector
+ * @return {Array]} a one dimensional array of numbers
+ * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] ->
+ * [1, 2, 3, 4, 5, 6]
+ */
+function vToNArray(arr){
+ return flatten(arr.map(function(item){
+ return [item.x, item.y, item.z];
+ }));
+}
+module.exports = p5.RendererGL;
+
+},{"../core/core":37}],86:[function(_dereq_,module,exports){
+'use strict';
+
+var p5 = _dereq_('../core/core');
+var shader = _dereq_('./shader');
+_dereq_('../core/p5.Renderer');
+_dereq_('./p5.Matrix');
+var uMVMatrixStack = [];
+
+//@TODO should implement public method
+//to override these attributes
+var attributes = {
+ alpha: true,
+ depth: true,
+ stencil: true,
+ antialias: false,
+ premultipliedAlpha: false,
+ preserveDrawingBuffer: false
+};
+
+/**
+ * @class p5.RendererGL
+ * @constructor
+ * @extends p5.Renderer
+ * 3D graphics class.
+ * @todo extend class to include public method for offscreen
+ * rendering (FBO).
+ *
+ */
+p5.RendererGL = function(elt, pInst, isMainCanvas) {
+ p5.Renderer.call(this, elt, pInst, isMainCanvas);
+ this._initContext();
+
+ this.isP3D = true; //lets us know we're in 3d mode
+ this.GL = this.drawingContext;
+ //lights
+ this.ambientLightCount = 0;
+ this.directionalLightCount = 0;
+ this.pointLightCount = 0;
+ //camera
+ this._curCamera = null;
+
+ /**
+ * model view, projection, & normal
+ * matrices
+ */
+ this.uMVMatrix = new p5.Matrix();
+ this.uPMatrix = new p5.Matrix();
+ this.uNMatrix = new p5.Matrix('mat3');
+ //Geometry & Material hashes
+ this.gHash = {};
+ this.mHash = {};
+ //Imediate Mode
+ //default drawing is done in Retained Mode
+ this.isImmediateDrawing = false;
+ this.immediateMode = {};
+ this.curFillColor = [0.5,0.5,0.5,1.0];
+ this.curStrokeColor = [0.5,0.5,0.5,1.0];
+ this.pointSize = 5.0;//default point/stroke
+ return this;
+};
+
+p5.RendererGL.prototype = Object.create(p5.Renderer.prototype);
+
+//////////////////////////////////////////////
+// Setting
+//////////////////////////////////////////////
+
+p5.RendererGL.prototype._initContext = function() {
+ try {
+ this.drawingContext = this.canvas.getContext('webgl', attributes) ||
+ this.canvas.getContext('experimental-webgl', attributes);
+ if (this.drawingContext === null) {
+ throw new Error('Error creating webgl context');
+ } else {
+ console.log('p5.RendererGL: enabled webgl context');
+ var gl = this.drawingContext;
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LEQUAL);
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ }
+ } catch (er) {
+ throw new Error(er);
+ }
+};
+//detect if user didn't set the camera
+//then call this function below
+p5.RendererGL.prototype._setDefaultCamera = function(){
+ if(this._curCamera === null){
+ var _w = this.width;
+ var _h = this.height;
+ this.uPMatrix = p5.Matrix.identity();
+ var cameraZ = (this.height / 2) / Math.tan(Math.PI * 30 / 180);
+ this.uPMatrix.perspective(60 / 180 * Math.PI, _w / _h,
+ cameraZ * 0.1, cameraZ * 10);
+ this._curCamera = 'default';
+ }
+};
+
+p5.RendererGL.prototype._update = function() {
+ this.uMVMatrix = p5.Matrix.identity();
+ this.translate(0, 0, -(this.height / 2) / Math.tan(Math.PI * 30 / 180));
+ this.ambientLightCount = 0;
+ this.directionalLightCount = 0;
+ this.pointLightCount = 0;
+};
+
+/**
+ * [background description]
+ * @return {[type]} [description]
+ */
+p5.RendererGL.prototype.background = function() {
+ var gl = this.GL;
+ var _col = this._pInst.color.apply(this._pInst, arguments);
+ var _r = (_col.levels[0]) / 255;
+ var _g = (_col.levels[1]) / 255;
+ var _b = (_col.levels[2]) / 255;
+ var _a = (_col.levels[3]) / 255;
+ gl.clearColor(_r, _g, _b, _a);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+};
+
+//@TODO implement this
+// p5.RendererGL.prototype.clear = function() {
+//@TODO
+// };
+
+//////////////////////////////////////////////
+// SHADER
+//////////////////////////////////////////////
+
+/**
+ * [_initShaders description]
+ * @param {string} vertId [description]
+ * @param {string} fragId [description]
+ * @return {[type]} [description]
+ */
+p5.RendererGL.prototype._initShaders =
+function(vertId, fragId, isImmediateMode) {
+ var gl = this.GL;
+ //set up our default shaders by:
+ // 1. create the shader,
+ // 2. load the shader source,
+ // 3. compile the shader
+ var _vertShader = gl.createShader(gl.VERTEX_SHADER);
+ //load in our default vertex shader
+ gl.shaderSource(_vertShader, shader[vertId]);
+ gl.compileShader(_vertShader);
+ // if our vertex shader failed compilation?
+ if (!gl.getShaderParameter(_vertShader, gl.COMPILE_STATUS)) {
+ alert('Yikes! An error occurred compiling the shaders:' +
+ gl.getShaderInfoLog(_vertShader));
+ return null;
+ }
+
+ var _fragShader = gl.createShader(gl.FRAGMENT_SHADER);
+ //load in our material frag shader
+ gl.shaderSource(_fragShader, shader[fragId]);
+ gl.compileShader(_fragShader);
+ // if our frag shader failed compilation?
+ if (!gl.getShaderParameter(_fragShader, gl.COMPILE_STATUS)) {
+ alert('Darn! An error occurred compiling the shaders:' +
+ gl.getShaderInfoLog(_fragShader));
+ return null;
+ }
+
+ var shaderProgram = gl.createProgram();
+ gl.attachShader(shaderProgram, _vertShader);
+ gl.attachShader(shaderProgram, _fragShader);
+ gl.linkProgram(shaderProgram);
+ if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
+ alert('Snap! Error linking shader program');
+ }
+ //END SHADERS SETUP
+
+ this._getLocation(shaderProgram, isImmediateMode);
+
+ return shaderProgram;
+};
+
+p5.RendererGL.prototype._getLocation =
+function(shaderProgram, isImmediateMode) {
+ var gl = this.GL;
+ gl.useProgram(shaderProgram);
+
+ //projection Matrix uniform
+ shaderProgram.uPMatrixUniform =
+ gl.getUniformLocation(shaderProgram, 'uProjectionMatrix');
+ //model view Matrix uniform
+ shaderProgram.uMVMatrixUniform =
+ gl.getUniformLocation(shaderProgram, 'uModelViewMatrix');
+
+ //@TODO: figure out a better way instead of if statement
+ if(isImmediateMode === undefined){
+ //normal Matrix uniform
+ shaderProgram.uNMatrixUniform =
+ gl.getUniformLocation(shaderProgram, 'uNormalMatrix');
+
+ shaderProgram.samplerUniform =
+ gl.getUniformLocation(shaderProgram, 'uSampler');
+ }
+};
+
+/**
+ * Sets a shader uniform given a shaderProgram and uniform string
+ * @param {String} shaderKey key to material Hash.
+ * @param {String} uniform location in shader.
+ * @param { Number} data data to bind uniform. Float data type.
+ * @todo currently this function sets uniform1f data.
+ * Should generalize function to accept any uniform
+ * data type.
+ */
+p5.RendererGL.prototype._setUniform1f = function(shaderKey,uniform,data)
+{
+ var gl = this.GL;
+ var shaderProgram = this.mHash[shaderKey];
+ gl.useProgram(shaderProgram);
+ shaderProgram[uniform] = gl.getUniformLocation(shaderProgram, uniform);
+ gl.uniform1f(shaderProgram[uniform], data);
+ return this;
+};
+
+p5.RendererGL.prototype._setMatrixUniforms = function(shaderKey) {
+ var gl = this.GL;
+ var shaderProgram = this.mHash[shaderKey];
+
+ gl.useProgram(shaderProgram);
+
+ gl.uniformMatrix4fv(
+ shaderProgram.uPMatrixUniform,
+ false, this.uPMatrix.mat4);
+
+ gl.uniformMatrix4fv(
+ shaderProgram.uMVMatrixUniform,
+ false, this.uMVMatrix.mat4);
+
+ this.uNMatrix.inverseTranspose(this.uMVMatrix);
+
+ gl.uniformMatrix3fv(
+ shaderProgram.uNMatrixUniform,
+ false, this.uNMatrix.mat3);
+};
+//////////////////////////////////////////////
+// GET CURRENT | for shader and color
+//////////////////////////////////////////////
+p5.RendererGL.prototype._getShader = function(vertId, fragId, isImmediateMode) {
+ var mId = vertId + '|' + fragId;
+ //create it and put it into hashTable
+ if(!this.materialInHash(mId)){
+ var shaderProgram = this._initShaders(vertId, fragId, isImmediateMode);
+ this.mHash[mId] = shaderProgram;
+ }
+ this.curShaderId = mId;
+
+ return this.mHash[this.curShaderId];
+};
+
+p5.RendererGL.prototype._getCurShaderId = function(){
+ //if the shader ID is not yet defined
+ var mId, shaderProgram;
+ if(this.drawMode !== 'fill' && this.curShaderId === undefined){
+ //default shader: normalMaterial()
+ mId = 'normalVert|normalFrag';
+ shaderProgram = this._initShaders('normalVert', 'normalFrag');
+ this.mHash[mId] = shaderProgram;
+ this.curShaderId = mId;
+ } else if(this.isImmediateDrawing && this.drawMode === 'fill'){
+ mId = 'immediateVert|vertexColorFrag';
+ shaderProgram = this._initShaders('immediateVert', 'vertexColorFrag');
+ this.mHash[mId] = shaderProgram;
+ this.curShaderId = mId;
+ }
+ return this.curShaderId;
+};
+
+//////////////////////////////////////////////
+// COLOR
+//////////////////////////////////////////////
+/**
+ * Basic fill material for geometry with a given color
+ * @method fill
+ * @param {Number|Array|String|p5.Color} v1 gray value,
+ * red or hue value (depending on the current color mode),
+ * or color Array, or CSS color string
+ * @param {Number} [v2] optional: green or saturation value
+ * @param {Number} [v3] optional: blue or brightness value
+ * @param {Number} [a] optional: opacity
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(0);
+ * fill(250, 0, 0);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * rotateZ(frameCount * 0.01);
+ * box(200, 200, 200);
+ * }
+ *
+ *
+ *
+ * @alt
+ * red canvas
+ *
+ */
+p5.RendererGL.prototype.fill = function(v1, v2, v3, a) {
+ var gl = this.GL;
+ var shaderProgram;
+ //see material.js for more info on color blending in webgl
+ var colors = this._applyColorBlend.apply(this, arguments);
+ this.curFillColor = colors;
+ this.drawMode = 'fill';
+ if(this.isImmediateDrawing){
+ shaderProgram =
+ this._getShader('immediateVert','vertexColorFrag');
+ gl.useProgram(shaderProgram);
+ } else {
+ shaderProgram =
+ this._getShader('normalVert', 'basicFrag');
+ gl.useProgram(shaderProgram);
+ //RetainedMode uses a webgl uniform to pass color vals
+ //in ImmediateMode, we want access to each vertex so therefore
+ //we cannot use a uniform.
+ shaderProgram.uMaterialColor = gl.getUniformLocation(
+ shaderProgram, 'uMaterialColor' );
+ gl.uniform4f( shaderProgram.uMaterialColor,
+ colors[0],
+ colors[1],
+ colors[2],
+ colors[3]);
+ }
+ return this;
+};
+p5.RendererGL.prototype.stroke = function(r, g, b, a) {
+ var color = this._pInst.color.apply(this._pInst, arguments);
+ var colorNormalized = color._array;
+ this.curStrokeColor = colorNormalized;
+ this.drawMode = 'stroke';
+ return this;
+};
+
+//@TODO
+p5.RendererGL.prototype._strokeCheck = function(){
+ if(this.drawMode === 'stroke'){
+ throw new Error(
+ 'stroke for shapes in 3D not yet implemented, use fill for now :('
+ );
+ }
+};
+
+/**
+ * [strokeWeight description]
+ * @param {Number} pointSize stroke point size
+ * @return {[type]} [description]
+ * @todo strokeWeight currently works on points only.
+ * implement on all wireframes and strokes.
+ */
+p5.RendererGL.prototype.strokeWeight = function(pointSize) {
+ this.pointSize = pointSize;
+ return this;
+};
+//////////////////////////////////////////////
+// HASH | for material and geometry
+//////////////////////////////////////////////
+
+p5.RendererGL.prototype.geometryInHash = function(gId){
+ return this.gHash[gId] !== undefined;
+};
+
+p5.RendererGL.prototype.materialInHash = function(mId){
+ return this.mHash[mId] !== undefined;
+};
+
+/**
+ * [resize description]
+ * @param {[type]} w [description]
+ * @param {[tyoe]} h [description]
+ * @return {[type]} [description]
+ */
+p5.RendererGL.prototype.resize = function(w,h) {
+ var gl = this.GL;
+ p5.Renderer.prototype.resize.call(this, w, h);
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ // If we're using the default camera, update the aspect ratio
+ if(this._curCamera === 'default') {
+ this._curCamera = null;
+ this._setDefaultCamera();
+ }
+};
+
+/**
+ * clears color and depth buffers
+ * with r,g,b,a
+ * @param {Number} r normalized red val.
+ * @param {Number} g normalized green val.
+ * @param {Number} b normalized blue val.
+ * @param {Number} a normalized alpha val.
+ */
+p5.RendererGL.prototype.clear = function() {
+ var gl = this.GL;
+ gl.clearColor(arguments[0],
+ arguments[1],
+ arguments[2],
+ arguments[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+};
+
+/**
+ * [translate description]
+ * @param {[type]} x [description]
+ * @param {[type]} y [description]
+ * @param {[type]} z [description]
+ * @return {[type]} [description]
+ * @todo implement handle for components or vector as args
+ */
+p5.RendererGL.prototype.translate = function(x, y, z) {
+ this.uMVMatrix.translate([x,-y,z]);
+ return this;
+};
+
+/**
+ * Scales the Model View Matrix by a vector
+ * @param {Number | p5.Vector | Array} x [description]
+ * @param {Number} [y] y-axis scalar
+ * @param {Number} [z] z-axis scalar
+ * @return {this} [description]
+ */
+p5.RendererGL.prototype.scale = function(x,y,z) {
+ this.uMVMatrix.scale([x,y,z]);
+ return this;
+};
+
+p5.RendererGL.prototype.rotate = function(rad, axis){
+ this.uMVMatrix.rotate(rad, axis);
+ return this;
+};
+
+p5.RendererGL.prototype.rotateX = function(rad) {
+ this.rotate(rad, [1,0,0]);
+ return this;
+};
+
+p5.RendererGL.prototype.rotateY = function(rad) {
+ this.rotate(rad, [0,1,0]);
+ return this;
+};
+
+p5.RendererGL.prototype.rotateZ = function(rad) {
+ this.rotate(rad, [0,0,1]);
+ return this;
+};
+
+/**
+ * pushes a copy of the model view matrix onto the
+ * MV Matrix stack.
+ */
+p5.RendererGL.prototype.push = function() {
+ uMVMatrixStack.push(this.uMVMatrix.copy());
+};
+
+/**
+ * [pop description]
+ * @return {[type]} [description]
+ */
+p5.RendererGL.prototype.pop = function() {
+ if (uMVMatrixStack.length === 0) {
+ throw new Error('Invalid popMatrix!');
+ }
+ this.uMVMatrix = uMVMatrixStack.pop();
+};
+
+p5.RendererGL.prototype.resetMatrix = function() {
+ this.uMVMatrix = p5.Matrix.identity();
+ this.translate(0, 0, -800);
+ return this;
+};
+
+// Text/Typography
+// @TODO:
+p5.RendererGL.prototype._applyTextProperties = function() {
+ //@TODO finish implementation
+ console.error('text commands not yet implemented in webgl');
+};
+module.exports = p5.RendererGL;
+
+},{"../core/core":37,"../core/p5.Renderer":43,"./p5.Matrix":83,"./shader":88}],87:[function(_dereq_,module,exports){
+/**
+ * @module Shape
+ * @submodule 3D Primitives
+ * @for p5
+ * @requires core
+ * @requires p5.Geometry
+ */
+
+'use strict';
+
+var p5 = _dereq_('../core/core');
+_dereq_('./p5.Geometry');
+/**
+ * Draw a plane with given a width and height
+ * @method plane
+ * @param {Number} width width of the plane
+ * @param {Number} height height of the plane
+ * @param {Number} [detailX] Optional number of triangle
+ * subdivisions in x-dimension
+ * @param {Number} [detailY] Optional number of triangle
+ * subdivisions in y-dimension
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //draw a plane with width 200 and height 200
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * plane(50, 50);
+ * }
+ *
+ *
+ *
+ * @alt
+ * Nothing displayed on canvas
+ * Rotating interior view of a box with sides that change color.
+ * 3d red and green gradient.
+ * Rotating interior view of a cylinder with sides that change color.
+ * Rotating view of a cylinder with sides that change color.
+ * 3d red and green gradient.
+ * rotating view of a multi-colored cylinder with concave sides.
+ */
+p5.prototype.plane = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var width = args[0] || 50;
+ var height = args[1] || width;
+ var detailX = typeof args[2] === 'number' ? args[2] : 1;
+ var detailY = typeof args[3] === 'number' ? args[3] : 1;
+
+ var gId = 'plane|'+width+'|'+height+'|'+detailX+'|'+detailY;
+
+ if(!this._renderer.geometryInHash(gId)){
+ var _plane = function(){
+ var u,v,p;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ p = new p5.Vector(width * u - width/2,
+ height * v - height/2,
+ 0);
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var planeGeom =
+ new p5.Geometry(detailX, detailY, _plane);
+ planeGeom
+ .computeFaces()
+ .computeNormals();
+ this._renderer.createBuffers(gId, planeGeom);
+ }
+
+ this._renderer.drawBuffers(gId);
+
+};
+
+/**
+ * Draw a box with given width, height and depth
+ * @method box
+ * @param {Number} width width of the box
+ * @param {Number} Height height of the box
+ * @param {Number} depth depth of the box
+ * @param {Number} [detailX] Optional number of triangle
+ * subdivisions in x-dimension
+ * @param {Number} [detailY] Optional number of triangle
+ * subdivisions in y-dimension
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //draw a spinning box with width, height and depth 200
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * box(200, 200, 200);
+ * }
+ *
+ *
+ */
+p5.prototype.box = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var width = args[0] || 50;
+ var height = args[1] || width;
+ var depth = args[2] || width;
+
+ var detailX = typeof args[3] === 'number' ? args[3] : 4;
+ var detailY = typeof args[4] === 'number' ? args[4] : 4;
+ var gId = 'box|'+width+'|'+height+'|'+depth+'|'+detailX+'|'+detailY;
+
+ if(!this._renderer.geometryInHash(gId)){
+ var _box = function(){
+ var cubeIndices = [
+ [0, 4, 2, 6],// -1, 0, 0],// -x
+ [1, 3, 5, 7],// +1, 0, 0],// +x
+ [0, 1, 4, 5],// 0, -1, 0],// -y
+ [2, 6, 3, 7],// 0, +1, 0],// +y
+ [0, 2, 1, 3],// 0, 0, -1],// -z
+ [4, 5, 6, 7]// 0, 0, +1] // +z
+ ];
+ var id=0;
+ for (var i = 0; i < cubeIndices.length; i++) {
+ var cubeIndex = cubeIndices[i];
+ var v = i * 4;
+ for (var j = 0; j < 4; j++) {
+ var d = cubeIndex[j];
+ //inspired by lightgl:
+ //https://github.com/evanw/lightgl.js
+ //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry)
+ var octant = new p5.Vector(
+ ((d & 1) * 2 - 1)*width/2,
+ ((d & 2) - 1) *height/2,
+ ((d & 4) / 2 - 1) * depth/2);
+ this.vertices.push( octant );
+ this.uvs.push([j & 1, (j & 2) / 2]);
+ id++;
+ }
+ this.faces.push([v, v + 1, v + 2]);
+ this.faces.push([v + 2, v + 1, v + 3]);
+ }
+ };
+ var boxGeom = new p5.Geometry(detailX,detailY, _box);
+ boxGeom.computeNormals();
+ //initialize our geometry buffer with
+ //the key val pair:
+ //geometry Id, Geom object
+ this._renderer.createBuffers(gId, boxGeom);
+ }
+ this._renderer.drawBuffers(gId);
+
+ return this;
+
+};
+
+/**
+ * Draw a sphere with given radius
+ * @method sphere
+ * @param {Number} radius radius of circle
+ * @param {Number} [detailX] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 24
+ * @param {Number} [detailY] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 16
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * // draw a sphere with radius 200
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * sphere(50);
+ * }
+ *
+ *
+ */
+p5.prototype.sphere = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var radius = args[0] || 50;
+ var detailX = typeof args[1] === 'number' ? args[1] : 24;
+ var detailY = typeof args[2] === 'number' ? args[2] : 16;
+ var gId = 'sphere|'+radius+'|'+detailX+'|'+detailY;
+ if(!this._renderer.geometryInHash(gId)){
+ var _sphere = function(){
+ var u,v,p;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ var theta = 2 * Math.PI * u;
+ var phi = Math.PI * v - Math.PI / 2;
+ p = new p5.Vector(radius * Math.cos(phi) * Math.sin(theta),
+ radius * Math.sin(phi),
+ radius * Math.cos(phi) * Math.cos(theta));
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var sphereGeom = new p5.Geometry(detailX, detailY, _sphere);
+ sphereGeom
+ .computeFaces()
+ .computeNormals()
+ .averageNormals()
+ .averagePoleNormals();
+ this._renderer.createBuffers(gId, sphereGeom);
+ }
+ this._renderer.drawBuffers(gId);
+
+ return this;
+};
+
+
+/**
+* @private
+* helper function for creating both cones and cyllinders
+*/
+var _truncatedCone = function(
+ bottomRadius,
+ topRadius,
+ height,
+ detailX,
+ detailY,
+ topCap,
+ bottomCap) {
+ detailX = (detailX < 3) ? 3 : detailX;
+ detailY = (detailY < 1) ? 1 : detailY;
+ topCap = (topCap === undefined) ? true : topCap;
+ bottomCap = (bottomCap === undefined) ? true : bottomCap;
+ var extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);
+ var vertsAroundEdge = detailX + 1;
+
+ // ensure constant slant
+ var slant = Math.atan2(bottomRadius - topRadius, height);
+ var start = topCap ? -2 : 0;
+ var end = detailY + (bottomCap ? 2 : 0);
+ var yy, ii;
+ for (yy = start; yy <= end; ++yy) {
+ var v = yy / detailY;
+ var y = height * v;
+ var ringRadius;
+ if (yy < 0) {
+ y = 0;
+ v = 1;
+ ringRadius = bottomRadius;
+ } else if (yy > detailY) {
+ y = height;
+ v = 1;
+ ringRadius = topRadius;
+ } else {
+ ringRadius = bottomRadius +
+ (topRadius - bottomRadius) * (yy / detailY);
+ }
+ if (yy === -2 || yy === detailY + 2) {
+ ringRadius = 0;
+ v = 0;
+ }
+ y -= height / 2;
+ for (ii = 0; ii < vertsAroundEdge; ++ii) {
+ //VERTICES
+ this.vertices.push(
+ new p5.Vector(
+ Math.sin(ii*Math.PI * 2 /detailX) * ringRadius,
+ y,
+ Math.cos(ii*Math.PI * 2 /detailX) * ringRadius)
+ );
+ //VERTEX NORMALS
+ this.vertexNormals.push(
+ new p5.Vector(
+ (yy < 0 || yy > detailY) ? 0 :
+ (Math.sin(ii * Math.PI * 2 / detailX) * Math.cos(slant)),
+ (yy < 0) ? -1 : (yy > detailY ? 1 : Math.sin(slant)),
+ (yy < 0 || yy > detailY) ? 0 :
+ (Math.cos(ii * Math.PI * 2 / detailX) * Math.cos(slant)))
+ );
+ //UVs
+ this.uvs.push([(ii / detailX), v]);
+ }
+ }
+ for (yy = 0; yy < detailY + extra; ++yy) {
+ for (ii = 0; ii < detailX; ++ii) {
+ this.faces.push([vertsAroundEdge * (yy + 0) + 0 + ii,
+ vertsAroundEdge * (yy + 0) + 1 + ii,
+ vertsAroundEdge * (yy + 1) + 1 + ii]);
+ this.faces.push([vertsAroundEdge * (yy + 0) + 0 + ii,
+ vertsAroundEdge * (yy + 1) + 1 + ii,
+ vertsAroundEdge * (yy + 1) + 0 + ii]);
+ }
+ }
+};
+
+/**
+ * Draw a cylinder with given radius and height
+ * @method cylinder
+ * @param {Number} radius radius of the surface
+ * @param {Number} height height of the cylinder
+ * @param {Number} [detailX] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 24
+ * @param {Number} [detailY] optional: number of segments in y-dimension,
+ * the more segments the smoother geometry
+ * default is 16
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //draw a spinning cylinder with radius 200 and height 200
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateZ(frameCount * 0.01);
+ * cylinder(200, 200);
+ * }
+ *
+ *
+ */
+p5.prototype.cylinder = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var radius = args[0] || 50;
+ var height = args[1] || radius;
+ var detailX = typeof args[2] === 'number' ? args[2] : 24;
+ var detailY = typeof args[3] === 'number' ? args[3] : 16;
+ var gId = 'cylinder|'+radius+'|'+height+'|'+detailX+'|'+detailY;
+ if(!this._renderer.geometryInHash(gId)){
+ var cylinderGeom = new p5.Geometry(detailX, detailY);
+ _truncatedCone.call(
+ cylinderGeom,
+ radius,
+ radius,
+ height,
+ detailX,
+ detailY,
+ true,true);
+ cylinderGeom.computeNormals();
+ this._renderer.createBuffers(gId, cylinderGeom);
+ }
+
+ this._renderer.drawBuffers(gId);
+
+ return this;
+};
+
+
+/**
+ * Draw a cone with given radius and height
+ * @method cone
+ * @param {Number} radius radius of the bottom surface
+ * @param {Number} height height of the cone
+ * @param {Number} [detailX] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 24
+ * @param {Number} [detailY] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 16
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //draw a spinning cone with radius 200 and height 200
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateZ(frameCount * 0.01);
+ * cone(200, 200);
+ * }
+ *
+ *
+ */
+p5.prototype.cone = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var baseRadius = args[0] || 50;
+ var height = args[1] || baseRadius;
+ var detailX = typeof args[2] === 'number' ? args[2] : 24;
+ var detailY = typeof args[3] === 'number' ? args[3] : 16;
+ var gId = 'cone|'+baseRadius+'|'+height+'|'+detailX+'|'+detailY;
+ if(!this._renderer.geometryInHash(gId)){
+ var coneGeom = new p5.Geometry(detailX, detailY);
+ _truncatedCone.call(coneGeom,
+ baseRadius,
+ 0,//top radius 0
+ height,
+ detailX,
+ detailY,
+ true,
+ true);
+ //for cones we need to average Normals
+ coneGeom
+ .computeNormals();
+ this._renderer.createBuffers(gId, coneGeom);
+ }
+
+ this._renderer.drawBuffers(gId);
+
+ return this;
+};
+
+/**
+ * Draw an ellipsoid with given radius
+ * @method ellipsoid
+ * @param {Number} radiusx xradius of circle
+ * @param {Number} radiusy yradius of circle
+ * @param {Number} radiusz zradius of circle
+ * @param {Number} [detailX] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 24. Avoid detail number above
+ * 150, it may crash the browser.
+ * @param {Number} [detailY] optional: number of segments,
+ * the more segments the smoother geometry
+ * default is 16. Avoid detail number above
+ * 150, it may crash the browser.
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * // draw an ellipsoid with radius 20, 30 and 40.
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * ellipsoid(20, 30, 40);
+ * }
+ *
+ *
+ */
+p5.prototype.ellipsoid = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var detailX = typeof args[3] === 'number' ? args[3] : 24;
+ var detailY = typeof args[4] === 'number' ? args[4] : 24;
+ var radiusX = args[0] || 50;
+ var radiusY = args[1] || radiusX;
+ var radiusZ = args[2] || radiusX;
+
+ var gId = 'ellipsoid|'+radiusX+'|'+radiusY+
+ '|'+radiusZ+'|'+detailX+'|'+detailY;
+
+
+ if(!this._renderer.geometryInHash(gId)){
+ var _ellipsoid = function(){
+ var u,v,p;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ var theta = 2 * Math.PI * u;
+ var phi = Math.PI * v - Math.PI / 2;
+ p = new p5.Vector(radiusX * Math.cos(phi) * Math.sin(theta),
+ radiusY * Math.sin(phi),
+ radiusZ * Math.cos(phi) * Math.cos(theta));
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var ellipsoidGeom = new p5.Geometry(detailX, detailY,_ellipsoid);
+ ellipsoidGeom
+ .computeFaces()
+ .computeNormals();
+ this._renderer.createBuffers(gId, ellipsoidGeom);
+ }
+
+ this._renderer.drawBuffers(gId);
+
+ return this;
+};
+
+/**
+ * Draw a torus with given radius and tube radius
+ * @method torus
+ * @param {Number} radius radius of the whole ring
+ * @param {Number} tubeRadius radius of the tube
+ * @param {Number} [detailX] optional: number of segments in x-dimension,
+ * the more segments the smoother geometry
+ * default is 24
+ * @param {Number} [detailY] optional: number of segments in y-dimension,
+ * the more segments the smoother geometry
+ * default is 16
+ * @return {p5} the p5 object
+ * @example
+ *
+ *
+ * //draw a spinning torus with radius 200 and tube radius 60
+ * function setup(){
+ * createCanvas(100, 100, WEBGL);
+ * }
+ *
+ * function draw(){
+ * background(200);
+ * rotateX(frameCount * 0.01);
+ * rotateY(frameCount * 0.01);
+ * torus(200, 60);
+ * }
+ *
+ *
+ */
+p5.prototype.torus = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var detailX = typeof args[2] === 'number' ? args[2] : 24;
+ var detailY = typeof args[3] === 'number' ? args[3] : 16;
+
+ var radius = args[0] || 50;
+ var tubeRadius = args[1] || 10;
+
+ var gId = 'torus|'+radius+'|'+tubeRadius+'|'+detailX+'|'+detailY;
+
+ if(!this._renderer.geometryInHash(gId)){
+ var _torus = function(){
+ var u,v,p;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ var theta = 2 * Math.PI * u;
+ var phi = 2 * Math.PI * v;
+ p = new p5.Vector(
+ (radius + tubeRadius * Math.cos(phi)) * Math.cos(theta),
+ (radius + tubeRadius * Math.cos(phi)) * Math.sin(theta),
+ tubeRadius * Math.sin(phi));
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var torusGeom = new p5.Geometry(detailX, detailY, _torus);
+ torusGeom
+ .computeFaces()
+ .computeNormals()
+ .averageNormals();
+ this._renderer.createBuffers(gId, torusGeom);
+ }
+
+ this._renderer.drawBuffers(gId);
+
+ return this;
+};
+
+///////////////////////
+/// 2D primitives
+/////////////////////////
+
+//@TODO
+p5.RendererGL.prototype.point = function(x, y, z){
+ console.log('point not yet implemented in webgl');
+ return this;
+};
+
+p5.RendererGL.prototype.triangle = function
+(args){
+ var x1=args[0], y1=args[1];
+ var x2=args[2], y2=args[3];
+ var x3=args[4], y3=args[5];
+ var gId = 'tri|'+x1+'|'+y1+'|'+
+ x2+'|'+y2+'|'+
+ x3+'|'+y3;
+ if(!this.geometryInHash(gId)){
+ var _triangle = function(){
+ var vertices = [];
+ vertices.push(new p5.Vector(x1,y1,0));
+ vertices.push(new p5.Vector(x2,y2,0));
+ vertices.push(new p5.Vector(x3,y3,0));
+ this.vertices = vertices;
+ this.faces = [[0,1,2]];
+ this.uvs = [[0,0],[0,1],[1,1]];
+ };
+ var triGeom = new p5.Geometry(1,1,_triangle);
+ triGeom.computeNormals();
+ this.createBuffers(gId, triGeom);
+ }
+
+ this.drawBuffers(gId);
+ return this;
+};
+
+p5.RendererGL.prototype.ellipse = function
+(args){
+ var x = args[0];
+ var y = args[1];
+ var width = args[2];
+ var height = args[3];
+ //detailX and Y are optional 6th & 7th
+ //arguments
+ var detailX = args[4] || 24;
+ var detailY = args[5] || 16;
+ var gId = 'ellipse|'+args[0]+'|'+args[1]+'|'+args[2]+'|'+
+ args[3];
+ if(!this.geometryInHash(gId)){
+ var _ellipse = function(){
+ var u,v,p;
+ var centerX = x+width*0.5;
+ var centerY = y+height*0.5;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ var theta = 2 * Math.PI * u;
+ if(v === 0){
+ p = new p5.Vector(centerX, centerY, 0);
+ }
+ else{
+ var _x = centerX + width*0.5 * Math.cos(theta);
+ var _y = centerY + height*0.5 * Math.sin(theta);
+ p = new p5.Vector(_x, _y, 0);
+ }
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var ellipseGeom = new p5.Geometry(detailX,detailY,_ellipse);
+ ellipseGeom
+ .computeFaces()
+ .computeNormals();
+ this.createBuffers(gId, ellipseGeom);
+ }
+ this.drawBuffers(gId);
+ return this;
+};
+
+p5.RendererGL.prototype.rect = function
+(args){
+ var gId = 'rect|'+args[0]+'|'+args[1]+'|'+args[2]+'|'+
+ args[3];
+ var x = args[0];
+ var y = args[1];
+ var width = args[2];
+ var height = args[3];
+ var detailX = args[4] || 24;
+ var detailY = args[5] || 16;
+ if(!this.geometryInHash(gId)){
+ var _rect = function(){
+ var u,v,p;
+ for (var i = 0; i <= this.detailY; i++){
+ v = i / this.detailY;
+ for (var j = 0; j <= this.detailX; j++){
+ u = j / this.detailX;
+ // var _x = x-width/2;
+ // var _y = y-height/2;
+ p = new p5.Vector(
+ x + (width*u),
+ y + (height*v),
+ 0
+ );
+ this.vertices.push(p);
+ this.uvs.push([u,v]);
+ }
+ }
+ };
+ var rectGeom = new p5.Geometry(detailX,detailY,_rect);
+ rectGeom
+ .computeFaces()
+ .computeNormals();
+ this.createBuffers(gId, rectGeom);
+ }
+ this.drawBuffers(gId);
+ return this;
+};
+
+p5.RendererGL.prototype.quad = function(){
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; ++i) {
+ args[i] = arguments[i];
+ }
+ var x1 = args[0],
+ y1 = args[1],
+ x2 = args[2],
+ y2 = args[3],
+ x3 = args[4],
+ y3 = args[5],
+ x4 = args[6],
+ y4 = args[7];
+ var gId = 'quad|'+x1+'|'+y1+'|'+
+ x2+'|'+y2+'|'+
+ x3+'|'+y3+'|'+
+ x4+'|'+y4;
+ if(!this.geometryInHash(gId)){
+ var _quad = function(){
+ this.vertices.push(new p5.Vector(x1,y1,0));
+ this.vertices.push(new p5.Vector(x2,y2,0));
+ this.vertices.push(new p5.Vector(x3,y3,0));
+ this.vertices.push(new p5.Vector(x4,y4,0));
+ this.uvs.push([0, 0], [1, 0], [1, 1], [0, 1]);
+ };
+ var quadGeom = new p5.Geometry(2,2,_quad);
+ quadGeom.computeNormals();
+ quadGeom.faces = [[0,1,2],[2,3,0]];
+ this.createBuffers(gId, quadGeom);
+ }
+ this.drawBuffers(gId);
+ return this;
+};
+
+//this implementation of bezier curve
+//is based on Bernstein polynomial
+p5.RendererGL.prototype.bezier = function
+(args){
+ var bezierDetail=args[12] || 20;//value of Bezier detail
+ this.beginShape();
+ var coeff=[0,0,0,0];// Bernstein polynomial coeffecients
+ var vertex=[0,0,0]; //(x,y,z) coordinates of points in bezier curve
+ for(var i=0; i<=bezierDetail; i++){
+ coeff[0]=Math.pow(1-(i/bezierDetail),3);
+ coeff[1]=(3*(i/bezierDetail)) * (Math.pow(1-(i/bezierDetail),2));
+ coeff[2]=(3*Math.pow(i/bezierDetail,2)) * (1-(i/bezierDetail));
+ coeff[3]=Math.pow(i/bezierDetail,3);
+ vertex[0]=args[0]*coeff[0] + args[3]*coeff[1] +
+ args[6]*coeff[2] + args[9]*coeff[3];
+ vertex[1]=args[1]*coeff[0] + args[4]*coeff[1] +
+ args[7]*coeff[2] + args[10]*coeff[3];
+ vertex[2]=args[2]*coeff[0] + args[5]*coeff[1] +
+ args[8]*coeff[2] + args[11]*coeff[3];
+ this.vertex(vertex[0],vertex[1],vertex[2]);
+ }
+ this.endShape();
+ return this;
+};
+
+p5.RendererGL.prototype.curve=function
+(args){
+ var curveDetail=args[12];
+ this.beginShape();
+ var coeff=[0,0,0,0];//coeffecients of the equation
+ var vertex=[0,0,0]; //(x,y,z) coordinates of points in bezier curve
+ for(var i=0; i<=curveDetail; i++){
+ coeff[0]=Math.pow((i/curveDetail),3) * 0.5;
+ coeff[1]=Math.pow((i/curveDetail),2) * 0.5;
+ coeff[2]=(i/curveDetail) * 0.5;
+ coeff[3]=0.5;
+ vertex[0]=coeff[0]*(-args[0] + (3*args[3]) - (3*args[6]) +args[9]) +
+ coeff[1]*((2*args[0]) - (5*args[3]) + (4*args[6]) - args[9]) +
+ coeff[2]*(-args[0] + args[6]) +
+ coeff[3]*(2*args[3]);
+ vertex[1]=coeff[0]*(-args[1] + (3*args[4]) - (3*args[7]) +args[10]) +
+ coeff[1]*((2*args[1]) - (5*args[4]) + (4*args[7]) - args[10]) +
+ coeff[2]*(-args[1] + args[7]) +
+ coeff[3]*(2*args[4]);
+ vertex[2]=coeff[0]*(-args[2] + (3*args[5]) - (3*args[8]) +args[11]) +
+ coeff[1]*((2*args[2]) - (5*args[5]) + (4*args[8]) - args[11]) +
+ coeff[2]*(-args[2] + args[8]) +
+ coeff[3]*(2*args[5]);
+ this.vertex(vertex[0],vertex[1],vertex[2]);
+ }
+ this.endShape();
+ return this;
+};
+
+module.exports = p5;
+
+},{"../core/core":37,"./p5.Geometry":82}],88:[function(_dereq_,module,exports){
+
+
+module.exports = {
+ immediateVert:
+ "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n gl_PointSize = uPointSize;\n}\n",
+ vertexColorVert:
+ "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nvarying vec4 vColor;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n}\n",
+ vertexColorFrag:
+ "precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}",
+ normalVert:
+ "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvarying vec3 vVertexNormal;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vVertexNormal = vec3( uNormalMatrix * aNormal );\n vVertTexCoord = aTexCoord;\n}\n",
+ normalFrag:
+ "precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n gl_FragColor = vec4(vVertexNormal, 1.0);\n}",
+ basicFrag:
+ "precision mediump float;\nvarying vec3 vVertexNormal;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n gl_FragColor = uMaterialColor;\n}",
+ lightVert:
+ "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nuniform vec3 uAmbientColor[8];\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nvarying vec3 vVertexNormal;\nvarying vec2 vVertTexCoord;\nvarying vec3 vLightWeighting;\n\nvec3 ambientLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 directionalLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 pointLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 pointLightFactor2 = vec3(0.0, 0.0, 0.0);\n\nvoid main(void){\n\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\n vec3 vertexNormal = vec3( uNormalMatrix * aNormal );\n vVertexNormal = vertexNormal;\n vVertTexCoord = aTexCoord;\n\n vec4 mvPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n vec3 eyeDirection = normalize(-mvPosition.xyz);\n\n float shininess = 32.0;\n float specularFactor = 2.0;\n float diffuseFactor = 0.3;\n\n for(int i = 0; i < 8; i++){\n if(uAmbientLightCount == i) break;\n ambientLightFactor += uAmbientColor[i];\n }\n\n for(int j = 0; j < 8; j++){\n if(uDirectionalLightCount == j) break;\n vec3 dir = uLightingDirection[j];\n float directionalLightWeighting = max(dot(vertexNormal, dir), 0.0);\n directionalLightFactor += uDirectionalColor[j] * directionalLightWeighting;\n }\n\n for(int k = 0; k < 8; k++){\n if(uPointLightCount == k) break;\n vec3 loc = uPointLightLocation[k];\n vec3 lightDirection = normalize(loc - mvPosition.xyz);\n\n float directionalLightWeighting = max(dot(vertexNormal, lightDirection), 0.0);\n pointLightFactor += uPointLightColor[k] * directionalLightWeighting;\n\n //factor2 for specular\n vec3 reflectionDirection = reflect(-lightDirection, vertexNormal);\n float specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), shininess);\n\n pointLightFactor2 += uPointLightColor[k] * (specularFactor * specularLightWeighting\n + directionalLightWeighting * diffuseFactor);\n }\n\n if(!uSpecular){\n vLightWeighting = ambientLightFactor + directionalLightFactor + pointLightFactor;\n }else{\n vLightWeighting = ambientLightFactor + directionalLightFactor + pointLightFactor2;\n }\n\n}\n",
+ lightTextureFrag:
+ "precision mediump float;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\n\nvarying vec3 vLightWeighting;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n if(!isTexture){\n gl_FragColor = vec4(vec3(uMaterialColor.rgb * vLightWeighting), uMaterialColor.a);\n }else{\n vec4 textureColor = texture2D(uSampler, vVertTexCoord);\n if(vLightWeighting == vec3(0., 0., 0.)){\n gl_FragColor = textureColor;\n }else{\n gl_FragColor = vec4(vec3(textureColor.rgb * vLightWeighting), textureColor.a);\n }\n }\n}"
+};
+},{}]},{},[28])(28)
+});
\ No newline at end of file
diff --git a/processing3/virtualCommandline/virtualCommandline.pde b/processing3/virtualCommandline/virtualCommandline.pde
new file mode 100644
index 0000000..cff518e
--- /dev/null
+++ b/processing3/virtualCommandline/virtualCommandline.pde
@@ -0,0 +1,87 @@
+CommandLine commandLine;
+void setup() {
+ size (800, 420);
+ commandLine = new CommandLine();
+}
+int pfc;
+void draw() {
+ background(0);
+ fill(#FFFFFF);
+ stroke(#FFFFFF);
+ commandLine.update();
+ commandLine.display();
+}
+
+class CommandLine {
+ String userInput = "";
+ String inputString;
+ String[] presentedLines;
+ String[] possibleCommands = { "asd" };
+ int idleFrameCount;
+ boolean busy;
+ CommandLine() {
+ presentedLines = new String[30];
+ for (int i = 0; i < presentedLines.length; i++) {
+ presentedLines[i] = "";
+ }
+ }
+ void getUserInput(int code, char c) {
+ println(code, c);
+ if (!busy) {
+ if (code != 8 && code != 10 && code != 16 && code != 17 && code != 18 && code != 20)
+ userInput = userInput + c;
+ if (code == 8 && userInput.length() > 0) { //backspace
+ userInput = userInput.substring(0, userInput.length()-1);
+ } else if (code == 10) { //enter
+ enterInput();
+ userInput = "";
+ }
+ }
+ }
+ void pushLineString(String bottomLine) {
+ println("bottomline " + bottomLine);
+ for (int i = presentedLines.length-1; i > 0; i--) {
+ presentedLines[i] = presentedLines[i-1];
+ }
+ presentedLines[0] = bottomLine;
+ }
+ void enterInput() { //user Input DEFINE COMMANDS HERE THAT ARE DETECTED
+ if (userInput.equals("asd")) {
+ goOutside();
+ } else {
+ pushLineString(inputString);
+ }
+ }
+
+ void update() {
+ if (!busy) {
+ inputString = "guest@iris ~ $ " + userInput;
+ presentedLines[0] = inputString;
+ } else {
+ if (idleFrameCount + pfc < frameCount) {
+ busy = false;
+ }
+ }
+ }
+ void display() {
+ for (int i = 0; i < presentedLines.length; i++) {
+ text(presentedLines[i], 13, height-25-(i*13));
+ }
+ }
+}
+
+void goOutside() {
+ commandLine.busy = true;
+ pfc = frameCount;
+// String[] stringList = {"Processing",};
+ // l("processing user data...", 10);
+// pfc = frameCount;
+// pushLineString(input);
+ // idleFrameCount += f;
+}
+
+
+void keyPressed() {
+ //println(keyCode + " " + key);
+ commandLine.getUserInput(keyCode, key);
+}