From 21c25872641d5cd1f72352317b2d1666f240e809 Mon Sep 17 00:00:00 2001
From: ZitRo <zitros.lab@gmail.com>
Date: Sun, 31 May 2015 18:25:41 +0300
Subject: [PATCH 1/2] diagram search enabled

---
 README.md                  |   6 ++-
 package.json               |   2 +-
 web/css/classView.css      |  19 +++++++
 web/css/extras.css         |  29 +++++++++++
 web/index.html             |   6 ++-
 web/js/CacheUMLExplorer.js |   4 +-
 web/js/ClassView.js        | 103 +++++++++++++++++++++++++++++++++++++
 7 files changed, 164 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index c4bb065..3697186 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,13 @@ An UML Class explorer for InterSystems Caché.
 + Edit diagrams after build;
 + Export diagrams as an image;
 + View class methods code with syntax highlighting;
-+ Zoom in and out, explore big packages and more.
++ Zoom in and out;
++ Search on diagram or in class tree;
++ Explore!
 
 ## Screenshots
 
-![Demo](https://cloud.githubusercontent.com/assets/4989256/7898598/7d367720-070d-11e5-9177-dded6abf93e1.png)
+![Demo](https://cloud.githubusercontent.com/assets/4989256/7902384/e7882a48-07c0-11e5-9c3f-7203a40263d2.png)
 
 ## Installation
 
diff --git a/package.json b/package.json
index e61105d..39aa711 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "CacheUMLExplorer",
-  "version": "0.12.1",
+  "version": "0.13.0",
   "description": "An UML Class explorer for InterSystems Caché",
   "directories": {
     "test": "test"
diff --git a/web/css/classView.css b/web/css/classView.css
index 700c6d7..ecf12e5 100644
--- a/web/css/classView.css
+++ b/web/css/classView.css
@@ -82,4 +82,23 @@ text {
 
 .line-clickable:hover {
     fill: red;
+}
+
+.inlineSearchBlock {
+    display: inline-block;
+    vertical-align: bottom;
+}
+
+#diagramSearch {
+    display: block;
+    box-sizing: border-box;
+    border: 1px solid gray;
+    border-radius: 5px;
+    width: 200px;
+    margin: 4px 0 4px 4px;
+    height: 22px;
+}
+
+.element.highlighted {
+    outline: 4px solid rgba(255, 0, 0, 0.6);
 }
\ No newline at end of file
diff --git a/web/css/extras.css b/web/css/extras.css
index edf9e7a..109667c 100644
--- a/web/css/extras.css
+++ b/web/css/extras.css
@@ -84,6 +84,35 @@
     box-shadow: 0 0 5px 2px #ffcc1b;
 }
 
+.icon.search:after {
+    content: "";
+    position: absolute;
+    display: block;
+    width: 6px;
+    height: 6px;
+    left: 4px;
+    top: 4px;
+    border: 3px solid #fff;
+    background: transparent;
+    border-radius: 6px;
+}
+
+.icon.search:before {
+    content: "";
+    position: absolute;
+    display: block;
+    left: 14px;
+    top: 12px;
+    width: 3px;
+    height: 7px;
+    background: #fff;
+    -webkit-transform: rotate(-45deg);
+    -moz-transform: rotate(-45deg);
+    -ms-transform: rotate(-45deg);
+    -o-transform: rotate(-45deg);
+    transform: rotate(-45deg);
+}
+
 .icon.select {
     width: auto;
     color: white;
diff --git a/web/index.html b/web/index.html
index 1418cab..cd56662 100644
--- a/web/index.html
+++ b/web/index.html
@@ -29,7 +29,7 @@
     <div class="ui-body" id="ui-body">
         <div class="ui-sideBlock">
             <div class="ui-sideSearchBlock" id="searchBlock">
-                <input type="search" id="classTreeSearch" placeholder="Search..."/>
+                <input type="search" id="classTreeSearch" placeholder="Search in class tree..."/>
             </div>
             <div id="treeView">
 
@@ -50,6 +50,10 @@
                 <div id="button.downloadSVG" class="icon download"></div>
             </div>
             <div class="ui-rightBottomToolBar">
+                <div class="inlineSearchBlock" id="diagramSearchBlock">
+                    <input type="search" id="diagramSearch" placeholder="Search on diagram..."/>
+                </div>
+                <div id="button.diagramSearch" class="icon search"></div>
                 <div id="button.zoomIn" class="icon plus"></div>
                 <div id="button.zoomNormal" class="icon scaleNormal"></div>
                 <div id="button.zoomOut" class="icon minus"></div>
diff --git a/web/js/CacheUMLExplorer.js b/web/js/CacheUMLExplorer.js
index df4f160..a1b6685 100644
--- a/web/js/CacheUMLExplorer.js
+++ b/web/js/CacheUMLExplorer.js
@@ -30,7 +30,9 @@ var CacheUMLExplorer = function (treeViewContainer, classViewContainer) {
         methodViewBounds: id("methodViewBounds"),
         namespaces: id("namespaces"),
         classTreeSearch: id("classTreeSearch"),
-        searchBlock: id("searchBlock")
+        searchBlock: id("searchBlock"),
+        diagramSearch: id("diagramSearch"),
+        diagramSearchButton: id("button.diagramSearch")
     };
 
     this.UI = new UI(this);
diff --git a/web/js/ClassView.js b/web/js/ClassView.js
index 275c21c..b118d87 100644
--- a/web/js/ClassView.js
+++ b/web/js/ClassView.js
@@ -21,10 +21,29 @@ var ClassView = function (parent, container) {
     this.CLASS_DOC_PATH = "/csp/documatic/%25CSP.Documatic.cls";
     this.SYMBOL_12_WIDTH = 6.6;
 
+    this.HIGHLIGHTED_VIEW = null;
+    this.SEARCH_INDEX = 0;
+
     this.init();
 
 };
 
+ClassView.prototype.highlightElement = function (jointElement) {
+
+    if (this.HIGHLIGHTED_VIEW || (!jointElement && this.HIGHLIGHTED_VIEW)) {
+        this.HIGHLIGHTED_VIEW.unhighlight();
+        this.HIGHLIGHTED_VIEW = null;
+    }
+
+    if (!jointElement) return;
+    var view = this.paper.findViewByModel(jointElement);
+    if (!view) return;
+
+    view.highlight();
+    this.HIGHLIGHTED_VIEW = view;
+
+};
+
 ClassView.prototype.showLoader = function (html) {
 
     var d2;
@@ -60,6 +79,9 @@ ClassView.prototype.resetView = function () {
     this.objects = [];
     this.paper.setOrigin(0, 0);
     this.graph.clear();
+    this.HIGHLIGHTED_VIEW = null;
+    this.SEARCH_INDEX = 0;
+    this.cacheUMLExplorer.elements.diagramSearch.value = "";
 
 };
 
@@ -268,6 +290,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
     var classParams = classMetaData["parameters"],
         classProps = classMetaData["properties"],
         classMethods = classMetaData["methods"],
+        keyWordsArray = [name],
         self = this;
 
     var classInstance = new joint.shapes.uml.Class({
@@ -283,6 +306,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
         params: (function (params) {
             var arr = [], n;
             for (n in params) {
+                keyWordsArray.push(n);
                 arr.push({
                     text: n + (params[n]["type"] ? ": " + params[n]["type"] : "")
                 });
@@ -292,6 +316,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
         attributes: (function (ps) {
             var arr = [], n;
             for (n in ps) {
+                keyWordsArray.push(n);
                 arr.push({
                     text: n + (ps[n]["type"] ? ": " + ps[n]["type"] : ""),
                     icons: self.getMethodIcons(ps[n])
@@ -302,6 +327,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
         methods: (function (met) {
             var arr = [], n;
             for (n in met) {
+                keyWordsArray.push(n);
                 arr.push({
                     text: n + (met[n]["returns"] ? ": " + met[n]["returns"] : ""),
                     styles: (function (t) {
@@ -319,6 +345,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
         SYMBOL_12_WIDTH: self.SYMBOL_12_WIDTH
     });
 
+    classInstance.SEARCH_KEYWORDS = keyWordsArray.join(",").toLowerCase();
     this.objects.push(classInstance);
     this.graph.addCell(classInstance);
 
@@ -562,6 +589,69 @@ ClassView.prototype.zoom = function (delta) {
 
 };
 
+/**
+ * Focus on joint instance.
+ * @param jointInstance
+ */
+ClassView.prototype.focusOnInstance = function (jointInstance) {
+
+    var bb = jointInstance.getBBox();
+
+    this.focusOnXY(bb.x + bb.width/2, bb.y + bb.height/2);
+
+};
+
+/**
+ * Focus on x and y coordinates considering scale.
+ * @param {number} x
+ * @param {number} y
+ */
+ClassView.prototype.focusOnXY = function (x, y) {
+
+    var sw = this.cacheUMLExplorer.elements.classViewContainer.offsetWidth,
+        sh = this.cacheUMLExplorer.elements.classViewContainer.offsetHeight,
+        scale = this.PAPER_SCALE;
+
+    this.paper.setOrigin(
+        -(x * scale) + sw/2,
+        -(y * scale) + sh/2
+    );
+
+};
+
+/**
+ * Find text on diagram and focus on element.
+ *
+ * @param {string} text
+ */
+ClassView.prototype.searchOnDiagram = function (text) {
+
+    var p, found = [], o;
+
+    if (!text) {
+        this.highlightElement(null);
+        return;
+    }
+
+    text = text.toLowerCase();
+
+    for (p in this.objects) {
+        if (this.objects[p].SEARCH_KEYWORDS.indexOf(text) !== -1) {
+            found.push(this.objects[p]);
+        }
+    }
+
+    if (found.length) {
+        o = found[this.SEARCH_INDEX % found.length];
+        this.focusOnInstance(o);
+        this.highlightElement(o);
+        return;
+    }
+
+    this.highlightElement(null);
+
+};
+
 ClassView.prototype.init = function () {
 
     var p, self = this,
@@ -635,6 +725,19 @@ ClassView.prototype.init = function () {
     this.cacheUMLExplorer.elements.helpButton.addEventListener("click", function () {
         self.renderInfoGraphic();
     });
+    this.cacheUMLExplorer.elements.diagramSearch.addEventListener("input", function (e) {
+        self.searchOnDiagram((e.target || e.srcElement).value);
+    });
+    this.cacheUMLExplorer.elements.diagramSearch.addEventListener("keydown", function (e) {
+        if (e.keyCode === 13) {
+            self.SEARCH_INDEX++;
+            self.searchOnDiagram((e.target || e.srcElement).value);
+        }
+    });
+    this.cacheUMLExplorer.elements.diagramSearchButton.addEventListener("click", function () {
+        self.SEARCH_INDEX++;
+        self.searchOnDiagram(self.cacheUMLExplorer.elements.diagramSearch.value);
+    });
 
     this.SYMBOL_12_WIDTH = (function () {
         var e = document.createElementNS("http://www.w3.org/2000/svg", "text"),

From d4f4320b75cfe4e7f219d7a8beddf55858050558 Mon Sep 17 00:00:00 2001
From: ZitRo <zitros.lab@gmail.com>
Date: Sun, 31 May 2015 18:33:45 +0300
Subject: [PATCH 2/2] favicon add

---
 package.json               | 2 +-
 web/index.html             | 1 +
 web/js/CacheUMLExplorer.js | 3 +++
 web/js/Lib.js              | 3 ++-
 4 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 39aa711..23220db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "CacheUMLExplorer",
-  "version": "0.13.0",
+  "version": "0.13.1",
   "description": "An UML Class explorer for InterSystems Caché",
   "directories": {
     "test": "test"
diff --git a/web/index.html b/web/index.html
index cd56662..e7aa9af 100644
--- a/web/index.html
+++ b/web/index.html
@@ -24,6 +24,7 @@
     <script type="text/javascript" src="js/Source.js"></script>
     <script type="text/javascript" src="js/UI.js"></script>
     <!-- endbuild -->
+    <link id="favicon" rel="shortcut icon" href="#"/>
 </head>
 <body onload="cue = new CacheUMLExplorer(document.getElementById('treeView'), document.getElementById('svgContainer'))">
     <div class="ui-body" id="ui-body">
diff --git a/web/js/CacheUMLExplorer.js b/web/js/CacheUMLExplorer.js
index a1b6685..0ab9c86 100644
--- a/web/js/CacheUMLExplorer.js
+++ b/web/js/CacheUMLExplorer.js
@@ -11,6 +11,7 @@ var CacheUMLExplorer = function (treeViewContainer, classViewContainer) {
     var id = function (e) { return document.getElementById(e); };
 
     this.elements = {
+        favicon: id("favicon"),
         uiBody: id("ui-body"),
         className: id("className"),
         treeViewContainer: treeViewContainer,
@@ -121,6 +122,8 @@ CacheUMLExplorer.prototype.init = function () {
     var self = this,
         restored;
 
+    this.elements.favicon.href = lib.image.binoculars;
+
     restored = this.restoreFromURL();
     this.classTree.showLoader();
     this.source.getClassTree(function (err, data) {
diff --git a/web/js/Lib.js b/web/js/Lib.js
index f61916a..ea0204d 100644
--- a/web/js/Lib.js
+++ b/web/js/Lib.js
@@ -165,5 +165,6 @@ Lib.prototype.image = {
     table: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADC0lEQVR42p2TS2wbRRyHv5ldr2Nnk9ixHbe0QC2BWoGQONGQFAgPicIBBBQkhBAHHleoQNw4cCwPcUOoQryCUtkkbSJLEVCVtiBRDkUUFQmaCrUQKCJOG7vrR7Pr3eHvdaB3ZrWa3dndb/6/b2bVgem5x7bvKL0WhcoYei1ERR5GD8u15mpryZn6b2wgYamfz5x/V3339Q/GLx3F+Hb8QAnAxD3SXwUo+vh/xxKJiM6p24gBh7c+zfLqGknLkjcd0omXaAdvYozamNEn6dyPH3wvYzW5TxIOtNjz66E+oJx7jp9qNVK2IqEHyVovshrs25hNyREwrHfT5iTr0Qra9AAd9v5ViQHezl23un4dHElRW4cTDXhoDLpRv3xbONUVGM9AIQlBKBFG4KvqiaY6duSYN7lrwq3XG3EFNV/xbV3x8FiEvwFw5JyvaSYyhoJj6HQNuVyG6sIXTXX8yyPexJ3jrtfwGBDAhY7hm1WLx7eErJvYmsSCuT80k3nD5pShFRhGs8NUD34eA8xbzRvQgU8maaG15lJgcVOuJ9AmJV7TjsWyb3G9rOKQROi5HcpmcY4fRC3OL3rjd427l+uXxb7mz7biqFTw1LVdrkT9CpKWYWbZYqoQco1AWuIpl8+wMFttqrnKgnfHPZPu2lodtwfoKBb/tnl+m087VLGDtADeP+/wQLHLFonQlAiF/Ciz5fmmOlwue/c9OOU2LtUZSsBZT1OW2V7ZHnBFbEdSRVI4+85Y7BEvJTeiIXKKYzk++agSA8z04E7CdpvRZIIuFr91NLcX5Utti0DNoMg97dncnDWMDMheFWo2n2e1/B7q4w9mvIm7JcLFNYYdzbm2pnLB5tUbfdYlglGKlDa8cTbBE1tDtqWjOEI+n+OzmVnUgU8rzXt3Tw1elK08IoBfmrD/nM3btwR9B1JIOmF4+bTNC6WQHS7UexE25flw/3QMMPlNBeo9iXEFFodWUuy9rtlfhd6fJ/vgnd9dHhnrUEqHtHzIjI5w6uSPqGeefPbR4ubiHP+jLS0tvf4PKUZIoAyrwMEAAAAASUVORK5CYII=",
     earth: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADUklEQVR42l1TW2hcVRRd5z7mcedOXtMmmmknpg+VZEIFrfjT0lZqQiemoWXyVxpRKNUKiiD4WUHBHxE/IvVnIuhHDLYiHUhKBEmxUEgKLbEW0kkyebSTmWle87iPmXNOd6a0VA9cOHeffdZae+19GP63XhvJRPv3+o7uCWrfpwq8Fmv1K9nLc9Z52q6Mv9t88/l89nTTl3xoRuu8o2c6zZ5XG3XMbEmoUiBTYQiqQJ0qIewqfpwpjV1btuP/nA0XnwHsHpo3hmPNd49FjLYncBILRYG/1wUadAZbAJ1eib1eQFckvr1dTA/dLnakzreVawBfT+bHvjgU6oYQ4IJhyRJYcoANV0JTUAOI+gQaCditAi8YDBcm18Z/iL3Yw966dP/E5GAkqasqbC5xqyCRLgMGyfbQ5W0XHIq/bW5flnhUAXboQNaqYuDKgxiL/7KQGBnYPVhwBR4Qa5GSc5yhIiSYBAr0f8CgMjU6q5AUijsViRZi+Pyv7DA7+/vKavxIa7NacvB6QAEn1iVL4l8bZJ7EJjEerWeIEECOSCy6XKlyAtDx5Y18ll2YyFj7XtnhS226eCeooHcnQ4kUTG8J3CmJWhkGYwiRebvI0CZNoEqlSIXh3J+PbPbRtYzVvj/kW1x30ElS39/lwQaxBFUFc6UKvlpwoZKsnM1xsEHBh2EdnHMk8hI/3czZrC8xu3roWHvzUq6MAnXg47CKiF9BPQEkcy4SaRemyqgjHFFTxaftHpRdIA0F312dz7I3Lk4ljg90Da5tOMg7EsdDCs616ZgvS3w2U4ZDbdMgYJMXglxNvmlgalPgt1WOGxOzwyz8wcSJw/3RpNkSxPKahfciHsRbPTgzVUKqUEUd1epKCU51bzoC3a0apksKpu+tIXAvHasN0v5PJse6Th7ozhPNNy97cT3HcSllIexntZZVxZMZEFR7lvxgNOKBW3Pj80NHemoALfE/jEC48W7T4Y622EseLOcsXM848NGpS3NQ3f6oEy7TwGkU1TtzaW2r2LH4c2/52WMK9Y+aeoM56u3a06O31INrKoRbqTFzejKc5CO/Dn12cUx17PjKyOnif17j09XU92uv2micQtCMSb8/IEguLKukbFlJpVi+nL0Sv/p8/mODDJQs66BSJwAAAABJRU5ErkJggg==",
     zed: "data:image/png;base64,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",
-    eye: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC7UlEQVR42qWTS0iUURTH//eb8ROdZ5o46qRktHBSFCzJlfRCKNqULXoZtOgdZSY9rIULIYLIHliQRBmIUBCREkSlUSBZmjROqTHj6ExOJqYzozPf896uBhLhqg5c7uHA73A4//8h+M8gfxc0z+FiaGotFKmEKbLOJAmQNQNkqZvNxuoT97zrWbSB+rXaTqh2jcOVoCoEXYMuxyFIcbDZOMAf5c1YTGqmCjuRdLx/eqGB6q3JIWBug4FaWDwG6veBBoMgPGdUBwQRMJkhGBJAZAWKokd5ucB00jNCOCwYjEKQGGnGdFcPIq86QFkyaGY+qCUdRjEJiIyBTAzAODMBU2Y2rGl2yCoN6Tp1EjZ2/iRi0as9Nx/wUZMhl5+FVlAG1bYKUDgbnUWK0wrDzyHonz/A3HkZxvHPWOlygoqWKqK69wbeNT5zOjacQeb20+ic4RMzIF/lydQ4Ghtv4FsM2FzXADERcGkM0Te3IbfXoWAZCRLv/R1S6rpLibZluRjmzGBUw2RgFNG3D9Hd14+WR48gxyWUVd9C3q6DWKMFsHm5HSP+ISQ9PSqTKb9Hsue4EueW2T8ex70gw3DvJ7w4UIrIH3IVHrkJ+9b92CIGsNMRw5gtD/G+JzLxNRYFzGVNzjRXMSb4wiueBJGdkoLnx8rxw/N2HjZbUrG6yQNfRMadUhFOsxGh94/heHMhSFjP9lPu1o4reu5uFFUcQk3IhdYvDOlWgh9tzYiHw0jeuA+jmhVltnHczeqFt70BjlAnslc4q4j+eptBIFrA/7IrIxySgdz1uDebB68lH35bITRK4JjqQ2G4C3tENxK+f0SyKGBpdlZImZNxbkS5bVOOyHS3PDllkXwBcOWhQ+A2I7+dRhgSqIYZaoRuWgIiGKOyohVkXBwcWbCy0rLWLkjqNaaqlZRLxSgF4zvhHzcWm/9VyuuMNXMXnkivHZhe9Jik665iSkktZ0o0ynTOzHUwaBTdnK5POzew+DH9a/wCg6d3xpUf4V0AAAAASUVORK5CYII="
+    eye: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC7UlEQVR42qWTS0iUURTH//eb8ROdZ5o46qRktHBSFCzJlfRCKNqULXoZtOgdZSY9rIULIYLIHliQRBmIUBCREkSlUSBZmjROqTHj6ExOJqYzozPf896uBhLhqg5c7uHA73A4//8h+M8gfxc0z+FiaGotFKmEKbLOJAmQNQNkqZvNxuoT97zrWbSB+rXaTqh2jcOVoCoEXYMuxyFIcbDZOMAf5c1YTGqmCjuRdLx/eqGB6q3JIWBug4FaWDwG6veBBoMgPGdUBwQRMJkhGBJAZAWKokd5ucB00jNCOCwYjEKQGGnGdFcPIq86QFkyaGY+qCUdRjEJiIyBTAzAODMBU2Y2rGl2yCoN6Tp1EjZ2/iRi0as9Nx/wUZMhl5+FVlAG1bYKUDgbnUWK0wrDzyHonz/A3HkZxvHPWOlygoqWKqK69wbeNT5zOjacQeb20+ic4RMzIF/lydQ4Ghtv4FsM2FzXADERcGkM0Te3IbfXoWAZCRLv/R1S6rpLibZluRjmzGBUw2RgFNG3D9Hd14+WR48gxyWUVd9C3q6DWKMFsHm5HSP+ISQ9PSqTKb9Hsue4EueW2T8ex70gw3DvJ7w4UIrIH3IVHrkJ+9b92CIGsNMRw5gtD/G+JzLxNRYFzGVNzjRXMSb4wiueBJGdkoLnx8rxw/N2HjZbUrG6yQNfRMadUhFOsxGh94/heHMhSFjP9lPu1o4reu5uFFUcQk3IhdYvDOlWgh9tzYiHw0jeuA+jmhVltnHczeqFt70BjlAnslc4q4j+eptBIFrA/7IrIxySgdz1uDebB68lH35bITRK4JjqQ2G4C3tENxK+f0SyKGBpdlZImZNxbkS5bVOOyHS3PDllkXwBcOWhQ+A2I7+dRhgSqIYZaoRuWgIiGKOyohVkXBwcWbCy0rLWLkjqNaaqlZRLxSgF4zvhHzcWm/9VyuuMNXMXnkivHZhe9Jik665iSkktZ0o0ynTOzHUwaBTdnK5POzew+DH9a/wCg6d3xpUf4V0AAAAASUVORK5CYII=",
+    binoculars: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADrElEQVR42m2Sa0zTVxiHfwfaSgthCxTEuZlMdkn2wW26utlEwtQB2rUUicSJ4gRS7cBNXIlmSGCbcYuGbMsYirawoWSJyEAm09VOII6tYKmOS8cYtEBrL7b0Tiv08t9/zZa4ZOfDSc553/Pk5Pe8BI+s3cUljrzc3FSj6T41NjZOLn/bRv6+31tSSvH5m6hJ3e9kfFLnuaW88fi/b8ijgLJy6ZL8QhPL4fSjq7sLkrKSWL29/TK1Z88uWBxeHJO9//DiN3L2/wK2C8XTIoEgs3/gNn4bvYfJidFYXVxQRG3kb0RPZzfC4WWHRjOc9h/Aidr6D9LTMo72DfQl7ywsZI6MaKH+ZRDqX2/H6ufOK6jC4t0ofWsfDPqZaAo3dSHgXxzUaIYKYg3Ha+rChw5K42fn/kRvrwpTf+jAZDJgsVjg9/pwov4kNBo1nlv7DGwOG9gJiejvU+FqdychlYer+C63b1Amq8KaJ7jwBJfQ/FUzrA/siI9jYqD/Jta9vAEejxs/3rgGr9sJl28RPVev04COHFJT++E+p9fbVnmoHHHReDooOzo7rsDpciIaAbTaIWRlb8UDmwVnzzbCarbCanPAYrPjYptCSmSy4/XJKal1ktK3kchmwWRzoUUhh8NqRSgKDA8PIntLDuz0+bz8HDhJHExN6ZH4WAqq35UqyIFSycj42Nj6CEXhYTCIYCCAlasy8NKL67Gw4MDo6F28nv0Gpg163NOqEfAHQOjkCL2tfnK1lVRUvncyLX1VzbHqKlz7QYVbdDgUHazZOB/gcrnapOSku0ajsexNkZhTVCDEqTOfwevxwDCjh9fl+IJUHDl6msfbVF1cJIKitR3jEzpEIhGY5ueWv+/5bsU/E7okEOazdgrz8PGpM/DQZrxuN53H/CekXPLOhChf/MIrG9bRvltgNpsRCYVx32iEUtkb01xSVk5t2ZqLLD4PDQ2N8C76EA2FMDc7rSPSiiOB/Qf2sp99OhNNF1rh93ngcroxO2+AsrcnBpAcrqKyN2dBKMjBp6c/h9vpjFmaM+iDJE8gpj6qrYPda0dzkxwhmhwOLSMajeIn1fUYYP/BCqp4VyFMJgs6Oq8gshxChIrARpshmZnPUw2NX0KlvIlLrS10exQJHDaeWrMWd9Q/xwDbtuVSX7ddwo7tefS39WCtYCF9ZQZYDAbIq/zNEcGO/LiZmUlqaEgNGg0Gkwk2J4HcGVbHADzea5RAVEB1d3XASauNoxXS40ziGXHRvwAVvrukyLa34QAAAABJRU5ErkJggg=="
 };
\ No newline at end of file