{ "cells": [ { "cell_type": "markdown", "id": "f6c85fc5-9435-4201-9d21-6a17513880d3", "metadata": { "tags": [] }, "source": [ "# Welcome to GoNB\n", "\n", "[*GoNB*](https://github.com/janpfeifer/gonb) is a *Go* notebook kernel. It allows one to easily run *Go* code in a *Jupyter Notebook* and variations.\n", "\n", "In this tutorial we will walk through most of its features, and explain how it works.\n", "\n", "See the [README.md's Installation section](https://github.com/janpfeifer/gonb#installation). It also includes a Docker with Jupyter+GoNB pre-installed, that makes it trivial.\n", "\n", "## Hello World!\n", "\n", "Whenever a cell is executed, *gonb* saves the cell content of the cell to a *Go* file, auto-imports missing dependencies (when it can guess), compiles and runs it. It may seem a lot, but its pretty fast (except\n", "maybe the first cell run that is usually a little slower) and feels interactive. " ] }, { "cell_type": "code", "execution_count": 1, "id": "430b4b44-0012-4086-8460-5ba81d20a699", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!" ] } ], "source": [ "func main() {\n", " fmt.Printf(\"Hello World!\")\n", "}" ] }, { "cell_type": "markdown", "id": "a936cc25-a399-43d8-8590-4bbf116a9c15", "metadata": {}, "source": [ "Easy, right ? Now when trying different things, to avoid having to write `func main()` at every cell, *gonb* provides a short cut: \"%%\". Anything after a \"%%\" will be wrapped inside a `func main() { ... }`.\n", "\n", "So, let's redo our example above:" ] }, { "cell_type": "code", "execution_count": 2, "id": "781a15d2-469e-4c93-b45e-c18067787f97", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!" ] } ], "source": [ "%%\n", "fmt.Printf(\"Hello World!\")" ] }, { "cell_type": "markdown", "id": "1917b045-6b6a-47bb-a9ed-dfac8fecaca7", "metadata": {}, "source": [ "## Globals and Updates\n", "\n", "Imports, functions, constants, types and variables global declarations are memorized once executed, and carry over from one cell to another.\n", "\n", "So one can work on different functions let's say on different cells.\n", "\n", "Let's test it out:" ] }, { "cell_type": "code", "execution_count": 3, "id": "1c73bb12-8e2e-49a8-ae72-60d2c022e25f", "metadata": {}, "outputs": [], "source": [ "func incr[T interface{constraints.Float|constraints.Integer}](x T) T {\n", " return x+T(1)\n", "}" ] }, { "cell_type": "markdown", "id": "35bb337a-1a73-4d0d-a411-3eec6c1e8507", "metadata": {}, "source": [ "Ok, now we have `incr` defined to any numeric type, we can use it in all our future cells.\n", "\n", "Some quick tests:" ] }, { "cell_type": "code", "execution_count": 4, "id": "d1414e76-3fa9-4046-827b-e449cc638e81", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "incr: x=2, y=4.141593\n" ] } ], "source": [ "%%\n", "x := incr(1)\n", "y := incr(math.Pi)\n", "fmt.Printf(\"incr: x=%d, y=%f\\n\", x, y)" ] }, { "cell_type": "markdown", "id": "7c1b28f7-b36f-4ec3-9239-99f8352c01fb", "metadata": {}, "source": [ "> **Note**: Only the various declarations are carried over from one cell to another, not the results of the execution, including updates to variables.\n", "> \n", "> So for instance, if we initialize a variable `startValue` with 1, then increment it in one cell. Next time we execute a new cell, it will be again initialized to 1. " ] }, { "cell_type": "code", "execution_count": 5, "id": "5549f231-4061-4ec7-9e1c-8ae56c7c82d7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "current startValue=2.000000\n" ] } ], "source": [ "var startValue = float32(1)\n", "\n", "%%\n", "startValue = incr(startValue)\n", "fmt.Printf(\"current startValue=%f\\n\", startValue)" ] }, { "cell_type": "markdown", "id": "df2be63f-991f-4c4d-acf3-d705fa2b6d96", "metadata": {}, "source": [ "Now if we execute again, `startValue` is again initialized to 1:" ] }, { "cell_type": "code", "execution_count": 6, "id": "2111a24e-2627-463a-b936-d8476ba69005", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "current startValue=1.000000\n" ] } ], "source": [ "%%\n", "fmt.Printf(\"current startValue=%f\\n\", startValue)" ] }, { "cell_type": "markdown", "id": "f4fc0797-df7f-4652-8a22-e8b489580e1d", "metadata": {}, "source": [ "If one wants to save results calculated from one cell to another, GoNB includes the `github.com/janpfeifer/gonb/cache` package that makes it trivial to save and load previously generated results.\n", "\n", "**Example**: Below `VeryExpensive` is only called once for `CachedValue`, so you will notice that if you run the cell multiple times, it will display always the same number, while `NonCachedValue` will always call `VeryExpensive` again, and display another number. So the string \"...calculating...\" is printed twice only the first time." ] }, { "cell_type": "code", "execution_count": 7, "id": "d59e0cbd-0d2a-42e5-8f94-29936130f437", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\t...VeryExpensive() call...\n", "\t...VeryExpensive() call...\n", "NonCachedValue=334\n", " CachedValue=751\n" ] } ], "source": [ "// Temporary fix until new release v0.6.0 propagates.\n", "import (\n", " \"math/rand\"\n", " \"github.com/janpfeifer/gonb/cache\"\n", ")\n", "\n", "func VeryExpensive() int {\n", " fmt.Println(\"\\t...VeryExpensive() call...\")\n", " return rand.Intn(1000)\n", "}\n", "\n", "var (\n", " CachedValue = cache.Cache(\"expensive\", VeryExpensive)\n", " NonCachedValue = VeryExpensive()\n", ")\n", " \n", "%%\n", "fmt.Printf(\"NonCachedValue=%d\\n\", NonCachedValue)\n", "fmt.Printf(\" CachedValue=%d\\n\", CachedValue)" ] }, { "cell_type": "markdown", "id": "5a5470b4-43ea-47ae-a111-63ab77376bd0", "metadata": {}, "source": [ "The `cache` package has many more features, check out [its documentation](https://pkg.go.dev/github.com/janpfeifer/gonb/cache)." ] }, { "cell_type": "code", "execution_count": 8, "id": "892deacf-a02c-4979-827c-59dedfdc0564", "metadata": { "tags": [] }, "outputs": [], "source": [ "// Let's reset NonCachedValue so that it is not called again in the following cells.\n", "var NonCachedValue = 0" ] }, { "cell_type": "markdown", "id": "83c85334-6323-4b75-b9a2-184c0d83ed1c", "metadata": {}, "source": [ "## Imports\n", "\n", "A few things to remember from imports in *gonb*:\n", "\n", "* Like all other global declarations, they are memorized and carry over from one cell to the other. Still it's good practice to have each cell import what it needs -- no harm in importing the same thing multiple times.\n", "* *gonb* runs *goimports* before compiling the code: that means it will be able to automatically add import statements for builtin packages (in the examples above we never wrote `import \"fmt\"`, and it just worked).\n", "* *gonb* runs `go get` before compiling the code. This automatically fetches an external import dependency. That is convenient in most cases, but in case you want to get an external *Go* module at an specific version, you can do it manually with something like `!*go get @`. See below on running shell commands.\n", "\n", "Let's create a simple example that imports a delighful progress-bar library. Notice it automatically fetches the lastest version of the library `github.com/schollz/progressbar/v3` -- and the execution of the cell the first time may take a few seconds because of that.\n" ] }, { "cell_type": "code", "execution_count": 9, "id": "cbfa0e91-0209-48f5-962e-fc43dbc6b5bb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 100% |████████████████████████████████████████| (25 steps/s) [3s:0s]:0s]\n", "Done\n" ] } ], "source": [ "import progressbar \"github.com/schollz/progressbar/v3\"\n", "\n", "%%\n", "bar := progressbar.NewOptions(100, \n", " progressbar.OptionUseANSICodes(true),\n", " progressbar.OptionShowIts(),\n", " progressbar.OptionSetItsString(\"steps\"))\n", "for i := 0; i < 100; i++ {\n", " bar.Add(1)\n", " time.Sleep(40 * time.Millisecond)\n", "}\n", "fmt.Printf(\"\\nDone\\n\")" ] }, { "cell_type": "markdown", "id": "452a879c-f36a-4c77-8c72-7daeeee6c319", "metadata": {}, "source": [ "## Displaying HTML, Image and others\n", "\n", "One of the things that makes working in Notebooks better than using a terminal is that one can display rich content, like dynamically generated images, plots, HTML, even videos and sound.\n", "\n", "We'll follow with a few examples of what is already supported.\n", "\n", "### Improved Hello World!\n", "\n", "*gonb* includes the accompanying library *gonbUI* that handles the interfacing to the Notebook through a very simple API:\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "48c217c5-6712-496e-8281-1179a487ad08", "metadata": {}, "outputs": [ { "data": { "text/html": [ "I 🧡 GoNB!" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import \"github.com/janpfeifer/gonb/gonbui\"\n", "\n", "%%\n", "gonbui.DisplayHTML(`I 🧡 GoNB!`)" ] }, { "cell_type": "markdown", "id": "78f82dcb-3bf4-4c43-8f41-3b8dc3fe3461", "metadata": {}, "source": [ "### Fractals\n", "\n", "Let's draw a fractal, using another fun package: [github.com/benc-uk/gofract](\"github.com/benc-uk/gofract\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "e5f298cd-a260-493c-9c59-dd3d79706116", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "lastRenderTime=1.633473\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUAAAADVCAIAAACpLr65AACAAElEQVR4nOxdBbwU1f4/50xt7+2ES126uwRRRAkJ66E+C2yxeMYzMJ+KT/9iK6JiYwCCBYqYSIqS0iFxuVy4Hdsz5//ZyTO1u5cQn/JzvczOnDkzO3O+5xfnFzTKugPoCAIzwYRHDe2gXV+mc1PqFtocPILeUujK3AnGjbkKND2DZP1rO6D1XVmfYvgt5FXVE7UeMcbEN7Ux1F8aajv1e8RzDUdh/K/4gRCJGyi+EyEAEUQUiH8QpBhA0ZDmIM2me5kMH1OUy43un9k0l/tla/0nS8tLKyINIR5j4HZSv7zSY8y9G4tyHOU10avPzh/l/c/YWVf9+Mpzjh6jQCSI+SgQBCzwAAvyR/phGIvvSP0LlG1tQ/35WNsvPxige8X6/YZD2m6s/E+ODaKB/PTU3ogOzSNK18zQUv/V4k4ArT92zNCbAF6mb/Z4sz1o19v/JnQtbs/wHA29QmNLUzMVrvEhC6EOvWRj4/5GohcQH+VrvD0kBjEAII46vi6IGAbWB+nhfTPKP8i4/MLK3w+GIKyvD/AQQp+b+mRpxRXD84aWNQ9eWsmxaOQTE9dvr3b2PQ9HAupkIV8FQ+03Q2WcQ+kvjh+F0uuTNsQ2WJ5tsLofiC3lw0oXUIIHlO9cOlN7XBLYoNxCO1HeKd+DdDGpNwy0o8C8bb2D2G9zTNlNG4eCuV2Co2S7P4jxNh69Rs6WQieNg658iURzliUOwXGBLsF4IcZCSoyX3K+hFyqdQQBtfo40NUgfDAAiUB1nekhpirGAY7wQ43E4Knz84+EbJ26sXnlux+av1DbEQhEh08/kpDEt8h1pHhqUgfog/+zckvGn5azbXA6EGPGsoIhAFcYE9qSxrmFYxZ6EIvE8ZYLBKiahimEgd6jh0IxhQGBSxTCJsdQwbIQlcRYwodkCv7pdUBGh/yfQ+4cz3j8zdA1oBEaZmUSysXEKjNcavSoPFGVmBb1IPCQJz/G/OkGaouMbFAMp2udmcjPY/h19eRnsqL4Z908Yd9otbwXC/PmnZk+5bOT7i7/99yu7SyvCEMLlv9VWVAeFcABEI3HhmY9iIQYEDDCPBUWEjgvPhCCtSs7GbVVM1ZgyNh1SH5z6CPViNinNYpMsrT+qk6WNsjfQn2pxVpKWuva0bkCQ9L+N3mMI3USXSAG6ls8BWp9lfUoK6i4B1iQyc3LGmyJ6FdFa4dUGbAOSMys9CBiEIsLmPYH6IL96W/28H74WMABlXwjRmsffW/jfWfu27QvsPxyuqI3V1IVxNAIERdeVLgQESUTHmggN1btW2KfClrVtgg+LzFHmqvpD0sPTycwEswUGTts4PqwyWIJ5GlmrPR9OKEjTfyb0HlfGm7CTE2apajzjNTUjsZqazAwskEnshGablhm9gMCqIjyTDFnBP4KE7iqhIxLF4Yiw80Dwk6UVQ8LjS1p9+v3a6m379u8pC5VWRqobYjUNUSzwcc1ZfTHSnUg3porQEkxl4GpQJRBogWEZWJJZS1OJSazaYxhYHzJBLEUMQ/3As1OFLY/Iu5B1a9OWda8pohf+YeiVxkrCTiCJAfEJGhgvtLhpQ//QpsdEp0NoxXgh8a+hV6jDmw6NGqhIY5Wk6mntoSV6TRYpvVEK6nRga/QCQJqUpJ6RaIsWhWe5vSRIy9wYQoQoxFCQpiCF4o+cpmCah84Z26KmIXa4Onq4JlpdzzeE+FBYkBgvFsVgqEOvifnL+zFx84RQQEoHwChfSJqwbrYyyiPksLSbBIk50lLNUSV36zk6ZT5nM/WbAHw80KttHQV6k0ArAeO1R9cfA11wNNAFppZKI2XoSfofJDVeQ7cQ6kYwhPphahCbTTdgCXJJSFawKqu+ykoShJSsEksLSyj+1cEilkEuB3I7qXQv3butd2in2G1jfm2W62iR75A6EwTAS1wLY+3SGGjsHRsXsZSfiTWrGzRjGKaEYbOxHRwdhtVvKoaBoSsrPNti0GJ808kaWNKRoTd5V0faT+M1XmuZ2eYmE1uqEt1bIy1VKam7Bpk5lQVe0yErWVqv9GKgY1+GVSIVvUgnOUMFvSJo4zxZtGNBiDiWcjtQpo/J9NEZPqZ1E9eWNwblrCxxnLWe+7FFgF5NoThnZmhIIxhWpHQMIADWPF85qiz/qEYjFfmaOA1Na0tYWQaCmmkaGI/KjwInW16yWFsyW60tvypvJpEynKCl9AL0o8Xyi7Gb/wH02vPGRDKzuRuojGv7zoEN0zYK8waua/6ZUP9LTYwUGGVmabRYtVc61B0yM16No6aEXnLRSEOvJCpTInop0eCsWp5paYPlaJ+bystglz9TdHqPtOJCp99Nnffwr6983Xl0bWfv6P0sDdO9dFYak+6lHazCzBWZXF6Oggjq2L6ihwOoFzEgNN45MU/p+DMkzMQQAiuHFmBj8zsCPoyxacwAU1dmSsKEkdX+Pw16k4rNqWi85OmNlZkTQxcmgC60Pct8RVt1l7y+hcxM3Kr+ZhLIzJqWSDJe8lBS9KqLRjr0QkRBSl4ugogGkg8WoliWzvAyHZq5Ordwz1wcefnOyad09p0zKIv60nvDWeu9joiLqs3wMs3zHKd09vfYf02Wn2FZKi6Tqyq0vI0UDGurVvpflADDZvFYHTyyZQxLpm0jhvVTnjW2k2IYEBi2fLlW25YIMg1J2njukaDXPIKT9nZEyzzJe7A/vRGruyfKyAzs3u7xlJnJPZhAAsGyDOglVF8SvXF+i2jIsJBiZMaOIMcgt4PKTmMuPTO3al6/8O/w7nP4AWmf8vsO/rYvc0v71a/edavz6QkLl31Y3MRJL8p2v1j569QtLg5FIqIQLlrmAKBF0VPy6MBAwKLpG+sFacKFA0DFAq0uKSliNiS9r0zitPhs7b21TO4fIEVZ2soorb2mVLw79GOE2JmCK6XuxZvbHSv0NoaBW4scloxXpNTRa811Uzi3sdBNTd01+TMDCO3bJxH2dNwDGuy0ABNQNwqcJvQqPhuidUpz2KC5M/vnsTTcURKqqI1iDGgaepyU20Et/632jIt+7t3Oe859v00as+LVES9e+8qIUH0RAOClG1tQP7Rr3eZqMOTh+b/VZvmYQ1VRlqUjYUXQgDxGCPIQgygAIqohVqcbCBAGgvwTlFUilQtinbcW1Dwu7TAsdwox6Vx5RBhW3oVhQ8FwcmU4wTHtKwXdA3VjyO78Y4PeFJZ5dOPSChXWUIGmTSvGm6BnC3X3+BiZgZW6C8wtdTKzhW8G2b6RMjOEBtWRgKu1zVnag8SeVI8rMVxB9LIS0ctCxuF10W8OuGiv8woAAMdCj4PyiDZnr5tGCLo46o5Tvjt99AXjLr8nFlknXfiLdee6zpjZx/2hv+tDX6yqFzAor4kKGPAY8hiKUrOkS9Mi+xUkOUTztTI8eJmwXqtVHrheeFaelUGcVuY388RnJcgAw/RNztuGOZp4t8Bmvjb+GEtAEV3TFofNT+WYodem/6PqwYbxNsLOnNCnKtEtJTUym+cm0xuyurej8M1INNSsPDRsGK+yR4de+VzNEB0HFc3EZWaaRTSdncbkpDENfVZPcY3ZNHj2Cx+XxATM0ijDR+ekMRleumfORk+/8mjJbbpnEp658KlDt8/qtWKbwLGoLsi7nVQ0znQBFiheiL9Hv4deee/m7KtzAc/HpzOEREFaunlBsRFD9ddoPFbdoUU7mK3NKXp6JOTDRO/qV5NRWjmewLvDdltP+mCGY4heu66OGr0JZFTzuanKzCmqu8ccuob5VTcHq19ExkuuUpraW8vMBJKTQ9fS54FwydLQi3VmJMngTDOQdfbrnHmgIlKYxXVv7WEouG1fYNzdl6+bx7TId4SjQvM8R34mN7iiV3mrTUx6110Pntr6ubdDq2eSz+LfL830tKfxNoAgyPDQDUEGQeh30zQFOzRzHa6OFuVyVNE/IfMTjoWBEBNvQxSksQCgakyGgJiRgCYDA9FvUopmUNaTyAAmW5UY6AOYEmJYU2KPTBkmxoWtaG0hSFPQfYqxC7JFKuhNvBJj6sd8GtANTUu0pIJeZZXI+sbMM04qjhk2AjO0+SGWl7M0Slv0byEz6/ol2yeSmdWbhDboJaAL9UusqslKh16pZ9kmrKm+FA1ZV8+OmTP/3U4QQL8Ovit9546dsG1cxuQCYUPbwZdHYyDdS3ct9hT83OTrX/yn9c3q0ufxs3vuWrIkWFaxVfcE96wY2S+CMvrmpLNjT8n8ZVsdQsDjpFrmO288p/CcQVnOHzo8t+7c9TvqMB+DAi89JGU067wtTaMDE/MRIB5RCuI0VPVs0/RnKUuTczc03JTFnRFzpQE7pm1LriBuGoxYuqeaKnot99v0k7ATyx7seV1KjNe2z8ZzXRsumugsK0uVVeNGyMxGUdkwpHQ7rb2azaujZsaridMq71UdmyUdWFz1peiiHMf8JeUPXvswAKD3xu937KL4z31njDk/muNI9zDBCJ/hZeq46KTXhuRn3LV1d9mGvYWb6ZELH1464v4K6W5aND2/e4uNiz+YOuwSl3PDVF/6B92Ki3aUBCkKnlbWy78cNAzavzhzxYq11fJPi8vPvMaE5UlNAACJDFnsVMeHlV+K1SUjYh7TzNcW4rTmICLZw+z4sMrNE8VCkKMCE0xY6QAktEhbE7QD8B+F3sQ9pMp4j0ZmTu1mjht07WVmE1btJn5gYW6xga69YUY12ugtWPKghDrVV+whrhJjPvblqso9B0Or1j7z6bKKL1dWNst1lP3a4l83B56Z0OHSi/vNeevnq688dXOFB4Rnbu+wF4CiS54oAeC6Efdrd7R735y7RYH6UzRlwa/N/9v66zZNb2JoSFOw/z8P3XVRv0u6RCEENJIdRbC8FKzcGBbRK6u7EOtgqT1ZEr5acDDQRy8BG1QrKjG2RrsegRYYBsmVYWAcPikJ0tAymOFPgd6EYnNiU7O+BXHIUmY2dwhNZ9mg11rMhrZGZkNjvZAsS83kWWR7vbORDn4mozE0g9CqJdCpuAQ+CfFb9ZeA2iHCfQLzoVB07+HwLc/vWLezfteBUHltdPL0bad2KPE4opnDXdsOpH3+8YKh98SZ578vKjK9UB317dVs+mc/71v6yICmv194ek7vtl6PE1UHuKa/5t3fd0aXVu52RS5AMSKM1XtWfbABIOMcDB5X0OCjon9K5vamiUxeJdaLKsA4IRJjxjRgIDCt0uvGjHm/3baOzBzYknEkaHWc0Jv0RGWP0UPNtkO76ceGhR7B0m7KliqSy8oys3qq1SnWGpfFTlMQLwY6A7J52BHsmtR41euSTosKVKA6iYg8pLYhxlAQIehg40eH9Bx+qNZ51TN7AJjx+kLw+rcTAZhpepIWlDt6NQCg0+R/rsd9569qddOkYffc9Z2bc1QMOMxlsi91oZ76aP9jv9dj2RtM0PiwNi0i0SgNjHwY63mazIo1ednYEljYqyUpOo5kmMQnRHl3pkBFoN8wCNLamMEgZSYMUfa/ja0Mo9T8LSl6LYZ+apgBjUFvShpvKjLzHwldHXb1eTPIs+ygaznxEyAEeseMhAKzCbrK6Vo6GAW9SqACUION1FQb4jJSlj/+Kcxie7X1ntU7o3JOixGPjgXhlHBrR6MHnvbOM71crS6Z8UPWtv0BB4M+W16x50A9jgRBTErQIYjZtgSsJuiQRoWcrEP04pKkXoscHfIbkBpgQ3YOMrOHluID6GVpIoeeZX4PY3IP9X9ivyF3Byb2J8naoTlykFbo44ReO4Oz1bl26LUTmxPYwJPLzMfKKwMa21s2NoYiQAuZORF6Dd4Xms1JLzcaPCLJj2aLgmQ2SVmzJUJ5od73WHOcVPyfte24XurkKI+TyvQzfjft99C93O8XZ+78YlW18Y00hrbt+73+cHjaCz816zP6ly31P2+tLy2P8LGoCFoM5aAUKOfCUg3SGkM2WvE1i5HuwUJZolDbGBqroFBmPMWbVT/bJrJUazcBgY0gDS0lrwSPRz6mT2p3tOj9Q8TmlBmv9a+wvYekS7uN4rrG10N+sbEzHwXjhbrlKCNH1Xaa2qstsbSMioizyNgjBJDUXgshUIZ9XCEFELgd1D9Oyy7K4WgEs7t9s2/OSOPjajy980O7V+Y+vWh1ZW2Arw/y0ZggGnShLEXHGaEgi81xrijK1YCQSFU3SvkBKrIrViMRMfnA5QehJsSDhMmK2NZkadnvGtumvAF2grSpia01Sx+caHKQRtqxpOhNuvNPgl4ITWY4MxT1PDNJ6F+juK7higZLFZk3A+hn8YSM1xa9VpYqg7VJXPVRWC7SQIjIYFKC04qMF+pj+qQLEU7RGpJpCnI09Lmps5t/f98V57UDs+o2Tbt5fCL2kZT6dhq57024Y/cb9UHeyVIsQz4zSMQhA0JYII3khAJvaYHTfizUgmrl9kQaIK1P3bSoRj4Qb8SSCQP9qwSJmDAwzdcWbYzbyKJ369YJ2N1xQ2+jxWZLf2byFEsoGi59fKELLU6Eps5Nps4EpmZA8lioi7MzQBEh7RJqYzKPJNkeQS3JhvxziJYqkABkGeRxUU2yuKoVk3pdNWP3N7dceuvau152m150I+jsO18+65Gx6V76uhvfHtfQ59xBWWKcsEEvIOzPiMSwctvERGMFY8NfzVdU99wsbNpAXS3XZfOwxrCFmKYHNzSKA8B8hu0eZIO9Pwq9iZVeoDwaMgrfmovaM147tFtC8dhDFySDLgk/pQE0SLk2jBeSjBcZ2C8BRR0XlRwhyThbiJTGBJiJBFekByXSQhqQfArLoEwfM/3B58INFVNveqTzpPCXpcPf/HK58V03hu67rNmmfRlV34585PSZgybMifIYieYzYgKKTzE6jCHllrRHAYAmXBhgbPUXIWDIGWC59gZInzZVK7FDLCBesWmfxdfGMWHaupNjj16rcy11SPNZycXmpBqvnaCSSuNGWJj1uq5VFJH2L7Tq324o2C0UYQAsRhg0mK+U6DqAlAbAvJ5JXhRqqhdC5hEPibFOU/ETojF862O3/tRkyrJfnBNGV+20YyaNpOxhX3Key9//6dm2Fz3OY0AhIECEEYIYYSRmqYVyaDAQBOVxYSgqxqKnNGF8ltacZMgpZmGoFFuBiq1YOkv6ixWjlRyuKHWvPnjZyK2NBsMyks5NGhh2WvhIA/OSEjEubJaUkHH0gj8GvfbeEXboTcRIEzDexDJz4sZQz3WhDfOUuzVxXdIMCkwXUm8Gap1bM95kYjPxgTpBV2mJlNxUykcKvgeUVMFI/EgrQyo3A7Lbk5KejlL4tmx5VhPZ0WLyjGBY2FUaWr21bsOuhnVb52y8+z6X9zLTS28c7XtlJt186qZt03/8sBcv5qikCEMaFO9QrsAk37y0Byk7ScVBGedalg/VJ1T5QHEtW30ahHwOSUFa9wogVOK0tVdsJTQlGu2GfVougZSYMG06aM3JrOho0GtzFtTvSZBGSN5h5GWJ2qduNG4UizZZmPVc145j6+cR3VHiq47xmiY+vYAHSZOMaivW8WekV4CVflQ2IM8UwHiKCABIiJpxzABEUYilIYWggHEoItQFeYqCH97TzMFkBaEfHAW5Tl9UWT+mftudr31xcM328eU1QQABTUliNMaYit+iIMUcilwXw/gfLBml1TBDLBsfANaCH6Dh96oPQVZGoLSSLIi9xbsVRIaJsJRiHipPTNlQrfsY62OS7OzS1v6VicL5rY+Le+hEILUe3Op9JDrhKNCrh65tV2bGm6Rxkis2uqUldEEK0LWXmcnJm9ifPOMcaYOFGm/R22DE/OuyvYeS9xi8EQAxaxBGXd2KsSJUI4Q4FnEMYkQMS0lhIQAUwuOnlgLwPDgKCiz9YHXXnCWTW/e4fs2P66pjPKYQYGnI0CgaxVIy+fg9CqIYTWGAEcAClBJKYzGzNKQkjw4NxoTkrB9g4sNEUDUvi8ESOD5BYF4Rn7Gc+kPrQXlROu8rtTKT4h1tEfygvvqES0oWK08WpyBbhvtnQG8jxGb766YqM8PUpWuYioXZUti2kJnVF6/30DCKzamgV1ocoiBFQ5oBUiILWs4yByk2vpNhAc1Bhwe5/JB1QZoT82kwslAd/1DyBqSgmC5HKhEqZqtjIEVJQibDUC4H5eIQTUMHiygUV4YRBA0hvteN28Plqz+4O9/09htD4ZlXPr13QNvShasqBVF4Zum4uB6/FiUVLpW0APXXxT+AljLp0ZCiNHMdaahDWjyzTq2In85ARnwyDjdkneIDkX4s0okzUJOfSUFGL0irL8iSUlxSsjjP+AXaVSdMhF7LfccHvZb9QGgx6dhB90ha2k8HZhuVYq1M5VzdJQwNbO1VIDX0KrNPfMyJuFWSQgIIsSDIPkoSvGm2eYH7fP6KWcLM0sqIEI0APiYyLqxyDYLfijqu+JWW6ypACgGajl/YwSIni9wOysEiEVqwvDa6anOtr2fnge0OgyMlusXjW++9J+0f4QUrKgI76ikEORa6YijGU5IUEYzASFQQf7Cgc0YSeBCLYBgXgCFQXCzjrJgwTSmII56tYo1nHaf2aep2Ugt/KhECtQBGMB9RuLV0LoKS6UweARpTVF4L1AvSx5wJG4lCsitl6ui1QqZx0wJ1pvnjCNALTZ7DqWPS1vhkMlNZcV2TjUrhjtDiErZcl+Tz0IrxagYqvdJrh15jcW0xxw0NOU9ekxzAcJ2K0wd2y9pSEo2zF5qBNMdwbF4m91HfQRjDu+577PQeaZ+tqOax8guREq8vcSeK5jjG72V9bsbrosQK3bRUYMHBUG4x35WTiwPY54ozZJ+Lcosp7PweqrBJyzbsGv+YVeu+ecE4GJKRUL34xV8fHDum567SUG0DH4mJQrE4pFkaxWchCBk6LsMjhCiacjrogmzH+fimurwLqho05ypomHKRwZxOaUqBWIsc0kxFA/zq4ife/m1IKCrdCh+XzLUu9I5QUDdcsWlM6xQi3aEUmLC1OdrYlQRgC5Z2jNFreQopISdVelMXm+0wmbSZZllM5I9hALPV7GADXWAPXT3jtU06p180gkCv94qZmSHFIKf3jouKZt/B9Svt+VPoulAEcyzdpdjbu62PpmBhNse3ujO74pVDmVd/9N3hQ9XRUFRi0EiuqCB/aJeTblPkWvO0qzKc5nagLq084cU3F/QcCyF0ssjjpNO9dJqbTvPQPhftd9NeV/yT4aU5BmUX9e4/+vae7Oo1O/Ybx0My+vzBrOff/WRPWag2wEd5WUGnEPQ4qQwfwzGi6TuO4bgG7nZSmT6mVYGzfP13P8y77Y2vyhvC0lvEpBoC1XkTEv5qklxNUZJNHlIswzHbYiNmn37RTu6qkloqEgwAKQGIGtgASP5rHolkBiTDaIXAAhyWKFMGj7U5Wkem6oSJTjjW6AV2jNcCvRZ3mRLjtYFuCl0Zw4aAFElmmiyPrH8rmRlYiM1ke9K8ZHBIAmTgAY5FZi442GHryIZwxkVjcrxOqrwm2rXY02LDgN+6L7k42q6o09T5q5lr71p65qmtPE4qxuP6UFwoBYJsHqUQcnLI66LS3DQAwlWwZTSXyhv0DBh67lMr3TsPBMNR7HagW1zdljbdOWh/yy8zt2MM/B7a745jLM1DUwgGS746vOismQtB6lSY/4/vH57bdNQHdQL2OKksH8NQMN1Dlzmi9UGeoeH5p2YDDJ77uKS0IhKKCgBjjkEFWVzbps5bzh24amvolM7+itroso21oSCEcXFaTN+BoWzNMuTK0jxbxAxBFOVgYH2Q39N25UC+7qufq6Q1MywIECGtBDGEWgouNYRIjibCxLBQZGtsaZROZo62WxPWywCWtZFsTksweRxL9JpOSZ3xWjeDNr/CFlrkl5SXhWzuITl0Ncar308EpxrQCxQnPtlKjDU+LBEWDlVHn679pktL98DPOzw6YvTv2U/XBXnmUE3n03MKDk0Mly6uC7J3X9113c4Gr4vCANMUjMaEqFg9G4k1ijgGZfmZdC+9p6H53KVtIoO/qpxy7lnd9qz4fN6pN8+sDfCZPqbz+QE03blqR96oszPLa6KdG/6dMeCVipqon6ng6zeEylcxvlYrnz64fGv+rdN3gIS0/CnPl2ubndV1oSe9KFLxS5qrSc/8cH5mG14AH03p3jG7NjTkl6Jcx4x/DasLsT/8VnjBvf8prYggBPIz2bvyTgdCFNI3vX3X6dNfuP+JKXcdyHtn614+Dic+Jvs7YMs0tHIshmQ14Di2RYFz1oTVXx3I/XFdNUXBqKxN8EDAEGEsKIo0gPoXpC5RYaslJeUlp64JA/Nx6zhh2jDebPv406H36JBj2U+SZSH7uePIbiAJ47VHL2kOlfGsK8OLMQ6Fotv3B3kep3VfObYb08PtrVpxY89nz/ouw5tx/cRY+fTmHk/VjvpMH40g8Lmo+iBfF+CDEYEX4qOMYZDPRTXJ5t69p1Vo/4K7Xt+a/endp3VyOxj+s69f+XKjOxASita0rA1U9Zr+fGTbitqrp3fsKiaL5SZumJ415N81Xz+aPuzeKgDAFcP7v/nl8sHdz/pxU6Gz1+jg0nOAnq5+cuurU/57/auH+7U+OOD2Otfpc98dcOmF89MiG699+/YmI4Z3vXvmlrzcC/fcvhcAOHThSgDA9Jta/Gv+rsn/bBOOCjlpTHXvLbUf5/a7bOfw7v5ho1/64Pad362m/B6mpk5il7wSLYx1KzJAkWJE2wEU0+K2L3LVbXp6V2DojpJQOBhSLNiUOBgQgILs+QWBrrpaSkzYTHomDOxi/c3nEr5dVM7d+mFmxvERoPdYGJwtnTQsWpqYqhUyjXdiD11j4aFEl07RfG3J9k3Qtb1tK/Sqsp9sm1GTRVKQpgHFQtbh8zpaFTjbFrlO6eS7+IycHa85u9x387xJb586ZgJu+8ia7fXb9wdrGmIQAoZCp3TxP/zWnsq6aCzOt+JD2u+h2jZ1TXa3bnbdhG8f/Hj8tBGHD78/sOsInzP82bfvHahL9/5+x/wPP5kwba90s58+kD3moSO3PNvRvRd3fnTWBgDArtdR++dnhjf/CMIzZ9+T9/q3HSdMfZ/n8aAu/urZfp8zMmNxp8e/Hbv/5bm5Z6/++fmcqzf+UFIeDoVjQJDM0dj0yqDyH0RUXPLv1db71j+XetpeE4kJva/9dcfeOiESANEw5qM4FomL4nxMrjwudoiJ5AGydE2oyphcY7cN99eC+LFFDgCgAVgfx6+2TFpa5YSh14bxpoLMpOAh+7SwLTfyuqmw3ATQTcB4VdwCK/QqwrMSGaOCXLJwOTmqMIvNS2euGOY98L7joY/6ffWv179eX4Q+mzkwUt2pdrun9fxITMheliVg2Iyb1att792locq6WDQmMDRyOxBLw80dK/hA2icPfHG41gkAWLpu4cHKMO3iatY8sPLr99yjt4BpOQCArKyLxzw0CxwHktDLtn+x5ZWTKn74KvPU9wEAFzx2MLh/ZgXny/AyWdkT+rUdXB9kV/32hcvXHdEuZ7+P6xav9D8QrWmgAAChiACxID1XJIZeqA9eLPMAKAo62bjCH+Px0yvPPFAeLq+O+tyUJFfL7FaCq8yEoa5YKQBanRTZO4astH5kTFg51ZYJy0QWN/uj0JvE4HwUSq8t4z0i6Cbh9ilyZos2NtC1EZtt0QuA0TsXQM3/ERXlcK+MfLU059Ebzz/VzXV87ZmhwT3Vwx7uGR5JRfj5uf7AsEd/qP2seCuPetxx0bC3X35mwoWVY6veWVTWIHpEuh1Upp+pD/J87eZzHylT81rlZXCj+p/+n8c++b/ZlQDkSDvLy48LelWKbJ4EAJDQCwC4/YJuhdf7KxfdUPkd/caNX4uOX3E6vdO+e1+mv3zt7Hs/qHRxQpqHhgBwDIqLFRA4GFSYxZ7VJ6OkPLzvUHh474wPvj1UH+IFIa7zux0UQ8OGkBATcCQq+N10po+pqAWQZloU5uzcVgIEHgtS5gCoGLkV8GH9sIDKP9gyoaylJiwfJ0zdiQNC5AbohKHXNn7ASmw2trRZAbJtoO9BWwfSarQTVyKDCjS0E0vZKopMNwahxeIQ0YZYgSIXhEm/An3AGrRDr/Yx6sPihoOjxw7M/PTDueUf5d8/IXT9M8sDTe92Nv/Hgns+zfSF+t2y9669P346/LLRZ91YXue8/qwNLXNr8k+dUV0XK8rhmuRwrQoc3Ys9p3VLa9vUCSE1+bzu5EtddHjU/81eC04c/d/stZWfDezb+uC82V+ec+cidf+of7/72oKV0RiGEPjdVLqXzvAxPjflc1NpHjrTT+dmsONOybpU6P3xwx3XvX7+TecV9uvga5LD5WawuRmM303npjO73shtme/Mz2B7tfV0aenu3Mo/KnAVZByihgI0f3KAibcgEjFw5RSW5gO2lKyNkf0o/1K5d1ufb2eCOkL0ittHYLJKlfHqWKvpKCTOlrdt6nSmeK1G3pIF1yWha7hzUunVfCrlbSLCHihxv3IIDlTqgNGs0+Me3NU/74lpj7/xYJqbdnCoRb6j6c8Zj33c+7UFK+XLcRNBeCbX7Y3w2gnQc8PGJ19rNvTlBSWjgxGhSTYnLGw57OFzQHhm5bKrd6yc1WdyA/hTknT/ypeJw7vtufuVuet31QdCwp6y0O7SUG2AF8TYQLeTys9kz+yVPv60nJK36Ze/6jzrp7Z3PDdtV2lIepx+N922yHnhkLTArvcWlpztc9PNfs3dV+4ZcFt59qjvhPoKHAkBIYZ5HmAeSP5tGMuObnplWMlpqaq7hN6rfVUnbvusd6QmbFSDRdYvArgx7Dcl9Fo1boTJyv5aRyI2GwXXJCV2UwNkis2M608pQhcAE3pVbkyWSiCCBwHUiuKLlT6z0x15mWxuOpubzjTLc3Rp6W67MW/Br80bwvS9b2wBenIOnNf84Fub92ds3/lCTUOso3vZkjcvfmFhl0+Xfj+o2/DV7uuCS8eBPz29d2fh2RdO4IsfyMi+NrjzvGjlugeX/GNPWTjKY5qCHgdqks11auHO+7ntWW8+vOaW29tdsfenbQ4EwZQrxn+1YsGP62t8LqpX0/LPnhjwnzl95n3/0YvzDyzbWLt2R73QUIXDARwNi4K0khBTXLHDKnSNpiyoxJUeI1OWAcBiS0jl3mN6DicAvRbyRiL0WqJFDw/dhKAIPbo0rmboprBKfGS4NV7ICrpqG7klVIVuC56sJYUi0k3IdXoZiCjIsCzHZnjp7DSmaQ7Xq623b3vfoLbRn19u0e9f9cCGVkzz9LzyV8h469Y/8uOC2WMfPmTX8s9MXz+a7nFE+9/zj737Xvq9NDT/p/JQROBY1Le9byh/WbuLMuhBN5bNG+Do+9G268Y/9nGv595+Y9/cLlsPpA++6P/uvO3F4d33dC6qyDl15ow1Q79YUbl+Z0N9TV0cvbEQjkUAz5OGaNmHXFumIpiwnPiO4LoybhMBWAWx+hVgoAntJlu0uTLDnwe9CZReK7HZBr2EuqvXdTVFl1RxSf2W0HB0eqZtM6hzkDa3Afq4M4vwI2C0J5MeVxpPVj5kjivVKVo2nERjQozHcYUQAOHrM1+9fVTN2vvaD7kV2NMpz91bvepm2pX/0awv/kfRCwAYdm9V/9vqQXjmdWNHNs3higudLfKdHZu7n5g0Mfvsgv9eshQtfxYAMOiUts1umbRkc8E3L5za6iph5KNjOwxZ8NKirnvLvY5xwdLvrry84IG49sFKGBEAJrAEDTIUNKucFuMamr+Qkpe+Mbllm+EEGjjwH4zeo1F6bTiz/hlB+RawreHX9twElzY+hxT8tHDCGybHhMJ4AQBGq5Wab13PfmX5WUm7AZG0/gEpOt1HZ/mZlvnOaZNaffZwh0xv6J8zLhQqpwEb4rq89tk/7jxzSqVdg/8tWv8C1/Ks6Qcc47fsDfjcVB//15dPeH7290sMzeq3v+5pfSUAoPy783/8Zkm/W/cu/qWqPsTnrOp5qM8vew6Gn5+zB9dX4lgkzoGxIErRog6MFTX4D5OidZozINPKSo0MPy0xeo3D2KLxcUcvtAKDygyB4lJKTJMGrgtMpl2jk5PVHoLZwkTNsAXLNV/UwIoNhmUjeiGBXnL1yJDUTsqOCikEm+ZwDR/77np3oH/chgToBQCcnf72Xwa9AIAut/3T03pCm6au/h19gzsyS2dd+zm+y9xMQi8AIOu0ORDiR64cuG1/cOmG2u+yl1AINslmQTSECQ8NPel4q2G3nMQDWDIM0wk6AJm4N8a6Ya8Q6Upp4q6JyQyt44heqwbJ7FUS44VQu6KR15FnJV8ETsBpDcxW/14T2LFMsw/BeNXpyYBeMvmGrmaCkilKTuZEi9I0gjAcEXYPKBV6rZnz0Ki4nHzTmp+e1y0LqTT3hx8t9/+vkljbpXbj/wW+71bbdOwjc/oE14yya9ut3egrH5t++IeBAyZ98emy8pLyyKGqyOwfDtfXBTEfBaQvl0TGlVpz1nVi7FlXGD0GC8I0cYahA8OmvkHj0GtxLkxwrvESjUKvWWy2lJmT4ZnsK+mtAqxThxp7/8pFoU7LVTg2NqOX8KPUDNFKVjeoJM0QU1gAAEorIz9tqGn4+tTqhiW3vevueL01ev+q5Ot0OwBg40s7I/2XgzVf2TVbu+Uz39K1zSdsWLS6KhTBVXWxQ9XRaDiEpYQHRlLeSJzHku5WykFN0NUsWUnRmFIbq8oMZtWXaA2OFL1G5wrtXCv0NtJkpbXUcVErsRkAg8xstwGhXjTW5yK0FY+Jm7cWv4GFNG51UQBMQjUGQFcwAarbQM35qi0Cy1H4ACIHixwc4hhIU5AXcHVd7IkPS1durpv6cS/PiCWAm2jzvv+yNPTBc5a/1CNxm+Xb8jL99A1jC/IzWSeHYtEYiMWAENNUXJUMQhW0RdCxlKJ1W/IGMt4NSMxqGoNeq3Mt/FagifEabtcA7wRKr7hTs7pbLqsaoSsnOtZAq4GEUJgBMM2LJr03FS0a6K4ODdDVGaIBsRMREUgketWksGIuDilBFEW5nbTHSTkY5BTdA1kaAQh4HlfXxx5+65vDM6rfn/xl6MA3gJuI0ieDvweVHfog8bQF027p37Y04+d2hU2uf/bi/RyLxJUgyViF7UrIEyPTOK5VidDugqa/VsfJLStbNIW8g63PS45eK/aYDL3GE83otejczJkhABZx8FJiMQiALZu1gK4+uAcaZzjickYrkeIUBS0wr2ts4uQqbm0FAWzg1TboRZLZWcrnBinG52X9Ljm1jZTvxuem/W4q08fkZ7J5GWymn/FRB/P4L7759KNPaq6O7f63eUz8ZYlfk+hoaOXi38YeqoxePGjbq7uvXr21LhIKA2nJV+A1XytAWIYNC7byqCHlMr1eZxztpg2b78QR4yGbaKQ/Br3ADr3JxGb9syBNVnIDA+M12IQ0hm0KnQcAQKu1cYtNaGpiOfuQ92mYjEy/TtJ4MQBEyXnCKK3MLyp6KVpZNIp/ctLYx69pMW9Juc9N7z8cFjB2sMjnootyuPbNXLdcdOu2XW/Xf+xot3Bpx70tv1j2LQBHm3v9r0Qrpnk+/XntTReEvuB+3LeorD4Qk3mvQX+FQBfwCwg1WGsh7dDiCo0ZZUAqyrD9GcSt2GSlTPFrSug9rgbnhCYrcvUIkJ4SABrEY83B2PLHmn+6zcOBpn8SmKAN84tSy4O8YWhg74Bwfhbzp8YZL6KdDsrvplvmO+6/8totJelVP3r/s/qmmgaeoWBWGvPY/W8WDR7Rq1VZdoepzdC43/f0e/b+nC+WJfqJfzeC3kn56S91unLxU9vrV28p214SBJg36b3iixBDEEXDFNSmfogh0ExVxCmkHxWBQkOSDfIEuxB/ddEYQvt1YPUq5l3Q1OKYofe4mawA4e1EyKKQrGpHVvSSMwBTQFeG0/QBBpFYk5aV6n7EVaAFAvUSuCKSGTRng8lK6QEiNfUcDRkuO8PVuZWnTRPX6AGZowdk/rppDtd+0O70R1rkO5rncU1yuGa5nCew41BV9IWPv4jtu//CgdsAAP+7XlbHinzpl/z4X1+HVuPeur0J2/6FyL4bd5X5vl1TvXprXUl5uD7IYwHrQsQAwQw02U1jJMpfcgDLDUgBzGrmJ5mN+WgSopBnsK6tDQiNvTYavVDPPKFV51YNbExWmntzYpMVIGCss/QCzY1JzmhhgB+hHxscJBR86tvpF3istwl9WPtR+kVdQJZEQXq0q4kjxYTPDLf/wXc3f/nei0/fhjG+fkxBxrLCVhO8t3acPuyC67wuumkO5+SogizuySu2fPfeBxW/Tluy8dCSDX936EoUDq2HTPfXb/im/zUrxo0b/OUatCQwobQyUlkXq67nAyEb1dfGe1khEgg2MDYdsCH7NvqJQAJwAvQmcydMFb3qv3qx2Rq9ag/ExEYc0hmcicsR6IVG9JLuTQR6tXpfRjZrBVq1E2TNgYHBiI2gxdOTf5C+cjQkvayQ0RNLKXekCM9y2tf5Owa8MfoBumTGodVvnjJ+S4Yn/M6Etwb2TPM40dI3Lj7vUW9gxUOTb7+GZrg+jof/+cQB2zHxt6Q1O/af0il3wcefFA+69kBFpKwyWl0fawjxDUE+FFGSwpP1DYGUs07+CnVpbgz54o2kz9Eh/WsHUQtI6I7oVkZIg02K6CW3jxK9wHyrxM+D1ofUB6FkD4NW6AUW6NW4t1yfXgnfoeWPsiQDyOp+pESNSEkb6YVbZCXqA0VmNovTFsWmobXYrDps6MAMIKxt4G/7fePWNlv7FJeB8Mz/W3VJ1pCPCq8Z4+2+dvm2vMiWmyYNXx/85QZH0czv85Ikhfx7UoxHd762tUXgJQeD/B7K7aC8og2fY9UcvYqrDACmN65fGgQGfALdRgpwtTjXDGfTYhKk8qYQDVJAL0yGXp2x1cSxjT1bNWiUwZlsYEYvMEvORH09hCDNQtYh1rOSo8PE3yXFiBkCwSzn18T3b/rhplcCyfYmqUHdJoqGirVOKBpSbIafHdI97Wq6b5s2TQ93WfnlYz3u3/xEcOm4+T+VjzslS+ry2etbHa51PvLeRtOdnySFxMQG735dtnVfIBLFDA3f/brscFUE8xEQi2JBAEJMDmDAghxOiMVtQYgfVc1dalSDMb7fEKxPDq0EgQ04lfh+hQNbTBBHiF6jq8YxQy88ZuiFUHNgoplT+hc3bdUUOjyQ4QDNAimro1w1S62da2a8EqKgbj9SaudCTTjXKtAirRa+qkKbWLGen2voVQ9pvwIhWFUXW1m0MXPI3M4tPef03YnDDQAAFb0AgFvfOeskepNQeObI/qf37+Db/f4//zOx+YCSXtlpjIMTq0whCsplhxU9iyIVLn1SJEi6ZBl8csCxVIOJ46QnllEGNnaUGnp1ZxnbWBqc7U1WBBqtl4tINmWLXmXGMhmEpTexdF35F4MHsh4fFMvSQdYVR7JcrU+Fn1LhGiHdR/ZwRDJQ1SLRWu3shAZtnQSO9KK46j6pk9JJ47Yg4IOVkZWb6xCX8frkooKz5i44b5Jz8OfkWw5UHFWZz78J1QS4f40fMWn4elerx1haaF3odHHyWp1cI06qz6jWfEQUUJf0jFK0NRE+lSolh7GxhQmVlsEMVo6dxwa95gY2R3ViuGJwto5PIPK/6dGrnq5cUf4YYvEAgNPqN114OmhZ4Jj20X6EAE2h8oOHQSwixnsiucws1Es75l9BWqTILMRYn10hwfvQQhfIRWDCF5pANRJZeDSG64P8ba/Xtj9tBZsFT7+7GoCzySs4Ocr0Lk+SkZZuyQfhmZ/8BACYsqusOZ0LPS4qHMUNwfibwBBBLAAk8lhBwNEQloRkXlA4rT7SSLfYq25AmwaJVoOBVUdk1RVkg1X9F3VP49CrZ60J0GsUPIhr6PNpKD+PGPHW6FVuSqdJ6tdalUM4Gnzv67J1O+udLDp3UNam29+JxQSIGDE3DQ3UWB+pLjZRvE9hwpQqOWvFwWg2/pE8pRBRQFCqr00ycEAKEYCwZplZtGZ+AxAyonBHofiTqW2IlddGeTqn1cUrnYM/H9FvqOmlnqSEFJaT5i5/yrNsS36Ux3437XFSHheNaLHGsmgryczyPdlpEnKnQ2klT+c8Cy0i0khKwG5JbtSoExVfaB0Ujaeq0Go0es19QqNsbDwKDOiV/hXLZyttdFi1Q69J9VXAA9VVItkKjSCiMUShKKwJ8NSSq+dH/rP7YDgaFa0UUOaDuq6QebVJKVEpBQPRTFwOlyEqabHImPwVEIEN2qKUvBxNWMLVj7QIrNSkpiiXQ7aaZvqYDC+T7qGrG/inJ7W6se1j8xbXdmjebOve3xO9+ZNkok/uzxl6T2VlxqjD1dEYH1eDKPGVsjTFcZTbyRRmcRdMuPPXHQ3l1RHAR6WFYnJtCUADk9OENUj+C1PEqj12NQ4MTIgltw3oNTdrHHpN+LdTegmTla7YTKPRS4iy0BgMJB8Sjc/RGGZpeMkjn/rdtIOBUt13EUVSnkcZNoCcd6V62UoxTiAxbYpBnHvimGbZOWmQcUCKkcrGay1hArMWMi5iybMAUA+J5baRk0UOFvo9dJNsrmW+o0WBIzuN8TgojEHd9ncW/Npc8rg6SY2iD5e1pgvub1XozM/k2jRx/jjV17WVu3kuJ8WBNM3miguc5TXR2Q92QKxTW+GTieA6OmXQzo51LMhYoR8a70betovOPxL0QuvL6XmytJXQ4JwUvWrPOn8MTcPU7YEsg07p7B/ZL3Pt847Vvp8q62Jx3AIsrhkgNfsRNEd1EYYxsUYWm5nmuDjaI3P4hjcWHqyopkA0jAHZiSnnoFmh0BR7pIwJpC5Tc2yc/aZ7mJw0ZtaU9p4eM8Nbl61a+0yzPAdLx5pPxDk5wYv+e9Jto9E0a/HStpc+3aWVu6wygjFmsu8ueXP+N302fb68QsCguMD54IRm5TXR33YHsBCTBg8mI2SsFVqNMBaOIKrBuuSKsmV25NCfmhJ6oQ0+7dGbXOk9GvQC4yFNwTDwYYWtUTTLwE2/N6zYVPtMw1oMgJOTjMlxjgo1lw9GskZqvh+SsRpK/JmFDOvzck1zuDnONWPr2k++oNDjVpRhVU/WDNQ00AJ6KU3ZhqpLtjS9aDozhJCmKbcD5aazLfIdPVp7BAzCW5fVr+vdvaDUF/h+cI+xAIBDh95PPCZOkh3N+09Hd3jdiKzXLxyay7bq1fK/0xzfd+/f0dexuXtwV/+VIwev3Fx3wzPbgSBAQPAJo0hswpKdbGzLke0yBBBio0jqOrCl8Gzgr3boBUa11sxdjRzG+kKE0gvsl4uSohcapQA9s9Ut30EKMlxWuqN3O2+bpq4vp/bnBexg4zIqzdAiLBlxcZiRV4blvzSxzCvqveIaQ2aac8KIvJ+e79Zl12nucyp2lYacnJwjEqgnSmtOWkUFg8OzereAdN5QFySdHMr0MXdkjpx5zkcjqzs/fHnX+85ftXzuPYy/7bQpt1w59De7EXGSUqHuY97fO6+vr8vdAIDIphvmnnP7kEGtbh7t6NfB26apM90TWv5brcdJQdYhqznAchFUITvcWreDtm3sJW/adBzqdmgaeUL0gsT4tDmqO6St9OrcMC2Qb+84qaEXa8IzUCcYmbVrKzSiKWvC2UXMkvG9Bi7M8NJtTv/5jYUHD1dFAyEeIdgQguEoFnjFvUZcvREEDAReq1gJZS9llmP8HkrA4NAXfVpfsfHtr8p2HQi5HVTYjesCAPBQ76kDZPsHtlqdgkATFgjbG8cghoYODv1StGy4Y0G/u//h7Hl28Bdp4XfmdxsLF/+82PZVn6QUKLz+qtZXa1/PfqD8xnFBxxvD7ricdTjOnnJFuLxrrttBXTKsQ5cLyUdtQJBlSX6rVuavjYwUpvX96iGHsfGqR4JeG8TqUZea2JwIvYS3MzaJyoppQWf0l6Nw3/h8b1bGS8s/LunY3DW146UPXvDeda9wgYjAUNDBoqiYG10QMITAyVHdit17y8I7DwSDIdFMLd8UYhnkcSCPg2pV4LjkIf8tz0UhBG4HSvPQAsYMBRtCSKlzSXjGAYAFo8e87mdqjriQohDLQJaOo7myLrrHMQGAX6Ol2wdfd/OPz3YDAJxE7/GgF+b/AgAovvTAbw+MbpoVHdMDHqyMDLl1HcC8VfME4FNy3tmWGrU+K1lWSmvDmM2i0RGjNxWxOanSq+00Lv9Cw1ocNFibCTAbrA5YALFIRTUV4zHLwLeK5o79sGWz3B2hiFDvoaMx7HEiAYOSw2EIYWEW+3y38beu/6guwNcFYuEo5oX4U6JFqLsdlMdJVdfH/jFge5eWnrwMdsl6Zt2O+rIqqjbAH66OBiN8JBqXMBACDI0YCtYFYoGQUi0aGMPHIRH5iCjEMZBjEEvH77u6PrZwZcXB0penXtX/NP9Tf61ksH9G6rajzcUP3RUL7L/lymH84NeqKmpE66ZdsmiRkgO18Xk5TGTKyAGPM3oTiM2QbJNYbNb2EKqyAb2AYGIK+8WS1g9JHSHOA/lobYDiBTCisnXzayL30eCZOQcyfXSGj4nxOBjmf1xXEwgLTXM4yHgLstjD1VEHh0JhIRoTeAwQBByDvC6KY1BZVfTcO7esfqHZ4CF9ccni/mNLd5eGvpk2hm3zSlVdLBLFCAK3k8r00eyymw90nHagIlwf5KMxAQpY1P2x/PxVfR4imoIMDTk2vsExiKYRBqCiJvb9mpp7X1+Rk84e1RA4ScmoduOTG/A1GwDgXbi8+96fV1fhWFQJfUmxD01EbhT/JU62rv1NIe+pyj6zrqsTgKFRALaHqCUCgSkiX0EvYTs+GvQSG1AXXqtqkoq+SrgWy3nhoCgGUz/zN6zcVDu0ybLvXrm8/9nX96RnLH510lWTJo/ql15eww/o5C/wlJ/WYvcvhzpyDGqSw7E05BjoZCkHhzxOyu2kvC6qvDbaYuBtxb0vL74u56Huk3r0GnzmkKLVpS0xgE4O5aQx7w0e/48epRdcNPKqi0a8u/gQUJ3GIMJAiZEQl3wphBgasTSS0Otk5Wx16V6mRb5jYGd/k2zu9nFCWqxs8ZqKRo6Kk5Scbj6n55k9M9mqL3a5r3vn67KK2tjs7w5F6+tALAL4GJZikgBR3MyQ404iaPvFZo+y3/oIiVBIW+y3MFyZ1VdLiDZebAYG92aQTOlNynuBSX5WVF+MCXsv+QvEGnOCcKA8Eo4INfWxy2a2yu42f96S8g7Nr7j66dvatBo/5/YvrrymtGrZxLYXMhu3vd2pxaE0D/3e/f/seMkre8tC4SiWmKTfTTN0XM8NhPlJ4/o9f9qhprfewBYH9j2w7F/nj39x/oGGEJ+dxra6vO+h1QN2ovGvT9+V5qYFASMEHDyK8gLPi6GMiq6E4qovZChIIcCxyMkhB4O8Tio7jfl1xoXZq/bmjuwx7rbwT2u32gyCk3QkVLHk0pJ1swUM+n/4wHj31PZt/NN+OLxhV8OC5eU4EsJ8TJafJUHJHKRgTxZLwSnK0TbNDFZoaIdeSHak/ZPILkWeTrQh7VVa6ySMV92pYFK/YmSFXqDGLZCxhAZ9WH6qIoZ5PharC0JUHRUwqAvw2X6GY9DWfYGzuu1xO2IUl+7yXbbpmXc8gesGd+3VIWt/748+/eSnCp7HoagQl2xFTTjTx+RlsDnp7PR5i8rmtY/y02/5uHb9ktmFlzzXpqmrPhjLz+QmnLap5teF4W4XuBxUTjojYMwyKBwRIlEY5THPi2UpAYbKr6QpyIrGZ45Ffg/dqtB5Rs+0G5/M2Vnmv/ypTy4aesrT1xVPnn4yZP+YUeagd36fCYXhgedaVG36/Z0rVgR2HghU1EZxLCoWB5YqA1tFp6iUooOG9ddG6MaQKngAgJRV38ahNyHjBVbnpsB4U0WvbuFXS2EHkVbRTw7ypCgIKbGwPQMpOs1D+1x0mofKzWDbNHFNvaowGKXZ0NYD8zre+NqQU9od2LA3c/qLEzZ8NjnHH8Qj6ub/VIEx7lbs4Vi0bV/Q46TGddjM1+9+8qEnYwLsO+n70QOyPp6Su6vM3/+Wn0srIhk+ekhn5+EvB4+5K+uJd2fVNMTeXlRWF+BDESESEyJRHIoIMV42j0nhCiKAEUtDr4vKTmcnjsh9555RNCW0u2z2HRcWpfimT1Jjac/B0IKVFd+tqd55IFRaEampC+NoGPMREI3EYczHMB9TihVK+XekjxQ5iC3rFVoUDQbAGN/fmMh+wzKSSkeMXpv9jWK8FpA2G5xByuiVTADItIakGLdUSVpMxRGN4UhMiAlUKCJU1kafmn2oXZFzcJfWxVOf/nHehP4d/dnZF7317NRtpW0+W91ix2WxLq3cggCmXjd+8bK5LfLSw1GBcuRun3vmgaquMz5fBd7LAgB0vf730qkd+7X31gb4ugAPcJRyF63c7uO+bdLugkPFhc66AM9QcNoNTcdM2VZZG43GcEzMiwjFJNC0mITDySGXg3IwcMOuhkXrik7tWLLzvfOOdHCepCQ0dWK7759s7ad55F6szKcyy1VgdLQGZCPZ8t1EDJmIBzYLz6mgN6ni2oiFIhvGq2ybwgkTohcYEnGYUW3sXyJ10oRxOINwNK7iOKNb37/g8f491gMAvrpvfo+bgwCAU7rmXH728Fc/X1JTzy/47J6zTjn3cK1z5g2La7udG4pSlzy6aMbnaVKfrQqdnz2Qve1Vzpfmz+zzHMq9eO3zjv9c2OKGV4e85/L3an8gJ505b+j1q16t7nnVcwiCuiAfiWpMmEaQZZCDRSwTl9IjUTxr4fQBhVu4nP4JxsNJOhq6e+aWODyaT73wanEJgEH1UtwohLrSZUY6BitDjSJIFT6QHL12PDaR0gvJXlIosW05F5jEZp3uavD716NXp/oiIjGNFmRrKopNA0R7nJTPTWX5mIIsrkk2W1zoPDhnxO5Dvtb51Q/PG4zrX1YvnjV26f6XA+GyJcVnbv/t3bLc89rh+pekBEsPXtrxg6VttuyaJ7X85xkDPY5om4Kq22Zsn/XvguoG7oYXdqv9VNdH97/t/v63JqfdvuGj7w/vKQvVB/lgWIjyWOLCFIrrwAyNvC4qw0e3yHNM6PTVzKcfa9+kcti9VUc3AE6SDXETf3/5jd/al3+8pHxHSbC8Jlof5MtrojhUL9qxpHRZsThw1HRZZGYsswgtlwKXzKmqhJxKcixgUfVb+UMh3xACS0bgNRK9RtcoiXFiA/xIHmsEqt77wig268Om9VxXx2MN6FWzcCCoBQNr8T1QDgyGCCHk5CiXgyrI5IZ087crcrXId7756qLz+++48+tr+LKp5CsObJ3ZiVmMqr4tzqsZveDZTsLC0vJtUgGe79cfLq/aorbcsGvfL9tKFv1SCQCYu7RuT9Wphyplu/F3j/sLMqIulwfUbz779TOuHZ1fUx+jKEih+IdjEMcgB4NYJi4/+91Ubjrbr4O/uPur9SH21eCMhi2vH4PBepLMxK955hNw7U338AKuaeBpCmb6mVf+1WbWd5U4ptRMIoFqThBtSXZrQ8lIxaGBKOQ7zZ79NhK90Ggl1lUbs0ApAOb1Hn1XEEJrpRcSYQnKV72ETPJeSOSyUJZ/lVR1ZKA8y1AcI9qK/Ezvtj7H9136FKy99b1eNw754dKeS976JmR4fNsOnb6jNK3PDd+8O6V9HL2pkYpeusV/M8D+F/fdc+M0SDcc2IjPeunSPdVCs/wMFiIovh7RgsUgJ4s84gpwQRa3973+X678Zu/BHSfRe1xp/zuOfGrN53uH9W3vhQAW5TjennIFaDastjYA+BhQuS7AJmdYnBDC9t+StTbvhVThg+JyVgLVNwF6rXaqSXAsA/GPRGbW/w6j0gt06IVQydRn6cihZEhXACwJzxJ6KZp2Oym3A2V46Zx0tk0TZ78OvjZNnG2LXNULOqT1ec5ZeFaSx31E9PInJU/ceMvufXNi9XvLvx394Kvs9EWd5y3+79odDbUNMUH0sYQgrv2meeIA7t/R5/ulX97Y9cfjZk6SkbiJvz75vnBW2Tt3D3ngtu69X7zmwL6yuBQdi4jpZgUlskWQyibpQ1ZMIrTEhbC6eEkI0hYidHJDNDL5daWMXkhyVEJsllwj1azrFjKzJTc2y8xAz3jVuzMYk6X8rGSaGxW9StJALQGVUt9AzXqh8N44eh3IwUAXR0mOyqGI8HtZaMeBUEVttL58x5uPX3fOlOOSn/X6sYW7982JM2RP0d6dO0b1+L3htyFZfiY/g83NYNM8lLSsleaJc2C3g0rz0Ff9N/PiMwYej5s5SUYKz+w55arWwWk1Ae6Gb247WB4kln+ArjzDiSA1rawCUGsh2bTTQmxWkuBYwA8a1V1ouxMarVAmSdvC4EymmASyH6IuLxxS5gUlCldSjKVFYIp2OZk0D+1z034P7XYin4tycoih4+1oBEIRofCMWcO67B1aNYZ2XRGtOY5uT30mN3y1rlnmRUxXOL1rsbtZLpfll+/N66IzvEyzXG7XzIxVOY/OWrz0+N3GSSIJ1z7/8nPv7zzof3ly6/gAF0jHSTNwU4DykenBVoRsbFHkxUyirJW4q9rWCMZr8Hky6K7GnVbQNTFe/cfG4Kyal5GWwkpJYafUIqSgkkEyw8d2aO7u3NLdNIfLTmNy0uJ8r0k2V5DJtsh3nNotrWV2LFK+6nCt88Y3zogF3mT8bY/Z47eiF+avDv180d4l9//4dJ8BHf35mVxuOpPlYzJ98fnF56IL0uvPbLj9uN7DSVLph//6azc+tbPMP/uBvWfesR5HghgTfpQSNTo84ZiRLhqJUI1tsWqnrCaq8Wm7uptA3cU68OusXIQvtE4TRprYjHQFRAnTNNKyTCl5bXxueszAzPHhNq/GNpdWhjkGFeU4Jo9hFm9km2ZzD1zW70Clu6TjM8tfegqAGcf3bShE5U+Zt/Ljj5a1viMzdiiXq6qLRWKYoaBHDJYomABG9Xf8MXfyd6aqFZNcPZ7jvFdP9oyNDRo1ZF7t3hIxDkkQiEUjYB3A0DiySg2dWoeiEUveVCzPjUCvvFCkZRNI9dyk0DX1YLBXaRq1XulFcjYpJYsFyfPlogek2ZnjmLwMdmBn31tvfl+6dOK8JeXtmjkpBLlv8hhKKB73mbPlB2rS4D+SDi0clDNiyc7X0L3vD3jojUW1gRiC0O+hmnlKGH/rP/5+/m7Etn8xsnnSK58e+H5d9a4DoT1lodraEI4GQTSEYzHAR+W1X50fpaQTq4W17I1Yuppb6ixAGrGIeSGJEUsict0oOQJV/VO2Vxn2J93QKgNZCMym9hCReq9yllprG6jWZs22TDGQlgodsYBi5SIpcg0UWit1gyiWifdXXh19dMpIV+2inrtantLrX/Crgh53XLSlJP2em//9/UNzB3Ub/geNGoJyRizhur9121uDnp5U1iLfUZgVF6Rz0lgca/jjb+ZvSJHNkwAA5TXRUFioC/J1DTHAiyGEIlyxBk6SEsb3N4qMSrKt0kwbj0P9adboBXp7lW2z1BaHVEUXGa+rbwwNC0hSgL7FGi8NGA45PFrmKnWWkc4lUkxxDEII1Ab4TXsanhU6d+69P7hz1cix+0F45gWPAQAOPv35xKvP2Lhk7ZG9h6Oi8JrL5wOQn9575qOzAkuHIy6TD5bWbpt+Am7lb0mxQOmLC/jcDJZl0J7SYJzlCoLOvwqoDMwKt6krxrqUtCk7Y4oNRU+sRMIz8RWS6IU6e5UF2zRzXZPNydLCTNZfBdpaLiSVWONaEVFtEFGQpiHjeH5yu5KKKIYUxdARHipVAimRDcebcSzl5BDLILeDEt2MEUNBv4du616dXv9+XaTvjhLR25Ff8+v2klTfxHGgdbF/vf/Sec34j3G0NlazJVK+6sk5g0H0lxN4S38T+mzutpfuaRagWtyQMfqltaP5SBjzigIsLfmCBHH8torxsbNAA9mV0uhmbIdehQ9iudKX3vxrudIDVWmZhCUAwCQhw4Tl6oEu5SoAWrVlxUdSzfAsJ3NeuzM4a0r7U7ul7SgJhiKYxxCLl6AoimXi0HVxFBdHL3IoTk4+F5XupTOb9u7SInLda8VCzTfH9FEfIQlVi+Z8UH5d98cQ443VbK3bMeuL1UWV1ZtP9H399elg+bYb+iweNq3vEzM5lNMSR8OAj0q5HzQnSiA7bwBJvdUAa8tFjy2Akcm2BHRfLdCrF5st+C2ywB5h4dYhlixTQuyERq6rbADlrqRL6Mp8Qoi0ekW8gF/+tHT9jH7ZaUxeBpvupdO9dJqH9rspyZbrdVF+N+0SM9F5nVS6h85OY1wOiqYg7Wm+7NZHz+xzxjF91EdOQuiN5ndPCex8O1Sy8GC1e/vvH5/oO/pbUK8OZxdePurlntfUre4v+l3xWgl4TGi8FqJyan7RR0JG+NPQcAwSCzwktxRhi5XAPj3jtbcS69ZyEUjmUwkTGJ9lf08EoD7iV5OoZf8qCfwt8h0XD81pWYRv6ldy2YwCCsH6IB8TMASAY6DLQTlZBCBgqPi210X3auu9qHfpvlC7jPIX3T03ndOn16JVf6IsrfyBh/Yd9Li58rqg60Tfy1+frj27zzNzl3+7prp3W++rX5RmX70H8/ViHlmsycw6GZngvEezJpxQ/9UflL+JwQzA5BRpEIxJLdnkTUFySB3blM/QWZi0v8jIqyG5UyvJqYCZKLepK+EntRGLa0vrulKphFAUrNvVAJvf0L1L5w27GsJRTFHQIUI33UN3bunp3c4X5bGDjXNgv5v2uelO/tXfTx/Ve1IzXP/ylr17jvw1HB8qyitOd4cPVHrmL6890ffyF6dftpX0GHbTgpWVj8/a+8lPFTgSALGIlH9DkZ/jghGxBJMCyyVSSh5DIgy/GuOVdkDC5qy0gaTVChm2oVHQ1ZfJVPyilGL2ykctokmiF5C4haTGC42lN9XYQJH9KtbscFSoro/9trth14HQmb3TiwsdxYXOpjmOAtHLalAX//UDNxcXOguy2Nw0NiedcbJoQ2jUmElvvHbF3IX/yTymD/nY0P1vbdpf4d1Wmnaib+QvTmu214k5GBz3XVZUVRcT0+hIebCwrPqSHBgcV4E5OSGTuktCFABjKK9ZZZXj9SBCttCFZFlNoooXInCIkGbZAjq7lLQBkaGYEMn2lXLbWtxC/J5DYWFHSei1L0o5Bt13WbMXrhS6FXtaFjia5zloCgZ+n922ibO4wNmmqbMoh8v0M5k+BrFpLXNrbn791D/4NaRI20rTSio9J/ou/uLUvbUXAFAxu2nxqPmVtVGpDnCc8QqY8L4yY9UeuscT1KaslLoABn3qVqOVGOj8GeWFVmRoDI3GZ4IMq8/QvPBrFux1pm9DQV0IlfQaEFEiM47EhKr62JZ9gU7Ci/WBkj7tHgUQ1DbEOrVwX3zOzvmfbNne0P3pSWfcMf0bAEDLzNp5j4w7/9EaAP6kVqJV23MPVLlP9F38xalq+Q3Vm6Z3mPlm995F67ZWidDlNV8rXeivDYaNiD2OCEa6b6TwbEavMZAAaVZfCbqaqKzwTKmIpiQ8i/X7oFyVU62pSamB9bKzlLZgSwGVtSKCxyr2Z7nkp5xWUqoGKjeTkryyNKQRdLKocwv33p8eOrDm1T5ZS9uXjhvZA2TXvu1zRg4vHNSSn7Nmd3ZxWkmbvHC0ZtvAHq5rR/c+fo/7KOnbrW0278840XfxV6aJI/pWNntqWv3WFsWF67fXAtH4jGWlV2W+CufByr4TF8yA9KBVSC5ebECvqogicsHGIO6Kmq3sqCjvER0bEecConujVPweUpRc9p74aIVzFWTqKuIDBIwtKTnMSCrwKVb9ZBjK7UBuJ3JwyOWkGAbuKAm2v/Lg4/N6pZ/fkDO2JeW/895FQzs0qRzx6NgPXrqfF+CBuW0Pzmlev+npTdsqX1nU+US9jKSE616M/9KTdNxo5sKV7U9/fe+h8J6yEI5FRJOV5eqR2Y/yDyGTBQzSTR+29KYSE1lgw2otVN0tADC7bViEB0nGYYqGNJvbNO9QWTWOhMRUYAKQM+lh3a1BQ21B3f/A4CAtVvsE4nSgsmWOQS4H8jipbFGn9bnpvAymXZFrYGd/XuWzC99/bvzUUgAA47pi94yPmlwSkC/OTfzwXwubZdXNXlH81OwT4TaZMrnO+CaweOiJvou/Jn07Nc0xes+hD1tP2vxJVbUYt8CLcQtYAHwMYEkTFqSQYEwK1QqLFtNxGAMYiMx1NsEMifPakbEMpngGWq/0ShtyXg2TcwXSlpegfj3WwitLTaEu1r+mGQpBzuMJ12HAU5JSgTFhzSM1atLxQyezaFeRtV+xdnazPGd9kJcSXyIEXByV4aNvPKeQF/D2/UG/hx7rvSct98WKTd9+tbYZAHEARwNvNrmEeHXhmaf275Z3wYiHx684PmPjmNG6N/u3bnKib+IvSt9tbLIPln6z9dPq2pCMWyK0SAGg2fP5xJivJJISuxOJL8QNEQzaQitEpLMEmSnOFLKrSyInbsvV61mGgt1aeVZtiolLalGAMRQETRTRMW0EaDY+q/EizpU7I3y/pLuKi9BZaeywXukQgpWbakMRgRJTKGf6mG37g2039x18weY4p285Y+MMz5JNhb/u6mj3IPLGrAVg7aL1wwHYdNyf+lHQB1N6nuhb+GtS5bJr7lp227K1NZW1UazlrFPzThpsVJbRC3/wLQNTeVHN50qTV6HqU4EI32Nr0CqaqrrAI2qnog7MOjjUIt+xp8xZXc+EQxEciwAkySHqxaHMsWmmd4e03aWh8qoQFniIybwcQM1TR9GUV/Re9rqo7sWe0opIbSAGAXBylM9FxXicft6m0065O7B1dNmcs31OcOvC66K77kz8OFaFRwPw5fF62MeC7nvzpBf0sSchWjfxqZKft9SW10bFVHU8NsjD2sIv1DtvHG/UJi3wbXWGFksgG6KUAFr92q8OsZI7FKmjSoCnWIfblZ/JFuU4Jnu65p2++dzBWefdv6m8GsngVDmw7IxFZacxVwzPqwvwT36wry7Ix2IChJCmIR/XQbBUasTJxdVdj5PK8DG1DbGsFcVtmqytrIsxNHSwiKVhk2zO66QPf3544fSJNYEmV08fGuO3JH1aUhToSfr7UP8uI56a9cGFj+3bWRKsro+FwzFdlnYjVk+YtdmOzAAm3TlEZNIMpBhA2n4h1PyWSSVZMiZhQZNyKZpm6OImzlvPKyzIZCM/UsU7hyxJW5qfyUIIwlEcjQk8H8eky4HEhJGAZVBeBnO4OlJyONIsj6tt4HkBO1i07IXuAyatCYQFDDDHoNx01uuiAABZfqYwm+vS8nLGk7FlT6BJNudxUmVVkVGdDkFY8/tPn9z93ug7xv4aC7x5z0WdH3v/RDzjk/Qnpn/cN+OF+Qf2HwpX18eCYRG3AplJQ2z0p4OtRhYcWC6DIoEU0YjzQNYBVAxTzOm9s7/7RSwnLQEYA5ZFDIWa5XIQwrKqiKiIxgGe4WVYBvbv4BuZ/kxad6mswd5guGBPWbjkcBii/2fvOuCkKLJ+VffEzYllF9glR8kiQQQFVAQxZzwThjPHOwPmnMXTwyx6njkBBlARTCBRcs67sDnNTu5U9f2mY1WH2dkF1O+kfiv2dFdXV4d/vfweFEQUikrpPrZPaVowKj9BAIryPNcO+0GM7HvCNzUWR6VF3ppGoeId1/HDdl5/RoeH3inr2dHvcTO9S/xNIXHMwGyWgV8+/vnAzq9denVDvGpBdMdbRxQMa1o8d9Hiyp82D1n6XkHe0WUAgMc+2PC7P97D7U/aVj6flndOw3ermjbvjQQjIi8gXi4oR9p2aVnXuvGnaMwfPYHD7XA73NreoKvkYZN9VRNuZbmXZWXXiwNioXuXpiksdObPHdeVFTSPWvLRD3XVjXwSFvrUo/Mr6vjfdoRSYaG7Fvuu6vbMloyHLSw0u/fj/lMeT7DQVzxfJrPQh4nw4Ua1GZ/sW7ktvLcqXtPEN4VEjhOwKKg565CIJTVznRyHpMjGAKjmJUQ4eBCWXvuMdm22A7eQ145lssfTACYqiSnmVnWWSiYREUgikCRFU6f+Scq/AkYCEBUlnqKFl7AkIgkH43DNzvC2fbETc175uWjVScPz3pxXXR/g4nFe4EVJEEVBjMWVPykUQ6KETx6Zn+5n5y1rrGsWmoJCY1B87tP99c1Cc1gMx1A4JjWFxbqAEI5JMR75PUz+zuu+a7xkd1V8d1V8V2W8LiDsbcpErvwO3q09M5bwIvP1ujN/2txJqTx2uB1uegtu23rv3ZdtLo/GOMQJKM4jOVEOkXDDhEZAOGOBtnDUBzec0E4Glp2k1AUDSZABilifWHIIMxK2mpEQxBYzEsY4HkZ7eZ/bBWdkr/txbd0rX1SpZiRsNiNhWQtd1yi9/U31nqp4QyCOlTQIAIicSvUlCEXIxOOQdbFxHkEIstJd9YN2bv+xjjQjMQzsUuRtN6VddNusmu+m7Pz3f3o+8qSwu4XHoSQTPahP+HD7U7el6+cf3T9bMSPFeRTjERdHGEoAIto/QveS+PPKwFhbWSg2ACONVUjQXhFrfwYFRrK7mZTgPbAoYkmOwFI6izwQE1jFIh/n0J6qeE1DLB6JID6q9Je7qf2xMojEYz62YmNDXX0I83EgcMrpIPHHAX1ASZAEIRASmkJiKCr9sqG5vCZe3cDXNglVDXxjSHSxsOmzfj8sfnx5/dGZZ/PBmOf5Sa8M7n1K8scx3PvloX7iB9gevrTvHz2F/8HGuDOfG/vc6P5ZBVluNQmxyTvYyBtDO/8eZIJqbS2sFzKAzbyBVoVc45yxWsIYq/KAYulGEpbk/Uq6TaTx2EhHuNxN8SYVeUHCa3eFMR/DApfgtGUQyn9Kf0HpqeKTiyR6SnIaBHkoLAskWL2uoIyJJaE+wC9Y1fT5z/X767iGoFgfFAJhsSEo9OrkFyes+3l987pdEbj+qv5XNZ17Wveh3eqcHkT1F4OBd9qJA8sP9gs4yO38Rw7nozwkLe/o19qvOevo/ll5WXLMnB64rkqXwBRpazPEocayXWNsghgVCqwEGxhiOpJLwmiygVrgWFKRjDQkYwPJCVgilWgDUZAQ5sJhnKCoXAKZOgHHyjhIWxQErBJtVZ0AkErPNQlcXz5kr0yRK6sMNwTijUG+MSSEolIolgDwv2dXfPxD3a7KeGU9Nzf02M4a4C0aP3GwmijHnXbp/neJ5FLeaT8trVn22MfNMc/v/QZa2QZduvSPnsL/bBvXf/9VU4pf7H1qTpYXsG5opD3V/BN1akw1Z+AeekizTPY4UwoOPRYYWwPwMaAWIEyESmgeZ5AMs1LrjCaORkLRBO1VtV9KlJaW5QAYy4RlQCDHfxieMRDQDuW6gk3+IUpYRInZiQgLEmblekJdi3xj+oKrLrv/0W0PinWZwDXkhqfv3vLzN/Wxox+/JLa38dgVT3zUpQMs7Hl8Flr7zuKpf2Zdl1DtO5wU+hC1/yyMv/nSE5/XPnnsmN57anitWoqtR7T+nbfaSavVoE46MKNNgJ6BTIQhAIb+jdBFY1NqXJ3qyhtYptUkQZaJKoe4qCLEKpQ5wQ9LBvU2aDgiVNySBCi/NgTMPRNrQeKnwqgnRpYEQYrEUSSG4hyKxiRBwD06+re8WXTnGauaPk2vnbtban7q0RMXbt6fN//uuedf+xDL4A5nbSs6e29Gv1v69cr7+4l/XlMTzLwucaeH2yFr0yaN2LLo8tJCb+f2PujyGKW2VFuprsqCAP4RHLMFzIzNYWzostS92OaPgrFCCfWk9Ur9GAVaWhVzoGi5JN0QpTHPWBOh5dQHMj51qVsXsLUN/erq4CrOlRPVYRHiBCRKmBexiHCMRxv2REqPub/DkCtX1I/eUjxn3mpQl3VxMOZpN+mX3ezZQ7rW7Qx03F7tdWf3WrI6+uqXK3+nl9H6Nr739r6dGv/oWfwvt1nzl+eV3XZrRu89OysG9swCLo+apAmobg/yBpFgUvdZ/IOaS5sQOTOo7cNaGnciahdjYxHSLMtQDwZWIvUTzLbKlicIOcTmEkpqqmdiIsrIWOsjZ6BW6w0nDik8vX5UXhETTAKWB5dXHIZJnIQAhgzESJLDED0uJjfD1ackDXa7PYPfueKbUFNISPexEgLvP9f9m+19GoKh426es3ZnODPN5WKzTrlpzo+ZE698ZcKfM3n68J41VU3pW3b90fP4n265o14CACx8/NKTZ7/izu8oiTxm2ATxSHxssm1J+Q6xNVRIzwxnIpWH0PjkksEJVfyogi9WES3vV12jDXcQcrFRwdwSjAFWNrCRq067f0AglhjSBsyyWh/Tue8AUIzUUIkaZqD8oBFIYBn4vEyPjr4rTi6uDfAPv1PWHGHCsbAk4cw0tndpWlq3c7b9FAuERRbCzHS2KBc3ZLs6ZQV212S/cPlPk+49RA/8gFqv4gAD/1x2yP+9tmZHaEjPzPxz9u28wj36+rV1vBsgCTISTgjDmkbaHr0O7VAaj3VHDq2yCyTxDHRKqMBQPoQNjOmaLnlbrZ0AsAXGQEcvRVeN7sqGPLii/VaXDCjXnoHESqGvK7pKUCbFDIBI7sAmyC8AwOtmcjJcR3RN79bB9+6Cmp0V8eaIKIiJFTQ9wvyyvnlfbd+dFRFewB43jPGu7HTXAN/XX8y87Yq3z0dNMw7V8z6A9tAl/TrlVx0G8KFuSlrZXRXxl+dW5Wa66pu9shVTls5kryaD8JgjhA8xWO2axkKr5I6sbqgRRBVTil4a230/mNBK6wIBDWMVk0QBRWxUUdEZdKjvxGQqWWUGSGfdZS4eQV2hDxmAEGYgxFAWqqGSmPvhy7p02zEMNry0q7JDdSOvl1YJu2EoJm3eG9FLqyAE/B7Gnd132PW7AxfOzDpy2hnDd83+5aff4w2k3E4cVJ7uFf7oWfwl2t+nDJ88Ms/nZR6e1uX1r6se+28ZRggiEWOU4AKh+jVChTFMEbGHBtougicmqJ/BSBuXVeRhhdYaSLeraUqgExvWKRXJRPUj83pBEH1qaGJWgICxHO6olodLiMQyh4NgYo3BaE9V/P2FtV02wdWbOpbVxOubBUHWjik2Mk9UUooDe9yQFzEDwaptodpAfklhaGS/6yKbPt705UcR7vg/T3kktsP9JUXPQ1d2hGv+o+fyv99e/WrFq152WL8pq3YV/uf6BXWv/7vgUj8WWQAkwjGLQAFJjuXynW28cNLzsN0vhg6DIA4bGmlAljM2qvJji4IakI4fspqatPEaY5NhHIhWbutOI9rpVB+kjWDoog0nMNXrUzVusQy85tTigVctqwsI1Y18U0hsComBsNgckcIxKRRN/DVHxGhc/qlFR0TjkihhMbz36Ofv/vOgl/FdtvfxR9K6X+zrOKkoJ9Kzy5l/9Iz+Em3V5q8q/vP1Nb+9ljlsKZTV0Xb2JFsVNHTYPvBmhriLVkyZRFC9LKBeHBBqOi1SNQ0N2mmhrJRCjCTIgCxRQRwiB9EnQYrcymGNo8ay5ipBhuU8szKrIwGMp/+t9Mpntlc18nEehSKCtgZBCWBJYjiBEUTs9zIAALeL4QUsSonlwuNmiiLvz//45eOLjvjmz1HezN39mQ9nXZJbNNKV1RPF6xHftLOu4I+e1F+iDelzSt4x175eMHRC+J+9X5/Cc4pnpcxFG2Kwkr9V+yZ/92AHWQYmlUaUGsnEV6vJq7QC33rcErACT23EfiP5JCliA0DbqOzxbObJdTO67N2BZUYaKsWWIQYSg0X+xn/tUHPqk4FgytLDYAgxxyf2uFjIiwnC7vcy+dnu3AwXm9bxpW8H/vDbd+rsvNOuPH7j61+vOMQvwrFdccRHU28tii45i/HmS7GqePUiHHnlj5rMX6qtXP3azHnSlvLmL0Ifi2K9El2L9WBbjJJSVzvZ8hA01ZHDuIgNI20KOFZ5aU39bM1eTThCWoKbsepoTfDGxtWQuT+mojEJppq+ouYEpjHSIhA4FG1GXAQLcaxFL+l+1EBSE5dxQuIPIZCVxvbrnH7TmA0dVnbyd//k8QuXAO+0T6YX3XLWkB8f/GxrxR9TzcQ75D+njzn2vksDoWVTa8KZFXVcFBdm9Lr6D5nMX7C50orDMammkd+wJyKrWajiPqr90947Wm6pe3dg8n8pA17uqJmRsKZm1lcOR7KMCUUyNNhpJ1Jst6HB30SQCb03RcwJamzMQi/goIrxWGakFT0/xgLAEjRqsiT+xUpkCUaKY40yA15gMAYFOe67H5k3bcm037rtXrzKj5kZq11FbhZNue4df7cPATcr1Wd68Frt/DGFky559g3mlplHPzgsHoyKDIRxAXXOOFzc7PdoSmR4Qbbb52Uy/WxmuisoeQCSIBIxYhTnJACgxWHjICXNMo/hOCZkO96vXRia6wADS718uz1QddUArTudAC20dtMFczIBtZFCAFCFEfWk8HoFCSMTPZkkyCjnr6YHknNWdynyTZtcdB7X63VxS1Uj53UzpYW+W051f7/RU9LO++qtYysb0yuOeH7pS0MPwotJrbHF9zxw4ucf/9pz3eb3ftuFmkIiL2K3EphR7OtQ4D151Pivly763ebz12xNy65LG/qCN/PKW56bHgiJSzcHyyuCOMHWcYrjveb8L+ncH5AZSYesOlgnXNiUUgcDgwQCIkAItJBPx5SRg8CgYkZqgQ6rexTiDSmfLaKzrnAHNjZm4Cge09QYEKeTpNg4ZMgkqmOWYmZK0GcJG4WdlP1MYqpIUlAdjIhfLGlY5F/BCc0QgjQvG4pK099x52fxkZj04DvLsr2x4LoHt3TPGHXvVBB97RB8KuYmVT1yxgiPxy3ta3CV1YRinIQQ8LihIOGCqFT+Fpj+fvx3mMZfvOWOnAnAzJ+ezB5y7BG33fHRj1eET/n2v5u2yuIYYgxagkmzaNua9cRUh2IIrNP1lIyhzCuBdY8i2KqkGABq7SGLqZpXJuAsHmNaO47NJiusJc4HNvKwWtPVqOyK1aAlI/GAUqhKwkhqDPKb90Y27I7sq+XqAkJtgK9p5PfXcZUN/J6q+E9rA7vrXJ6C4e2yYv++7HtX2qVC87bWv6FWtOtPH+Y76oPSMQ+NvWXFr5uaqxq4miahPig0BMXmsBiMipVNGd+lP3NI53C46e3YO5qz+t/WvX3zOQ+Wfvf0QOjxQzU+CQJTzZA/oikZOQg5Whc7KWBbdpIYpqOXNM2WiTfANqfY7bSDsQX8JE+iZx7TnybCasyjHiqshUypOzVzsRLAhCUxGhMCYTEYSSAkEkPBqBTjkCAm+okI+DxMxfdTF6wvXZj7hRh9253d+9C9jxUz0icOKmv4QFiHr163M1JWw9U3q3MLRcXGkFBWw3Wb1ji89u6px48+dNM43MgGs2645sYLuhc1XzNjh2zFYIjI/uRGYId28DTTjGXxwAZqzYy4BcMW3l3VTkMtwsEUBm2uNIMttNoYh76chRQb/6peH1Rkv6bExhr51UALgA5sJTgRqUlFJFGMxFFcwFFOEkQkSNjnYbq09/Xo4MvPcmcU9Lj0zldmP9L/oD14or08t6JrydkAADFcXtq9x9eru6Qf8WN9s1DVmOAFAmEpGBUDYSkQlsIxKRKXAmHxjTsa3v9+yaGYzOFmbt5pvz3yxg7/rdlp3EsTni0q8BMaGWDg9Q+iwboWWhN6DY20aT/hL62LuIBwtyTkXqyFSVJSsWHvJrTZgJSWW7Qb0+4lAABgKxIjrUNCBsZA8ZpmEohldKdLNc4pMT8kAVmpKEkSx0MXA3gRe1zwyF6ZroUDOk04JnPcwG+vq4Fbz7M+voG9Tu1f0nDWfXPOOrZdW55+1ydvOvKDOYsb9qeNuWpKeeEF+ypeeeq49CGjrkPrdkXqAnyMQxJKzNHNQtndG+RnofmPDLzplZ1tuNzh1qq2/78+b/GEx7ZN/63zI5sX1Kad9OkZ11/D9CO/RbmZAmNTaimegFs8Sanircf3WXhmG4WYlcG2stMqCaVIsSNHTbDKyThqwseDkqUBKUUDUyptxTJMeW6a9lDUO8E24wSAOQHXBnhu3Pr12W+MzF9aXpc58fXp1sc3/cyV/zhtdfXHIzJO+mVonxZSXuqtf8/TlA1xzx1Thu35+MLPq15aNPWYbS4WfrfnyHW7wsu2BHdVxGoDQjAqReIoGpdCMUnelhqCwrDrfgPeaWMGn9T+jF9TvOLh1obW6aL45oL3Sgu9C1cHNu6NrNoeeuitjyrr44ZLr9lpEtrvT9ZaQrL9cWOvU2kVTEE5dQxbNFuqsxkFVxNHbSstWzlq/ZADO62rtaxuHkCvdmPsxzqeAdBtAAgDUcKCiBqDwuINwWWbg5v2Ro49omLB+tLpo/8DM64hn1HBaUtOv/Gd7mP++cDHI3bfcv+a/SVA5rgAAA9cdESfbmfoPS88fvTfpwx/9qqeAID37+hw7cT1+qFxdzbjHndXb5u/cV/+DzMGrd4Rrmrk6wJCY0gMRqVgRAxGxVBMinEJ/jkYleqahdU7QuENo88ZtePdYSe38PoPtzY377S9s2A4Jm3cE61q4Cvr+e37YpPv3IC5qFqkX22tZJ3bKv1ih5Mh2+F+g7OlTDiEYdhwYIbmn+R+YwWikm/oZl7dB9NkB7Y/kbIY25qLMTCXF9dqGpO1JjRrsGZJYtTSp0AufaxXTpXrtkGGTfe7MtPY/Cx3QbarON/btdg3qHv6xL7VXzxz/NnPTAbcrNUv+IfeGAMAHDPopK7tg69/9UtzWMrmlpxy2qN1Qf+sa7/vPPjM3atnx8ZVjh2Uoz/oL+9v16M4kJWTnTP8hfRuU9e+6PtyVdfZK7q/d9O3m/pWFua6z5pwTc/iwJFXvFBWHQ/FJF7ASlIRCIFLrlru8zBpPqZdtrtze9/wvplHd9zqLRzVxs/hcEutubo8fv6Vp28tj9Y2CQ3NPBY5LHBA4DASgSioxVYUi4bG3Kk8HbAG+ahMohGuZMt42uzRfluMwABCIqBfkRvthWFLwDApDwNAW32BSejVTEyYshUDOoIfELI0wDYWY6qXRQg3IhEBFWtsCMxYm5ZsCjYkZvJ5qePrPjYMBF53gkmJuXtf8MmdS1dfNuqIWRMfPn3mdcu3V+V8uSr955Uff7++GSHw1LWPff/r5xUBDyegrPRy34ZPX7/7RH3MXRWxbx4/YvJ9NcGo1BCVkBBqXHzZvf/IWvb4x+zJzavmV4ei0oX3PfzctSWn3rO9MSgIcqU8JM+RYaDEAkGSEMYuFsZ55HHDqZOuPvaIiqtPOeqVP3EGr//X7fFpfTrkRtyuF7+QThMSIhVSk7fpsYL2pPfg6ZdTay5Aa3mJeaSMYT2Vh0mtRe7XtNOaVIyNMa3KLeCQncPwG9EnmBTDBp0moiZV9KoV2CEhCCheW24X9LgYFwN8HiYvy33bOYUxweWJb9t51y3XXzX3yct7bygvu+SmuzZ8ecuNk9ftrvvv+l3NGOO7Xvlo8Va0fV9Thp/t1K+m28RXOyx7+p4L+4+47sdTji5Y93KXGJe9bEuoqoHPy3J1yvdLkfIRPQu48fu3lkd3VsRCUSnOo9E3buIFHOeRKBnkl5ULmntcDMDIxUjpfnZAt/QTB5W7WNT9ws/Al6W/6/fyl2l3zdpaVh2ft7wBrQm4WMgyhuaZyHx1UJsj9pMtCpDtcB/F0FoZaaVsEbENgB0vbWG/ge0pGh9MqrqBNd+d007KiRxQWT6ceGmFfzYYac3XUg7vhIwLsGrdY8i6/X53drqrINudm+lql+3u0dE/eWTe23eMv3nK2p5XimlZF29+/r9Fk37YFh3Wr2D/ruaSuYsb9tdxcQF53YyLhT4Pk5/lLi309ujkH9xFqpnd9/Of/Td9PnXhTS92/FvVNyuawjGxON+78uUp0y8oqxi86/Of63dWxKob+SiHOB7xAhLkZLtywBqG2l3KAIY+L+P3su2y3X1K044/Muf6cy/PSeOWb5x3wYRjhvesvuWwXvqgtr2zIDopunB10+a90U17o7sqE69JKUsABF5joUUtm6pkZFZOEIY2sdDGT5PKyVAFabMzWGgGABLidhppubexCJAKatLLyqzHpi9GMPcWBTWtxAIgmYKaVDgbPyGleQaY8i2hFFp6UnjC8UMxx0OWdbky/Wxhjru0vbdbsa+k0Nu9o793Sdq3aztH4i6JayqfGxl513nhtKN/Xhf4cHnOzeeeWtXIV9RzlfX8vlpuf53qyFXdyNc28VefceKXS7y3zL/aN+D4gWPOkSS8fV90x/7YlrLoWz/0yx76hNfFRONSbZMQCItNck2JcFyKxlGMRxF5I8pJMQ7xIhbEBFmOySBvDou7KmLfrmw6smvttRM31C88bV9DxmH0HtzW8MtFwag3+FnujU+savryordHntKnNC0/yw1dbihXTgIGRXEYomVWGjv/bAUfrlBgCwm1o8MW/VMK9Nasi7LRkBGk2ImMO0ZHEGotO0Ktu0Ar24xChxUKrBQ6ZiDrkmmvC7q9JUVpXYp8XYt8z5299el775x017Lewsuvv/jGLS9tAJB5Y179EV3T+4vPQ1fGP789pb5Z8HqYuiY+EpeQHAWV7mOz010lhd5uHXyDumWMOiIrY+gb5Y++lDvqNSGw8dYvRu+v4zkepXmZ14af7S08xtNupLvLtKOuWdMcFmWgIkn2jddeYeLmGAhZFrpZ6HEnGOk0L5uVnrhKUZ5nQLf0SSPyenXyR9ff//LMj+9889A6eP41241nHJmdxh13xP7yIVvnLW/o3sH/4mf7cTyshqkqMapY89IlKbA1mMHwDqYto9hsvrFQWp362lBgHcDAgZF2UEonx3CK7LSejlJ3pAYpsNPJMIwBWSYGqrVOCUY6gQkAWVX/DFkVwG4P4/EN7J7xat+Rva6KeVzg+U8r87NceVluUcIxTvp5XXOUQyWF3huKpj5Z9t91OyNNYTEuu1tKWNV1ZaaxBVnuPp3Trjm1w7pXuow9bsSeDd9LJ1btqYovfO7UXb1ebQqJvIAZCNL9bH6Wy/PrjZVHPFfZwIVjkiDKVWYANvR1hP7cxSYkc5+HSVzFz2ZluNrnursX+wf3yBg/NKcw989ez+n/ewtufHoDvgoAICH8+HvlK7eFIo2NWJBLZxoAluwAbC7/bQfgllXQNIAJixKhhabVUYZG2kGhZWRyNo7SSTwobbZxiNRaa8hV2WnVyOTktkVqp6GW/hZTDltUuLJ2IXWHfIgh8vUB9RFAhoGsOyvNxTJgft4Oz1uej7w7t+2LybjCGX4GYVBRx0EIo3EJ54cq6/mqBj4UFTnN0uNioeBJzCTTz7bPdS96qs/E6WV7A/zixuC6uVU1TXyw6yt1dXyMl3gh0Y0JCpUNjLvTk6GqWDSuhltgiqsHRh0ALImYkb2wEMtATkCiiCAA+dmu44ZkP3r5yDn3FZ7+UO2h+HAPN6Vl9f/nsuce7DfhTjG6v2DN+hPHvjFnUSghDEMGpBqDZBDPNuipzUZgDb0AYBeBLvqUg45hYKu1Bg5GJkqDbdFOAwOlZtU0lXIAGLRcW9vU9FpyH8Wz0uXJz/EV53t6dvRfknlW3uTNZa9y++q4UESMckiQEiIoQonx65qFG+BH5TXx2gAfU4CnNMjwAoMQDsfYnAzXx7/2LN4dXrY5tH1ftKKebwwJkVhCrI3ziE5CIi+qCFHeY9qI8gPQRAAsIYA5wLIscrGJxS4nwzVpRH5R8TWuDuetKZkIwODWfxWHWyva2h7b37v/lJKC8N1vrp7xSUVufnZjVQxDh1wcSmsZqgfB5mQyI9GwpDBsTKv1GAYWCxMBRdXIpPC5htEYJDEUQ8L72YRh6lr6UzLS1QP1l55CBF42pdT9y3nDzpyfl+kKlfz0wifVFXXhxqAQkl0XOQEnZFO5fxOE1Q1cQkzVs22pKjCG55kwhOG4tKsy/u79zTsz3BiDSBwFwmIgLIWiIpYkzW0T20g+lISjRZnKyxqGGDAMxFiSEC9AtwshjPMy3Z3jbwEA3MU9f37lBeCdBrhZxx91/Pcr/yyZNP9n2vWnH+lzS2cwp1/w4GmxPR/XS7goz/Pj84MGnm9bazoJRcY6yWrN9VvobKqNZIIlsPHuSAXDBrEFtPU4ZXaaNBSbWXFHDAOdxlKqOEgID6qLhowLGT8IvfVVebv8lyqW1A/qnrFi5tjyvp82hpXIW0kURMJZOjGIRCm6tXcGIWZYngPNYZaBoPDkFfP/UXrxzduCUXHT3kgwIupZuIi8DQZwCfRq6gOVEdFyBiGAE8wa5gToccM4h44sPxrF/77s8Y+/XLWS6YrH9qs44W4wrn/FhWNKLntuX2u+j8ONat6Bb2y84e89r5SUn189WDD8KH/++NnfrWN6Fvifv3+ub2LNglVNz3xYBrBEnGfVIdsBz4QzYDdAK6mykROLYKQtDLC6LymGAdlBd/OwAjUZp62z0ClEMtlgWCPemFKDYUzMQ2OeDYWBhAWuvolduRX4Pcy1dy195YvKOI9iPBIFkahCjslUYPRjli8mRzU2BPBb86t/Wtc8ou8PA2fndyveHuOQXOJckIm2rNUgQ6nMi7GROle+B6QWkWEwQBgzLERSjIMNQeFp97wPZ3uP6HLpff/p7M24IrzuKOH68WK47ITJzwFwGMBtb2u+uKA0Y3BwxIKsgXd5+r101uy0/8bvqojEA2EJY9AU9p15RNbsX+oxHwe67AOc3qYVjTYuU0S/pMh3aEyyTlj7pMifxlEy4MFiB6ZolJ2VGBPnEof0oqZEhnv6dHutnfpTsw/Th4xHQ+cJ0SseSyIv4H5d0kf2y7o5fTAEIMYp9UoFLAlGKVM1taWW4FJNcykCuR4ylngs8MEQt6+WOzs2ZG7mlhmfVIQjSk5MEevpQSSiDDLWFwiNPhuEWtLM2Fry+gTvjEVRisRRTRO/pyq+ekeYgcDb++iMQSvXVBYH0477efVcAEBh4QWOL/xwS9rOuHdTxDtofv3lHy6s4Xet2n3HrfHj1izdFNy0N/LzuuY35/08om/mSzf3lEth6l+dBRpWLNkg2b6j0cH+kLZXQyWthSbJJknsdaLhSIed6HYqIjHJKqcsErdAhwnWndTFq0QYqhXMtX8BwLyAFm9onres4cWf6xuDjWr2WUkkcI6JRYvQYhM+XgqNbQjA992rv/ymur4xAkQeEylv7Qg4OR4p/Ro2bbXYOlK7cLzEyr5kLhec+siWG68ZV5Q/ceOeSCgqje6ftXcW7HKN/4M7OlzwZKXT13G42bapx4/+6Psv1+/qtbksGoyIQt30S/71j/11VZF4Yu2srOeveGr7yaPyjuqTCRkXldGJ/sycmuyS4MQ6OzZ7FbS25bIRgMltk0LL2q0tGD4YInFKGCZM0FhTX5FEWHuuADJuF+RF/O49p/KjX4sLWKaZokoSEcKk3Esq7bHmsgyRvM4wGCPMoVlflBkl7RAivMfMrwNQ3jyadw8mCrXK05PTEiTuTs6KC2M8dLmY5rC4X85TEOOQWOjNz3ZDCDJ7XjR56N4Pl/QC4DCAW9fOO3rHewsWz5pXXdXAVdTzY+8SghEpFJNEMbEwu1gGYVyQ7T7ngc2IjxmxqGozWEgKYxiTbOlB0DsD6poWJZa9MExg2ITAVmMYtEkkpq3EqWMYAEBm65CfrloZAxuAZN2ezkW+KSPzthS/9dioGf02XESkgNffE6kxJps6BxnJCWILoYhFuYygycBrxT8pTUBV8AcQq4UXsZFAXE0toqIYAgQ5HsVdkONxOCZFOUlE+KSjcvtduqpy/7nH4RlzF/94oB/HX6+d9lDt0uzMX74bwB3zZkNQqG0SZJ9WCSlLsPyCtr89bHvZLMDHFM2IEYIO6G+Dwi0wq6BtubAknLZzc9nI1dQeJ6V0ihgGFtW0HchtFNdJrcQ2aWutGAYq56lrvwAkpF+DCEO3/8IT2mMMYjz6/Jf6OUsucrkYjISEAJx4SYAw3lrsPZrSWHs48tqR2BC1LhCYJHlyFSZor/qJYEQUhtQKIKvcs5K0XilizgiyUkxOuAOy0l0FWW5WrN31/ggAwPwWX/vhZmqyHQ4AMOq28Gs3VS1mYXNEDMekSExUUqYp30BDffyftTOx0ISRblYgk8BA7U21pIK2HmqTBotUYtEiuJNCCxAlikxnUTUVsV0fS0hEEqUXBgaXa6vWIu8ZW11JsUXTa4QxkPl0lEO3ZvT7cFHtg29sCzYGAnWN9ZU1WOCwpKShFRXFEpbjtjGWsJbyUt6WDO2UrpqSREIpJQKdkUZE5j09sR6iazUCjTXAWjohoj8GWt5cjGS+HrtdMMPPPnt5luuHkXz98kWP5/jHfkW+txgnJXv/h5vcRvepOu2Y45Y+m+EqfaRb+2ZRwuGoFIknxCjZ4VnWZYo85mOIiybYK0mOQwLad0XhxaKgsgLBfj8xgu2AFg0WmVY2CYbJ6x04hrGlg60i3hrDBGwwTMUq2WCYiNuCwFTEVEkri9HoQQUn/7yEDwdxPIL5GOajcup9UcGerIJG2IAoov40OBnwVjobqmYLaM1/2GaPeoPISKxpZPMyMj8wDCzK84zom4m4xstnlFd+e9bkz2bGfp5Cvvy0/Bss38fhZm7ZadxzH82f+c3A6K7pvMjsqIhFOfn9SpoNX7Y+JKCLtD2ASHsKaK2KXdMi/8iWogbL9re6xTgPhW22U8MwtcLY9QFJOjgan4w4RGfzkhOGrWnukJr2XRQWL925b9c+OcSEAyIPRBFIPJZrZ2DdxmNLP7EcgYBMFFUiIC1hYwnQ/gwCTvMC1Abh76H7b6mHjLtACOdmukaU92/48awNu8Ozl3eH3nQAwJzF9frDfv6ib++58JBkw/3fad5p85YuWro52PWC9+6dtffXjqvqAkKck7CyghO5hxUrIOWTY3yfUPnciO85iQarZei23Ec+ztgD1XrF1mCYoN+64JcEw9jcwdmAbJfssiUMAyuGsVrSBiMs8kghvCKX+FOYJYN+SiaB2e4pavMnYZyEwCIKqHopc6OaOSA4Bf22iZH1VR9CyPFIPL4sUL19QLeM6YuuaHiPZwr+efqE2689bRgA4LtH8i666PhHPh3+/Kf7W/ga/pLto7uKAQDBVX3eW1CzY390d2V89Y7Q3MX14ZjCcCmPWlLLeqifDdKXUSOoiKQoZrd24oPGJMXSD5ooWeua1ZEjBQyDljAMLBgGSTBsA1Ta08MGw3RYg71TBwCmBAA6v00WW5EIlwwiKMyAmWQWWc2kmKaZgOT/DU6YILCY/olIvgCbOxip6jGJavloVjr7bJf+vbf3XrGzPfBO+8fwd+t/PLfitS9CawaP6lXt6fPizG8G+o98KV4+7bjqHi18CH/J5mLRU1f03pN2bVxAzWEpEpdCUSkYlTjeBFT9mZPvxaQNJTFMSY3A/LWTzYlGWo9rW7QVg7E7Eztewsr0HiCGsXVkEgb6Q7H11sKQHNrCPNtg2AjOVAEps7iyw4ahbSJjOzUXKIL7peFtRSMBPIQcV0Bsrn6sb9iUQTZ9QMqUAP75ilemvz+KP7asZtivlRUvn3P0ju6PPT/jQ1+4/d97T9u88OOLLnr0k183BbnKb29447jpFwwAhxvRpk0aObxH7S3PzFb4XiVmPCESYSU0W38pxsslLUYUSTDzz+ZGCMBWNtPUbCBhf0TeILJSAkj8n/boMDy0tENkNyfbkho0AAiIW8xLVvcvq/3JyVtLr02sdrGYiDHhQa1fQHfwUFGhJgbApoQEzs2yThJBT8Q2oLaJn0Yif92Eppu4oO60Is9R2VbePZI9vVDigWIpcfOiUAg5nWYAAC5ZSURBVPLgRQW5vgse3sJAWFHPd+u4o3l9ce7I7PMb+OVbgoGwCCFsn+s+86Ld4oi733522GMf+O+eOuDR9zckv8G/QsvK/dulx30x8eHT7th44pVf3xlZOmHxhpHvZa1oCok+N2RZKIra28GAEGowRU6wlX8mvHcPvQBscqUkjpm/4YOCYbsTgUY82+CtZXhcOpiIIRGHqOWs1Ei3Xl1OT2qpGXVBSxiGAFCVnY37xTR0ITWUZuvGmAIzAMR+4hKGKwoirMEQI9mZA8g1UwVQ14jqA7zfx9Y08d2KfS/98wauIrdr09p3q25ojkhuOQ1tOK1Haa77+jNPdpU89OGSdQBsmHtf4Wl/7RwAwaZ3x94BAJhzyTMAgOs9JdftfSE4viQnJ8MFMIhwqFmA2Pg+CQ4Z2/pOEqyihWm1uHCQB0m20dJSQDrLZIwlfkL6//R3bI77p7942MK50OlEm/HtOjin7FE8LqncWvpR06yg7fCQej0AEFKNRXdlMAtkw0Z+PvIopHpCSAtG0Nofml8ktQZAYNyfGqEF5SoBooQjHOYF/OhDF7k6D/6leuSeqngwKnIC4ng8Zcqw88YVznp98b7tz00t+tts39J9azbs2LcHHG5641eef2zGL199efPwt/29b5CLy8oWIz28BGjmBgiM1O3GZ0ObUPWmsdsQ0uyYrawKCBJgXglIAZg6C7JFd9NDHACG9YXkIGDYBqjAOYutWpo4GYa1PXQePJv+FBVNcu9Jn5X9jZgnbD9VqHuJ2uXHVaQphoGQVZLjJuQr1gVYF2RcWRlunxv6PIzHzXjdjNcDs9NdeZmuojxP12JflyJfr5K0jvDXpiWXL1kTv3D+U9zqiy039ddtGdkXnTd6e5+OTeu6zF2wqikUjGCRByKPRUEJWdOsElopBqrkpUVmBpRDZWvzYGFgcYsARMIZoJ5oTamTRBgGls7A3NORl3ZwtwROXtMmkdjEbOuMMOU1TUQ+EMwsuUH9JKRtqDMz0I591h8xNO836/AgOTjVjVw3Tem3TVMFlNwOqPwi8ucCGYAQZgBUPh4GAElMcCAsDoZQiGXTvKzfmwBwRhrLQMnrZkIxqSkk5mZKicHE6I+r+DNufI975j0m9xbUNMN6w/+bTfOXtG0w56aZV3x2wnDQ4aIT43urxlflrg1zAPDaV613JEFoYcTMOktshOaQDLN+3LTh8DtJs63MkDqG7Xq2hGFAnwOskQ/2XtMtqLUMr+nkai0zZrDue6yMSSiiKP7VBr3WRw0tz9+0h6bx+guF1oUGkOsuBphxwLDcg0nQAKip5yMxLCEWA8DGgc/N8CICGLAszMlw3XfJhDmuJ8OLTgJPTEiMxYG/SGtfeH5NrSN6E8868K+l24468rofKva7b3qnjONDMtfDYkaSI8EgtHDA9LbloMY/2/FuVuHZ4Tgw8c/mpkUjYVvKc8AYNhFY7Vxsj2FgobQkhsn+bVVr2VI8SAGMWEMxtC39aiMgYOvJBFb1jCI0ki0XhWY2QRF1FSWWEuTA2GFY3sewGEnqrbKuOA9ZBroYKEqYZWBOpuv284oDEVBy5qp3rxlj96b/x9vCB2ZfuXH10peGJukzqld1Q7P4wcK6qgY+xiGX2yUgF8ByeBlEdBgpILdbMiBZ1dS2zUkAtgOztmEbzGB7Mt3B0UmLpCn6L5rZMLtqYfurHESPS2uFB9KVGpvSdFCFHYiGzH1MlkDzHSUbGVAxaBZLNTUxSPwkTcS6g4eeygMrjp+Kg4ogIlFKXKI4z3PMgOz0E3667dwxR1zDH3PDGvBXasGNz1TP6ddpxK2epXcl6Ta4zynB0cu2vTW4b2mazwNzM12FOe6MzDTo9gLWaqwhI5DIb9LOgGQDvyStpT70cdITyxnD9gO1CsPWVcuySLSAYTuPS0wf1X8bHpeEDVjvYDLoYWeA0Sgl0Ux3I14egGYwYytcTWuHAWMMTHketDHNGKZjmLSQJqwrSwEQZcqNMPZ6mK5riplV/zn7/q8BAItfHOL0Ss86dmwLL/3/V5NrNWf1/wd73NqsgXffc/YK/7FfO/Vdu/XLG87s2C4r+uvMk3uVpHUp8p14VN7D07o8eW1vyLqV8rTUCbaCK7UTW5z2ic7k12htKWOeaXlOTkTYOidr54OJYSux1b57YkAabEDT6TqQYjM9dIBu68CM7cDsTJPNMAZmUmyDYXNEJDY59yl9ZA9rCeF9tVz6mcEn/rakec4AJu9W80sk2ldNF3/3SF6SDv+/2vpn3wvveGv7vujSTcGfNwmjp746BT5h7Rbe8aayUf/D2RjDe95c0quTf/SArHF1YySE99fxwO2DjimgafaY3t06B6zk/DNlQDKOMk6jWC5sPtOufxswbPFQsY18wJY+ANs9FBOVpgupkaTYDGMLbTRDzkJO7cBMdzORZXL+NvyzaQMbhgdlvxYqDHTHaW2/FhQB9AQg6pMHDIQMhCwD3r9r8NJtxRNPO7Xp+zTg3KRg3ZARwwEAr97YJUm3/y/tzvdG12Wc//1vTdv2xXZWxI+Z/M4nS3u+cXPn4qLzAAAn3LYOZl1/RI/TfvnwdiCT66F/g2c+M+Xz+/ueMCz3xNrS8ZMnL/ot8MHCWiDyJlWs8n+gW4ApTtDEP9ugzg6J9r/NzYI/O+berNBKqpS2ddIydaZy4llGsJqX1P+TsmUKaq3UKj9QKfKAydeSiI8gNU9m7RQk1hGqm1H82b4PSZCdy5rTXaiV1/APVXbJCaOBlsoDK/6hrHKu26UWVcIAMCd8d2XfrOzewsqXuyb5PBbf+GjO8NViNDO0/pGinE/+n3prLXg0N8MnjJp+7itzX9pbFd9ZEYvzqLKBuX3mrAnSxX0uGO0acz2Y/dEvi7eV/WvmY58Pm3D9T7uKB26rnDv2gmduv21maUEoPsdfPG7Wa2smBCKNcV5Lh6K8PUTyvUQKDosEav6uzTSM/tfCaFJb9npsANTXb9n7+9JhYBNF3AI7bScSW4MfCDKrk2JoWUGJJdOW3tI02ZEsgxRosokgWzl5mkHQNVuUdGBkJsA2Gi+gLxbZaWy7HHf7XE9uhkuUcCgq7vpv8bLtRY9e1sfyxoF/9Oy+3U8fede5e0Od1u5L93U6xe8RTx19HABgzOCT/KPnWE/5E7b3bu/YvPqeI2+oHTX93Nius3Kqn5uzuL6shttfz5fVcPOWNczY+9KLH874YPhkd+8XVl3ytw7nVZ3/8IJl5Z0um3nCuDtqlwROu+jxhZNuW7ZmT7tjpnx2xpiCIT0zenbyQ28aYFnDcwGQGLZ+sfonb9UQt0RgiVXfcoZ94kvItldUcy06HkHLpqWDeQxI/F+nky2MYL6MtWdLTk5JnC5JFyhzhfHWXauVU7JxvQLAZHAGDk5jMv9vFDRXaiyq29CuXrkLujz+jPSxg7JnP/XcE289kJPu8nmZrsW+kpV5j31+1BvzlquXkx0bvIPf4tZeBjOu3fj0G50nvDyv4pQYjzq186L53U546AzAzWr89cqdy98ffksE/CmbMn/tx7STBpfd9epn63eHo3FUVhOXXUolJK+w6X62ON9z4rDc88YVVrzjevnbAe8v7v3PF57bXRVXHmd2uqt3qf/843Kiu9+bXzElK93VeXX7ffUZR99W3+7kH1C4Qc7nrlTJkXM8KAy0ukHlx6L9N2gLCCYtLyQF1v+jRUI7Byz9dLtgBv2wLSOdKi9txw8n56VTinxw8vRwYqdpVtngqHXBGEHStQsAsjOx4phYYqI4OeU11QJ3DY03Ac0ygjXPJmGkwEDn/U1sP1ZLPSWYZ4Yg3WDMgOzTr1/Qdf+nvXqVRgeu9HuZNPDgmRX/Km3X7/Jn1pz30Ob7i8Y/+8WEO8+8eXa3oQgv7zzh5SWBM/ZWh0MxqbKeKx66ZcXaNL/3hcy8/R88uwoAw/jk7vGssPM2xy/n92oj+k++6oSNF903zJOr7nn544evOa3jrQLaV8vtrY7XBoRgRE7ZKWGGgXEBZfjZAd0yls3IGXajUPfJ6CffefGHNYHyWg4AkO5j8jLdORnsz88Ujv1n4Ls52xuCQlXDcozBsZcMBdKTAJt8IQkXaFJNo6lfgNn/mWKjya40JB3Qa9OwHMyQPsaBHiYlqm2kwxbCbjOIHR1uBXm07WBPqCHhRJ2Sq7b57py6tXBpO0do+mVD8pAjbwGgRp81r2nIMDJNZiXAhmLo/gt4NHze04+/u+771ycMqo+VfTrkxvEDS+vZ3Q+d3v61yV+/u2He32LbX7zy5Ql5Gdwxuf/GPaf/sr65oVkIRKSGoNgQFBAGvduHT77kXvLmJvUWTxuV/evmavAHtX+cM3hr9892rtzx9lO9vn7r3k8Xh5X9sHzN2AHtB59w0Y79sfJarr5ZCITEKIdiHIoLSJCLM4sSXhyb9vpXVcdMuWTWvOrdVfHmsBTjEC9gjxt63cyJFzxU3yx8+lP9mh2RxCrQGKvLP7uxrgmInGyi02gv0IUaCwutuCEYv1rmnJP1sQ25178UtlBmoX9PDKfCTlvh1DZ2mpqMI4yVZg/jlq/bWg48CYwJPoIOuqCiGpSd6n4ZsTJuE1w0w8IEC+2GHn9hftpRvTN6dPQ/cmlh5Qe5t8waedUJGxesLx3Tp3L0xDPF4I69nefwImr3awHCsPNJ7z/z01F7quKNIVEQkdvFpPuYTu2844fmnnBkztz7i898+mTFkbi6kSvK8zavuX/51y8GRm89d1whAKCgYGp9/fvgkDVP35n8lusafrog/9gPlD2x/fMavOPzMt0F7S4b2bsqHPOs2PR1WtbFe97bVPrAzaHvh0y4Xyiv4cIxvapr4rExDONxM/qDVxJLsiz0e5isdLZ7B/+w3hmXTy4GAJz30ObV28NyriVBjmfgsMgDJd0/UjGM9bwOgOafZenMjn+2Nf9imncmCHUy/lndMLHQdv76ToxxG3lp7X8pqKaBcRpoBTsNbOMfAMUnEympsZUaa5vaVUie2cpaAzsOnORy7fl5mqmm+Hxg8GAEI22p0JoArVzrWH5apN4r8U+Mkyrq+Yw019sLQlPPj98f9g+898bZ170z5pRpuPcjG3eEd+wIN0dEmL3bzTLHcNmrtpU1hgRRSlyDYSCfwRbmevpuymfHXLboAa5dVqyuDoweNOmyyZPEaFVlKPeoExrnfDRMmWx9/ftf3N/u1AdtK24eUFMyEPBbrtv9JtPhponA6wfcrE+mF51x9rOXPT5MkvC2Xa8FPsnO8vOvfT/giUWlSFwZW3bmyhcLm8M/JdDLiVoiK6wUl4wJ1LqpMC9xjoUQuFh4y4jvMgqu4kUUjEhqVTotUxqVesWqMQXGhwApR2NAfTDm1irzr02zZqW09nZWSlspu3GKZY+1f0uqaXtPD2wRJEzaaUMdQDw+k86QUj5rWmOgTEp5/hCbqrdh8ix6ZEwzVNg0AavW2rg67QpC3hqpYSblLjKZC1Figg40h5DxuhmPC3Zp7734WOTzsB2HXtUlfc/grnU5x9RnwsoYh+qahZ0VsRVbQt+ubLzl3zvLa+J1AaG+WWgICoGI2BQS99dxJRfHo9tPGX9XAABw7rgxj1yw9IvvXpu/1r10U3Dr4rdOf3CXZ8BrwDstuOlZFb3eaT8+ma3YcpTbuPSkUQCAsUMmAu80/+jZwNKufHob8E4b3OeUq085CgCQNv67z+9p7+n/KgDgnX90unlaKQCgqP35HU9dGlzQT+ECGkL+n/23r98VWb0j/MHCWvbkxqpA+qOfHXVCl6XnPNC58sO8O8qW1DcL8biIJTWxs/zHA5EHApf4E+U/QSk9JyAxIS9s3BO57avjqr8Y9MKnFfLjRABJ2MiXhoz0oJTIQ5p/tdeMye9Qf6FW8kt/k07NgX8mWGj1F/U/urWBl3ZWZafOSx+ISGyVilvkqC3cO5arE0HrXbQg+qbCV1PqaDuOmmSnSdW0HiGs+fclWGgWKiy0yw3dPn9W1pCeGQO7pY+uGj1u0il7280IxST3950yTq/uVPsPKVz28ZxtDcMXrdsVqW7kg1ExEkOCiAQ50JVhgNuVkAYLst3din0PXtbls/uH8GO/bfzizImDy/711eBjb5wVjEr5We5bzu646RX/ih1Fo27eXN8sDIjckXf0qw3NQra7QQrviVd9H935dnl59dJtxTe/shMkbUufzfhmbeeJg8q7dilI7321v+Q0jLhKvpeEwMf3DOnSLhg/7rfS9r737z4pFPf8tKnjOXc/XNXAMwwozvfcWTQeICGj7w133jP72X/f99Q9d871/ndbeQRLvFoch1pD6fcF5fgQ1gVZt9fn6d8tff4Na7+tPPndBTU/rG2ON9ZhIZ5gnvXMsmq+NICtBFn3mTMZ/2g3OwBoh3z9dxL1lQP/bAHwnwXDyUXigwihZEOR1yT46qQ30pY5QDvBGJqXHhOGdduSEuKf+CUDWBWA0zqX5D7TfXKEc6efuvGrXxvqm4VBPTK6bjh6U89fpgp9Ssc+PuftGX9fNvPEY7vvqYoHwmI4LvECUkq1AQhYhvF7mcw0tmdH/9y7YOXsgYLIFo15HgDw7PIpuypjnIDTfcxNaYOXlOwas7/bN/k7MAbZGa7sdDYvy12U6+la7HMHFtZ9N7H0MpB661h87o8PfVZy8rehtLE7K2KV9XxzRIzEpZomIRyT3C549rHtAAYvfF5R1cDHhQR+vG6mQ4G3d4n/pgFvbvH98+W5lQ1B4deNwXgsLpeGxECvgUJxZ+TDZBIyg2x+y8v2De2VedeFJcs2h+6btVdoqpEBLAAsma1HpvSUrbAe2Um/SQBsQ34NALsswqetWEsds9/jdGLLCQNo8xJoUSS2irtW0TFpN0wy8CbB2BjKKAZB4IogyClKyPp90VKuOSLSEIzNUZDGfQHDvKRTaIC1pFlIFoQT3xN0eaZNLjpx0q9b3x3w5MLaNTvCMQ41hcWtud/vWhNYm7lq3Mac7r6nPnhi9Gc/1YVjUiAsSqKo+wRCACWEwhKDEA5ERAC8b+Ddu2tihQs92969Kn3iuLqAgBB2u5h7/Su9dYFl3rW+WCzNxwajUijDhRDwuRkJ4ayOE6dNGgnAMsuH5Ngqqj7ueSX46oHzj761KhyT6oNCTRPfFErw8+GYhBB++sN9gbDYHE785BPEFbMsbAonQD71lSVfLr73wg3N1Q2KwonHVA5gXSQjGVBZgc8wALPynbNxAWf42c7bRjy74TOPG/Jygn5NX2Vk2yec1YlvDWipjoCVWiaTTM3oNT4e20bJj5bqhFQ/y06b6OQDw7AOV0h8+k5ByMBiJbbtbMWnowKsJS0UoCObALYzO1mXgKQrBZFYEwCbBCPaBQGxDGvvmw4YxtBYn4AWloSRiPjYS3OrnvpQ7NVpWbcOYG9VFGBc0xADkHG5mMIc9xMlR20S8kd0S/e64bzljZIo57JX4yWVXFsJuhSNoa1luPvfeTcbhhAkhOr+TwllUQlhBkK3C0bijNsF07xshp+J8Qhj7HHDGI+yM1h31Ttv31byQ8HbYL6N41fyNuWBevaNxxZ/ezMvoFBEagolEBuMSpEEm4AjcSnGIUFCgoAllHgRoagkiPj44sCQq9ZX18cUsZaskqGCzVRoDmhhLhhBRtZHMyIE4IUxDwye+XZDfQXmokBjnklKiw3omqVfaKQ8ppGGnQRdO8EXE1vYuZtyD2zhnfo2sdtmizhq3ZkCL31QzEttZ6dbyXi3LB7T0E7hXKqbqYMdR21hpzXtvcFRK55YerosmJCBFWcs1i1nyWJBgioryJRZ7oSQ7OnSIf1s6dL30ayqRh4JvFyNDen+rBAQ+bcSAzLKTxcLXSxkGcjKtcUZCH0exu9h0v2sz8PkZLhyM10dCjw9OviPPzJX+jq95BIRtKm5uj6x7e7pOedy85Y1rN0Z3l/HN4aEsJxyXcFwjEe8IFNXlfvQ3giSEmyzWpJOS+INgEV1TGAYyqpcxX7u8R07vCTdz85fXIGiwcRQEi/rsXTmGVArgln61b+KA5B+AUjKP1Pk11Kh30LeHOiwdV8KdLjt5iXQdnaawkbynqQ5Cjjx3tqzpQBm4atT4NtNjLdNniBbdlpPgqtFPgCkpemQOyBJowMo8f0xjOaRm3iwiefGMFgS9+xHz7AvYzEEJFEuMaPERWgPQ01MpJQslzBSASxKMoWSga1ouQAAMg1MTMfnQZKEC7Lcw/tm5YMNs7e2A6DK/OWk1sQ9d3a/AoAr3Ktf8G/P2CwhzPE4yqFoXIrzKBpHUgJRWC13YuTHR1odI6TlnVM+JEShl84fKb9IOQ4EMphDPy3dIxfcERSrr5odwWCekU3SBYD10IW2KJ+B3T5b9No1l60EDFrAsG0KnkODYQeROFV2OnVwGh6OLfakxGONr26NeGxy3oSOwUnEvhYxjNSrqPW4UIJyYgYbSi8MgEyuZQxj9UJW85Wh3cGAkYNvJCiTd6zS5ISoLQhQkjDCIB0wcR553Yyo/PSxq/7ds89TFeAAm3fam9d+/+s216Rr8raVJ5h2Xk4wEudl9KrFihTTjk4GidpRyChAY/C9dljC+qoKYQKxht4Ly09Sry9piR4BJrsdEa9qD1e9tST9OjVs+YFlO7Djedj+VNMk7K/guHikEuqEDU8jx6GwJYYJE//HdH9s4T2w+YpkT2zX0zosYT1WYAwp67HW33qufS4RTByivjY6MFhbCCgWTq/lo5R9khQDpiwKalZQzRAikxcOC5wiK8rdRCzptRSJ+jJIBCpatDpSanHNBIOKJMTxiBOQIMqyqGzMSsAdwY/uKoZZB1TWNG30+cO6114xY8fqHeHMNJeLhRICvIgFESm1muWiVpJafEyStDqgSkFJ/SHoxV/ponP6BtDjq5FaQFR9VvK2fJuAKuxq+nL0Nwvpt0l8WgeT/NqcwliO4BavYhw7FBgmz7LBsGl62H7ytpc2WwKxzRWNGR4IjEEKMMZms4FxKzayE5VUxHxHenQhXTFchbGGTEkrPk5BlKxgjBXFj14JVdUDad2wjhwFzwBJEuJl9CrycKaflSR83mNlg7rU+3EzOIAWXXRiXkY8o9dTk0bkPXfiRwXZboCBKCkl6bRbA1ifobr0YL08lURBFxOIJeknfYNKpTt9OdPUYFi1+gJa4qVpu4V5PqTk19jjAib2E1hZUCd+WJlNm3lpYK+aNp3VFnbakfXV+6fCJwPKHEeuDhbGGJg1Wg7Kaounpw1HTQQbkSuxNXMlgNalUP6FZOW0ru6SWWy5P9adQABtWFYH0zhJZXyEMFQ6K0HjMjsNGQwQVAKfEIQMFCUGIeD3Mt2KfUN6ZvTo6B/U++xd+GExdCc4sFby92mAu6tfr619Ojb1vuBsAIGkBtMjLfuX5MAz60Yjk38FMMrqm1dGYiem46v1fIa2oq+ZeQbGaz2E5NfYZhxGtaXDtotE6nTY0s/mruxIKIQtzcTETtuSYguBtV7Xnv22Jd0mimq8OZL2WqhxEk9PemT9rduTYv0npD84Pb0OUUUREWRHDaaR1PrjWCdcRAVz/V91NdCpsSENYoMLxaKUGNrtgs9Pf/6Y/R2OPvKWbXtmO9swW9fqFpz04HnLlv9w04h+mWwCwIp7IyImoHEKgLx9coZ6jWWDDhtl1g2mWjIijYyyktisc8YW0RfYvThgQi+w7rQnv07PzYH8agW+7an3Qcew3en4QERiK8yAmXGlOqYAyzbC2AxIC4wdPKtBEo7apAtpUSQ2JbUzFUMlkKzX+9FAa1ROtcqKOsWjpEcACCDxAmoIClc/cKM3Pf+uF+/ZMNN7UvE3igt0m9vD75T1K2nMHT/vnkXTfnnrbDcLEVZqqmJDt4y0lLoGP4woD0f1yZFyrMmDyprc0/DWIBKP2aJXYxRNzLON7op8g/Q+m5+tIL8Jrolpd4e8Bc0mzGS/bNcJ29Tw0G7T2i9lJ03y6ThNhjIyOQ+VytWTXsLc3/YGW/Cs1k+EdoPTDpUWL0tIscF2VmJtW3sk5E7dAc4pAYimvlbTgCi7ibhFyACWhazb43EVZLv7dE776Kotp5372ux3zhaC27iqhUWnrTc/t5TbiP6TP/3HfN/p3NwlDWt2hDftjeypitcHeNm6I2ClLLuiJdZWE82UbSlNhC2ciz2LSyj5qeS+wBa9lN2I7GkzMjDtNJNfTL7fFnwn6YUAM9a9tpQXpLKzzXQ4iVqr1ey0MylOzlFj09UPBTU2NNXUPVg5auqxpECKgUU7jenK1EgnPrTKyrgDqjQ5ptTaiHAApnh1ZXxRwpyIgxHpq73HPfz2Z1vB1Mx+t77wkT1fl2JbvnFeyaW4R9fLMvxsjJd4gXxmZF5OQHLOBv0kHgVBdalnQv1LnGIpsI5SQC+wfUF2dNWBeTZ3S4n8AgBYmH4MsSsFOpyMkCq77QiszS+705OcC4k+FhpmP6CZFKdAWg8yNTZd3FBxWaIj7M6yJcVW+g3JGVp8cdWFj/oJge0HZBN6Co0uULNHA50yq+m4IJvmZT1uWFHP1zcLmemu3PXHVtXEv14RMD+rVrYrT/LM//SbkZPOqqrnY6oLh2rEItwbEZUoG1I2NmzywTILJuRjwHbk1KTZItGrnWmmkOZxHWBJd4EOcb+2dhOiOeaFdqTDyQip9ZJ6TweKaj3XiRQnsTC1RIptZu9EWs36rQOkxjYGJ2VTCQd0Foy1kY1Z6X3MHKARUWwKVSV30mQHm6VBhcjY6Xtoykxpd8m1U2bGeQH5PExxnmftxoZrXhtnfh2tbKeMHvfI3eO/XfB0uo/tVeqfMiqvuMCjMvN6LmZdqQZkHgECQCvzaOJpjSvEFNU1Py5nzpl8ZQ78kd2HlJz8Wr7kZEyMeixZhf42OWkBbeopmpesNC3lHCD28Q+mAVX/Khs7k7FpOQvTawR5VqqnKLOC1s4k7aUT62m3gYF9wINCO8liiy0YmbTCaPYVTLHJR8zmdoB6E1DPmKeKzUhVf8qju13QxUKfh/F6mOwM1+1/O6e2eYxRyDNpUU+b5p22/rn35qzofsN1A5987tuG0E/X/WvReePaZaax2Rmux96Jqe/bHFqgYUYnyLQpCJCir1nWJYCHaWRa1koVvbhF9BLPmcSjDahNpiPrYWLb0odJeo7zEtAiHT74IrFpWcKtIMX2diaHAY0ubaPGlvu16WwWjKnCEW0lxcCsoMYGjK2qVJ0o6SmsKZGPeAJ6tQfNKoN1rYGs8MpKdxXmuPOyXNlpCXrw42/fFGbF3ri5M0i76vJJI9654TvL67BvNV8OAwBsnPFen/OX//O1DTXtH3vs/bURzp3/azv3znuunbHj85/rE/yzLrVaqsnYoddkuSXfrHNPE+Bbi17jq7Iyz6ZXaRXBnMmvHWSsADbjx37z98Cw8x04sdNJ0AhS4ahThzHZN7lKzBnzZv2WHUcNCJmNlNDIr4f+7CwcNa3fcoIxwOYCS+r4tCMhpkPYIevzuUvbef91Q49B3TO6dfAVZLlnXN3rp80dw3F3wzfRXh0CU86cvPCxHADAkx+UW14o1ZavKrv6lKNKRt/z674uHy6qXbktFI6hnDRu39Dqh5ZftX5XZGt5VPEJlf04lDkTxl7d8OOIXsNsTj0la3+SaGv9U0Av8c1YPhgMDpbuimpOeaEpPrYlJy3LfodxrKdpi5DDCDasuAMfbmKnHcdMhaO2O9GWQ07Gh+scL93f2plgqW04aksKPqCnyLN327JGQeiXIh6RPVOtnW2kCoBq3jz1N4YAaS80gRnIuk4anje0Z8bwwTcDAFZv/FdWGisN3XPZZROF3psDUenke6R4prvThlnAO63n5qMAAO/e3nHa1/fOPe/uSfc1KBftWnL2VSds7NOxcfzUh48a8Liv+ITty6M7K2IsC9uvKJx+PohmuzEGIsJqUhvK0qsh04n2GpiBxo3YgDA5RYV0iTxTT5qcmNklYEEv+UU46a6S7KEIkHNi998NwxQUrSPYisQOkIOQeqbJxGxgiUlsSTC2WVBSg7EV9pb7JVNhqjpqMrCJylmpj6kdMpUvB0lyAxAjWGFMJpEH2p3KhmugyMBK2FMCKjCxyMjxEuW18YemdQm9el9xvqfj1uPanz3ok9sKli1YcsGj8bU7IryIjuiansm5Z17x44kXP9H73S8GlM7vK87T0QsA2LPv0zV7xlx/299rMy9uHDDV5fGu3bm3vllAGARzl3ca1SHHxx7fMDLW79cd5eHEvGzjcrFJR2ViQKwSrwNWTWyzsco6oxdg418b9BJExXTIKVwHp0p+FUeO2x2AB9R3azZbWDapHU5D2bp5tMZAlVIWAZrOtDwspMw3jsM6nmhzltPlUrQ2Oeaptuuvu3aQNJbMFqDttEu1pX2cxiH9J9RO0nPoKSXUiBzUSrYAlwd6/CMH5Fc28B0LvEN6ZrhZOHZQ9unXzl83+4xZ86o5AXUp8hXne8c2DKsfurl/Kaj4IKfnC+/EV00ln8UnP9aeOcq1bDu7fEtwd2V8Xx3XFBIlhF0s7Nc5rS4glLb3PnZl1/wpi1GsGQsckWLOKGuCsWOKOeV7sI8oxEnM7DpjlxS9mESpiaN2YJ5J8mtlnrEFvQ7kFwDMwvTR5m/I3FqLYafRDhjDqTp7QRu0J1tfoN3ALQHSfj6tgjF0mpvOUUMjrJ/oA60YtkzGzlROD6PDmOhj+ZdYFhjzdbDM32NUURtrjqLKRqGsJs6ycOrx7e8aeOde9qzvVjY1hcWqBqE2wO90X8EJqG/OlvZ/68XvXAGkNeRT2bNiywXH7qtjR5XXcrur49WNfFNYbAwJgZC4bV+0op6rqOcvH7ToqTk+IMg5brCEraJv6uhtifAq/Yk84YcMvdaWIvOs/XQRP5wwnBov3TI7bctLW4YErWKnbWekMJM0KW4dR00MS03JdK5J0KWZZNsboWRpU+fWcNSp2JlAkvQA+vSgMTGakdaHV3sleGnFcx7LNaxQYsZIhCJWIuARctc2gdqAkL5i2CP75m5dUB6MigADj5sRRORiYVa667fa/k3fblsZfnbcEMKw5J026bZ7xeA9I0cyP6xBmX42EpNC0cQfx8uBFhg0BHC7q4qxGJO10IgMsk+GXkPV3Aq2WblzrRBVaugFNCMNbNFLvnOHfLHJtoHNOLJxL4XeKeqlk60W+jgt2rvIu7Jbjuy109iyqX2t9nYm68xbMjU5nnuA1iZML+HGF4DJXPPAEvhG9jeZlLBpPzbRFrOZVL8LOyRgchAAjBggJeYWSUrCACzyWOAKc9w3rv34l/XNW8ujFXV8TUBoCovNEQkC0LXI17XYd/yMwRMv/OA/t5X4Mi5RLvzSlT9cmz3OndMvvP3lkkJvZT0XlNNfcZyAE8MKWIhjPob5KBZ5JRIDG7YuTP05oRfT6HVWyGPj4bcGvdgGE9j8XVu+fCt6W8M8K5uQKbidJki/Ay/9e7LTrZWKUxeMbW/cjs2m/p+Eo3YUjEkWWssIZupvzyUbh+y8Mu2T5tFisB4XQaXOA2RNJqWsKQtYF2Bc0O2BrFuNiGCg182k+9gOBZ6bzurYNHskwtDrkqbe8KAUq/7hk+e29l31+p03+z3S/F8/qmkSXN+1Sz+98aLHt5bXcIEQjyUj+4cs8SobRM4N0t1KRSAyUIGxXX7mVrHNrUVvG0TfJIh3ItHUxywD2PxdtQHDSX4dOgw7xU9aRyAYxVQHb7N+ywGWSc5KSTAmMgNYi7CZOrcYz0RgG5K6K6Dx/OaoJhrDKoANX2gNw2wCw8oehgVySj2Px5WX5e5d4u9Y4B3eN/Pxa2949fPXB/fIaP7EXxf0Z/n5PpdXf7pE3FsTd7Fw93tnLC18dU91nOf4BO1V84eIRn4MhfwiCSixytihXpEJvTq30gr0mtTIBxW9VmQmQ68j+ZWDGdJGm74c6w+6/b4YPrik2FG5lQyKSc5pC4ydrmiFsXVwaAT7tVyg3F5HTXQzk2JAkGJgJPSwOZX22CTO0sMkdM8yhAAvgVBUinLo39fkiSUTdlbEK+q50mMeeva5bwd1qc898v7lW4Lb9sU2l0V3uCfXNArhqIxYJVU1pvL+ELorGrrJ0OvACWv71RXLSegld5rwkxJ6jVNbJ/qmgF7akYPStrRBp5XkV6tMxK0dx0mzpX1vxibxXZpM8NBhcEWBaaPfIgaH9B7q3Nbqt2jHD7uklhavD2V2pv7aPcLWJutxzn1JVEoEireHbBzWM+wAwCp5qqAiezIs1NQKPAeCifP4UTeX52clCHKGn/3svqF/P6Hiy6wNpV924l2rmkJifUBoColaNVAjklHLaGMUGQSkgycweZUmRa+V8BoP6xChtyWrrxXt9GeU9KfJlTLJOKZ+2Okkp19OQydRa9lew3acFHRjphFMMYnY7qLGUasPJs38OJ5unVhy/Ra2qDFsApsID8zWOGACqwMm/Sljk9chMOu0AKY8LgEgQvmwHmOspmLVeV15g+OlSBw1BIX6oNAQFHbsj/a57JdR1++Kf3sGN3ZPmpeREJYQEEQsamk3zPik/6jiJmZbbsroxVoxDrsHAkx6rANBr/1P6juifjt85tZdFl/oliFnM5WUMZwExg77bc52GqelhcA6ggnDycbHdjA+NGpqs/e1qafWyaKjxuRzcIKxzeduwrBlAvZ6aZIYEsmlgIZhI/WcGrsbl8spROMoEpOaQuLKbaGFG13PfjG0rCa+pyquDMYwgIXE8qpcEQIDsRBQkzHU41AjojbysCN6TUKvmc0mTzkw9JqtvsRnY93viEGb79sumOFQYLjlMVPAcMtzS40Uk0izkuJDBGP7oIgUYexgajIFGANo/hZtiIYtKabBCYjvnpqMxe5iMKtE0iwN1YSuGGOMkIQECYtSgtJCCEQJB8Ji7dw92emudjnudtnunAw23cf6vFqhEzW5vHYXxHUxpk1HlNHIit6UVVYUegFxSpvQq7dURV/TDsv3Y9eVhWlHO+hgbLbsWso6rVTHPHSaraTKLZhk7o6XSEG/ZfscWqXfgjaTMeu3jADjlHXUtHKLMikBQ38HHW4KEhdh9AGh+lBkTTU0yqCqNiePm/V7meyMhBg8qHvG+ePbebpcXBD/bmj7bf0GjgzIRcx4ASMMOUFdDqBaJIFI4gNMzLO6KlFZrEAy9Dr4abSEXpoDsqCXfEcEXJOg12ZBd2jONEnXQv/vYfjgwtjhEm1XU7cyd4+jqYm8FqWjtvOjhpbRrMl6SO10UgxrSfUIVTWEVldqhlGLqjGMz8PmZLiG9Mwobe87blD21aefXJd9/I87Czt0HTb9oskznr5xzY6Iz8N0LvI1hKSYgInaCGpZbZnU084bBidCItYevXqIhgW9LRDYFNBLskupoNf09p2ZZ8vyQB4izEj/PzDcehi3aCu2wtix758PxtZuBoxT9KOGgCat1E0lw7ABfdJuDAFRf5xhFGswYFyQZdP9bH6We+zA7NtOkXxbpoUHv7l8c7C8hluzM1x61JkMA4/qkzmpsVv/Ex4OhMULTyhe9FujlgGXilsgGHgIMOnn3CJ6AXDy0wCpKJxbi15jH9XMmHRGr/P5yj8O1Qlt9iUxLCl3ZXwHFisQMO+ADoccBnSaU0ozNJtz7C5tGiSZqcluTvIlLPNNJYVQi97UpnnKP0lX6mSmphT8qKFdWCI0TEbaL1O1ce12tF5AYaQV8MD/E3RwARyFsLTMxMjCzMTCzMjOyhRkJ3ppnpBoxLurCx8+ePnjy7e/d5/94ONmVpLi/PvvvzMDAw8nc1mkbHLXTUYWtv9/fjMw/IKFFY6zcuBZAj0nI+Ve9K1FqLkXkaOom3tJXXGFkV1xN54hABAAAP//+7ppYN7S9aAAAAAASUVORK5CYII=" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import \"github.com/benc-uk/gofract/pkg/fractals\"\n", "import \"github.com/benc-uk/gofract/pkg/colors\"\n", "\n", "%%\n", "imgWidth := 320\n", "\n", "// Default fractal\n", "f := fractals.Fractal{\n", " FractType: \"mandelbrot\",\n", " Center: fractals.ComplexPair{-0.6, 0.0},\n", " MagFactor: 1.0,\n", " MaxIter: 90,\n", " W: 3.0,\n", " H: 2.0,\n", " ImgWidth: imgWidth,\n", " JuliaSeed: fractals.ComplexPair{0.355, 0.355},\n", " InnerColor: \"#000000\",\n", " FullScreen: false,\n", " ColorRepeats: 2,\n", "}\n", "gradient := colors.GradientTable{}\n", "gradient.AddToTable(\"#000762\", 0.0)\n", "gradient.AddToTable(\"#0B48C3\", 0.2)\n", "gradient.AddToTable(\"#ffffff\", 0.4)\n", "gradient.AddToTable(\"#E3A000\", 0.5)\n", "gradient.AddToTable(\"#000762\", 0.9)\n", "imgHeight := int(float64(imgWidth) * float64(f.H/f.W))\n", "img := image.NewRGBA(image.Rect(0, 0, f.ImgWidth, imgHeight))\n", "lastRenderTime := f.Render(img, gradient)\n", "fmt.Printf(\"lastRenderTime=%v\\n\", lastRenderTime)\n", "gonbui.DisplayImage(img)\n" ] }, { "cell_type": "markdown", "id": "87fb9828-c892-447b-9eb1-0717a96c342b", "metadata": {}, "source": [ "### SVG Drawing\n", "\n", "From the amazing [SVGo library](https://github.com/ajstarks/svgo), I really wish I was that creative.\n", "Below is Antony Stark's Shining example, [demoed here](https://speakerdeck.com/ajstarks/svgo-code-plus-picture-examples)" ] }, { "cell_type": "code", "execution_count": 12, "id": "48d813a8-8d4e-4ab7-b374-10a73977ec7b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import \"bytes\"\n", "import svgo \"github.com/ajstarks/svgo\"\n", "import \"github.com/janpfeifer/gonb/gonbui\"\n", "\n", "func Shining(width, height int) string {\n", " buf := bytes.NewBuffer(nil)\n", " canvas := svgo.New(buf)\n", " xp := []int{50, 70, 70, 50, 30, 30}\n", " yp := []int{40, 50, 75, 85, 75, 50}\n", " xl := []int{0, 0, 50, 100, 100}\n", " yl := []int{100, 40, 10, 40, 100}\n", " bgcolor := \"rgb(227,78,25)\"\n", " bkcolor := \"rgb(153,29,40)\"\n", " stcolor := \"rgb(65,52,44)\"\n", " stwidth := 12\n", " stylefmt := \"stroke:%s;stroke-width:%d;fill:%s\"\n", " canvas.Start(width, height)\n", " canvas.Def()\n", " canvas.Gid(\"unit\")\n", " canvas.Polyline(xl, yl, \"fill:none\")\n", " canvas.Polygon(xp, yp)\n", " canvas.Gend()\n", " canvas.Gid(\"runit\")\n", " canvas.TranslateRotate(150, 180, 180)\n", " canvas.Use(0, 0, \"#unit\")\n", " canvas.Gend()\n", " canvas.Gend()\n", " canvas.DefEnd()\n", " canvas.Rect(0, 0, width, height, \"fill:\"+bgcolor)\n", " canvas.Gstyle(fmt.Sprintf(stylefmt, stcolor, stwidth, bkcolor))\n", " for y := 0; y < height; y += 130 {\n", " for x := -50; x < width; x += 100 {\n", " canvas.Use(x, y, \"#unit\")\n", " canvas.Use(x, y, \"#runit\")\n", " }\n", " } \n", " canvas.Gend()\n", " canvas.End()\n", " return buf.String()\n", "}\n", "\n", "%%\n", "gonbui.DisplaySVG(Shining(500, 500))" ] }, { "cell_type": "markdown", "id": "61449cd0-4a9a-4934-ae73-5aa504edf3fb", "metadata": {}, "source": [ "### Plotting with [Margaid (SVG)](https://github.com/erkkah/margaid)\n", "\n", "A real pearl!\n", "\n", "Since its latest update is not yet \"released\" (tagged in Git), we needed to get the version on the specific commit. See \"Executing Shell Commands\" below." ] }, { "cell_type": "code", "execution_count": 13, "id": "1fda7399-ecb1-44c2-b05c-fb52d188822a", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "go: added github.com/erkkah/margaid v0.1.1-0.20230128143048-d60b2efd2f5a\n" ] } ], "source": [ "!*go get -u github.com/erkkah/margaid@d60b2efd2f5acc5d8fbbe13eaf85f1532e11a2fb" ] }, { "cell_type": "code", "execution_count": 14, "id": "6904a8ef-5a4c-412f-ad75-58910d933b76", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
12345678910X1.02.04.08.016.032.064.0128.0256.0512.0YA diagram of sorts 📊 📈
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import \"bytes\"\n", "import \"github.com/janpfeifer/gonb/gonbui\"\n", "import mg \"github.com/erkkah/margaid\"\n", "\n", "func mgPlot(width, height int) string {\n", " randomSeries := mg.NewSeries()\n", " rand.Seed(time.Now().Unix())\n", " for i := float64(0); i < 10; i++ {\n", " randomSeries.Add(mg.MakeValue(i+1, 200*rand.Float64()))\n", " }\n", "\n", " testSeries := mg.NewSeries()\n", " multiplier := 2.1\n", " v := 0.33\n", " for i := float64(0); i < 10; i++ {\n", " v *= multiplier\n", " testSeries.Add(mg.MakeValue(i+1, v))\n", " }\n", "\n", " diagram := mg.New(width, height,\n", " mg.WithAutorange(mg.XAxis, testSeries),\n", " mg.WithAutorange(mg.YAxis, testSeries),\n", " mg.WithAutorange(mg.Y2Axis, testSeries),\n", " mg.WithProjection(mg.YAxis, mg.Log),\n", " mg.WithInset(70),\n", " mg.WithPadding(2),\n", " mg.WithColorScheme(90),\n", " mg.WithBackgroundColor(\"#f8f8f8\"),\n", " )\n", "\n", " diagram.Line(testSeries, mg.UsingAxes(mg.XAxis, mg.YAxis), mg.UsingMarker(\"square\"), mg.UsingStrokeWidth(1))\n", " diagram.Smooth(testSeries, mg.UsingAxes(mg.XAxis, mg.Y2Axis), mg.UsingStrokeWidth(3.14))\n", " diagram.Smooth(randomSeries, mg.UsingAxes(mg.XAxis, mg.YAxis), mg.UsingMarker(\"filled-circle\"))\n", " diagram.Axis(testSeries, mg.XAxis, diagram.ValueTicker('f', 0, 10), false, \"X\")\n", " diagram.Axis(testSeries, mg.YAxis, diagram.ValueTicker('f', 1, 2), true, \"Y\")\n", "\n", " diagram.Frame()\n", " diagram.Title(\"A diagram of sorts 📊 📈\")\n", " buf := bytes.NewBuffer(nil)\n", " diagram.Render(buf)\n", " return buf.String()\n", "}\n", "\n", "%%\n", "gonbui.DisplaySVG(mgPlot(640, 480))" ] }, { "cell_type": "markdown", "id": "2f534d6c-57c4-4ec1-ba71-310d73fa5802", "metadata": {}, "source": [ "### Animated Plots with `UpdateHTML`\n", "\n", "Still using Margaid but now we animate a `Sin(x)` plot varying the frequency from 0.0 to 10.0, every 10 milliseconds. This demonstrates `gonbui.UpdateHTML(id, html)`: it allows a transient HTML cell to be updated in the middle of the execution of a cell." ] }, { "cell_type": "code", "execution_count": 15, "id": "293ceefc-c50c-4817-98fe-5f15ee4d0754", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Animated Sine" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import (\n", " \"bytes\"\n", " \"math\"\n", " \"time\"\n", " \n", " \"github.com/janpfeifer/gonb/gonbui\"\n", " mg \"github.com/erkkah/margaid\"\n", ")\n", "\n", "\n", "func mgSinPlot(width, height int, freq float64) string {\n", " series := mg.NewSeries()\n", " const numPoints = 100\n", " for i := 0; i < numPoints; i++ {\n", " x := float64(i) / float64(numPoints) * 2.0 * math.Pi * freq\n", " series.Add(mg.MakeValue(x, math.Sin(x)))\n", " }\n", " diagram := mg.New(width, height,\n", " mg.WithAutorange(mg.XAxis, series),\n", " mg.WithAutorange(mg.YAxis, series),\n", " mg.WithBackgroundColor(\"#f8f8f8\"),\n", " )\n", " diagram.Smooth(series, mg.UsingAxes(mg.XAxis, mg.YAxis), mg.UsingStrokeWidth(3.14))\n", " diagram.Frame()\n", " diagram.Title(\"Animated Sine\")\n", " buf := bytes.NewBuffer(nil)\n", " diagram.Render(buf)\n", " return buf.String()\n", "}\n", "\n", "%%\n", "htmlCellID := gonbui.UniqueID()\n", "plotSVG := \"\"\n", "ticker := time.NewTicker(10 * time.Millisecond)\n", "for freq := 0.0; freq <= 10.0; freq += 0.005 {\n", " plotSVG = mgSinPlot(1024, 400, freq)\n", " gonbui.UpdateHTML(htmlCellID, plotSVG)\n", " <-ticker.C\n", "}\n", "ticker.Stop()\n", "\n", "// Erase transient and display final image.\n", "gonbui.UpdateHTML(htmlCellID, \"\")\n", "gonbui.DisplayHTML(plotSVG)\n" ] }, { "cell_type": "markdown", "id": "9b6d9d8f-de5e-4154-9f09-21bb3b2f545f", "metadata": {}, "source": [ "### Plotting with [Gonum Plot](https://github.com/gonum/plot) (SVG and PNG)\n", "\n", "Another great plotting library." ] }, { "cell_type": "code", "execution_count": 16, "id": "58248364-f1b3-4e56-adc7-7034a1f6c56d", "metadata": {}, "outputs": [ { "data": { "image/png": "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" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import (\n", " \"bytes\"\n", " \"math/rand\"\n", "\n", " \"github.com/janpfeifer/gonb/gonbui\"\n", " \"gonum.org/v1/plot\"\n", " \"gonum.org/v1/plot/plotter\"\n", " \"gonum.org/v1/plot/plotutil\"\n", " \"gonum.org/v1/plot/vg\"\n", ")\n", "\n", "// randomPoints returns some random x, y points.\n", "func randomPoints(n int) plotter.XYs {\n", " pts := make(plotter.XYs, n)\n", " for i := range pts {\n", " if i == 0 {\n", " pts[i].X = rand.Float64()\n", " } else {\n", " pts[i].X = pts[i-1].X + rand.Float64()\n", " }\n", " pts[i].Y = pts[i].X + 10*rand.Float64()\n", " }\n", " return pts\n", "}\n", "\n", "func GonumPlotExample(width, height int, format string) []byte {\n", " rand.Seed(int64(0))\n", "\n", " p := plot.New()\n", "\n", " p.Title.Text = \"Plotutil example\"\n", " p.X.Label.Text = \"X\"\n", " p.Y.Label.Text = \"Y\"\n", "\n", " err := plotutil.AddLinePoints(p,\n", " \"First\", randomPoints(15),\n", " \"Second\", randomPoints(15),\n", " \"Third\", randomPoints(15))\n", " if err != nil {\n", " panic(err)\n", " }\n", " \n", " buf := bytes.NewBuffer(nil)\n", " writerTo, err := p.WriterTo(vg.Points(float64(width)), vg.Points(float64(height)), format)\n", " if err != nil {\n", " panic(err)\n", " }\n", " writerTo.WriteTo(buf)\n", " return buf.Bytes()\n", "}\n", "\n", "%%\n", "gonbui.DisplayPNG(GonumPlotExample(400, 200, \"png\"))" ] }, { "cell_type": "markdown", "id": "c311053c-84f4-43d4-84a3-87e9d987907f", "metadata": {}, "source": [ "The version in SVG looks better though:" ] }, { "cell_type": "code", "execution_count": 17, "id": "b5e2269c-3f8c-4f61-9b73-317d0c71498c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "Plotutil example\n", "X\n", "1\n", "4\n", "7\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Y\n", "\n", "3\n", "9\n", "15\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "First\n", "\n", "\n", "Second\n", "\n", "\n", "Third\n", "\n", "\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%\n", "gonbui.DisplaySVG(string(GonumPlotExample(400, 200, \"svg\")))" ] }, { "cell_type": "markdown", "id": "aadf447d-22e4-486f-a749-36834d9bf24c", "metadata": {}, "source": [ "### Desktop App Development with Fyne\n", "\n", "If using a Jupyter-Lab ran with access to X11, one can also experiment with desktop UI programs. Let's try the [*Hello World*](https://developer.fyne.io/started/hello) from [Fyne](https://fyne.io/), a popular, high quality graphical application toolkit for Go.\n", "\n", "> **Important Note**: Disabled by default: since this have many requirements, and won't run in a test environment. But feel free to\n", "> copy&paste the code to a new cell and run it!\n", "\n", "> **Note 1**: Fyne needs to link many C++ libraries, so the firt time this is used it takes a few minutes to compile everything. But\n", "> afterwards it becomes immediate and interactive.\n", "\n", "> **Note 2**: To compile it it requires some libraries present in the system. See [Fyne's Getting Started](https://developer.fyne.io/started/).\n", "\n", "> **Note 3**: Remember to close the newly created small \"Hello World!\" window: GoNB is blocking while running a cell, and the cell only finishes to execute when the window is closed. Here we add a timeout just in case.\n", "\n", "```go\n", "import (\n", " \"log\"\n", " \"time\"\n", "\n", " \"fyne.io/fyne/v2/app\"\n", " \"fyne.io/fyne/v2/widget\"\n", ")\n", "\n", "%%\n", "a := app.New()\n", "w := a.NewWindow(\"Hello World\")\n", "go func() {\n", " <- time.Tick(10 * time.Second)\n", " log.Printf(\"Timed out, exiting...\")\n", " os.Exit(1)\n", "}()\n", "\n", "w.SetContent(widget.NewLabel(\"Hello World!\"))\n", "w.ShowAndRun()\n", "fmt.Println(\"Goodbye!\")\n", "```\n" ] }, { "cell_type": "markdown", "id": "626a3bd7-35c8-424d-af44-005940178224", "metadata": {}, "source": [ "### User Input\n", "\n", "There are different way to provide input to a program in GoNB. We list them below and introduce a new one:\n", "\n", "1. Simply define constants or variables in the cell and use them. The cell itself is a good way to enter input.\n", "2. Add flags, and pass the values of flags after the `%%` command. For instance `%% --x=10` will run your cell with the flag `x` set to 10. This is handy for instance to test a function with different values, each one in a different cell.\n", "3. Read the input from an external file. One can edit the file in Jupyter or another text editor. It's easy to set `os.Stdin` to the desired file.\n", "4. Jupyter Notebooks provide a form of input request, where it displays an in-place text box. The `gonbui` package has a function to do that, the results of which can be read in from the `stdin` afterwards. See the following example:\n", "\n", "```go\n", "import (\n", " \"fmt\"\n", " \"github.com/janpfeifer/gonb/gonbui\"\n", ")\n", "\n", "%%\n", "gonbui.RequestInput(\"Tell me a number: \", false)\n", "var x int\n", "_, err := fmt.Scan(&x)\n", "if err != nil { panic(err) }\n", "fmt.Printf(\"The number you typed was %d\\n\", x)\n", "\n", "gonbui.RequestInput(\"Tell me a secret: \", true)\n", "var secret string\n", "_, err = fmt.Scan(&secret)\n", "if err != nil { panic(err) }\n", "fmt.Printf(\"Shh! Your secret was %q\\n\", secret)\n", "```\n", "\n", "The output would be something like:\n", "\n", "```\n", "Tell me a number: 42\n", "The number you typed was 42\n", "Tell me a secret: ······\n", "Shh! Your secret was \"I🧡GoNB!\"\n", "```\n", "\n", "> **Note**: Not executed by default because it breaks the automatic tests, but try it out on a new cell!" ] }, { "cell_type": "markdown", "id": "0037e1db-61a2-4fd8-bc6f-d8a45eda5b5d", "metadata": {}, "source": [ "## Flags\n", "\n", "The `%%` command can also be used to set arguments to the execution of the cell. This makes it easy to configure \n", "different runs of the same code using flags. This is something handy when testing or developing code that is shared\n", "with a normal code that already used flags.\n", "\n", "Also,`%%` not only wraps the code following it in a `func main() { ... }` but also automatically adds a call to `flag.Parse()`. \n", "\n", "Example:" ] }, { "cell_type": "code", "execution_count": 18, "id": "4e2e9992-3a74-4825-87d8-773bdc30b05f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world!\n" ] } ], "source": [ "import (\n", " \"flag\"\n", " \"fmt\"\n", ")\n", "\n", "var flagWho = flag.String(\"who\", \"\", \"Your name!\")\n", "\n", "%% --who=world\n", "fmt.Printf(\"Hello %s!\\n\", *flagWho)" ] }, { "cell_type": "markdown", "id": "7d42c111-54f3-4a1d-b99d-4005ac49f9e5", "metadata": {}, "source": [ "Alternatively one can also set the arguments for execution with `%args`, if not using `%%`, as in:" ] }, { "cell_type": "code", "execution_count": 19, "id": "27c7aaad-b0d3-46f0-b1f6-dc66722fe5bd", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Where is Wally?" ] } ], "source": [ "%args --who=Wally\n", "\n", "func main() {\n", " flag.Parse()\n", " fmt.Printf(\"Where is %s?\", *flagWho)\n", "}" ] }, { "cell_type": "markdown", "id": "b2e0a724-0594-4462-88a4-6856a0dc2cb4", "metadata": {}, "source": [ "## Executing Shell Commands\n", "\n", "There are two variations to execute shell commands. They differ only on the directory\n", "from where they are executed.\n", "\n", "* `!` prefix executes what comes next should be executed as a shell command, on the same directory\n", " where the kernel is executed -- typically the same directory where the notebook files is saved.\n" ] }, { "cell_type": "code", "execution_count": 20, "id": "724e33f4-c5fa-4fbe-9d90-e411369a74f3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "go version go1.20.5 linux/amd64\n", "/home/janpf/Projects/gonb/examples\n", "total 428\n", "-rw-r--r-- 1 janpf janpf 158378 Mar 8 07:18 experimental.ipynb\n", "-rwxr-xr-x 1 janpf janpf 87160 May 22 11:29 google_colab_demo.ipynb\n", "-rw-r--r-- 1 janpf janpf 185777 Jul 20 09:14 tutorial.ipynb\n" ] } ], "source": [ "!go version\n", "!pwd ; ls -l" ] }, { "cell_type": "markdown", "id": "58a9dd1a-c30a-4d89-aada-efb91a989f20", "metadata": {}, "source": [ "* `!*` prefix executes what comes next as a shell command, on the temporary directory used \n", " to compile the *Go* program when executing the cells. This includes the `go.mod` file, that\n", " can be manipulated for special use cases, like importing a specific version of a module, \n", " or to `redirect` a module to a local directory for development (see `Replace` section below)\n", " \n", "Example:" ] }, { "cell_type": "code", "execution_count": 21, "id": "be207993-219d-4a7f-a130-5111971fb867", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/tmp/gonb_036046a6\n", "total 9296\n", "-rw-r--r-- 1 janpf janpf 1202 Jul 20 09:15 go.mod\n", "-rwxr-xr-x 1 janpf janpf 9491670 Jul 20 09:15 gonb_036046a6\n", "prw------- 1 janpf janpf 0 Jul 20 09:15 gonb_pipe_3304903318\n", "srwxr-xr-x 1 janpf janpf 0 Jul 20 09:14 gopls_socket\n", "-rw-r--r-- 1 janpf janpf 10229 Jul 20 09:15 go.sum\n", "-rw-r--r-- 1 janpf janpf 4819 Jul 20 09:15 main.go\n" ] } ], "source": [ "!*pwd ; ls -l" ] }, { "cell_type": "markdown", "id": "c7155d4a-1076-4b63-bee5-bf0ae2baaeec", "metadata": {}, "source": [ "You can also use a `\\` at the end of the line to extend the shell command to multiple lines.\n", "\n", "Example:" ] }, { "cell_type": "code", "execution_count": 22, "id": "8688859a-ec3b-4e54-99b4-abbd8542091d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Counting: 4 ...\n" ] } ], "source": [ "!((ii=0)) ;\\\n", "while ((ii < 5)) ; do \\\n", " printf \"\\rCounting: ${ii} ...\" ;\\\n", " sleep 1;\\\n", " ((ii+=1));\\\n", "done;\\\n", "echo" ] }, { "cell_type": "markdown", "id": "81f89ec8-242c-4acf-9ece-af896fb1ad5f", "metadata": {}, "source": [ "If some shell program requires some input from the user, you can precede it with a `%with_inputs` or `%with_password` (for hidden input) and it will open a text field for typing some arbitrary text input. Example:\n", "\n", "```shell\n", "%with_password\n", "!sudo -S apt update\n", "```\n", "\n", "## Environment Variables\n", "\n", "For convenience, **GoNB** defines the following environment variables -- available for the shell scripts (`!` and `!*`) and for the _Go_ cells:\n", "\n", "* `GONB_DIR`: the directory where commands are executed from. This can be changed with `%cd`.\n", "* `GONB_TMP_DIR`: the directory where the temporary Go code, with the cell code, is stored and compiled. This is the directory where `!*` scripts are executed. It only changes when a kernel is restarted, and a new temporary directory is created.\n", "* `GONB_PIPE`: is the _named pipe_ directory used to communicate rich content (HTML, images) to the kernel. Only available for _Go_ cells, and a new one is created at every execution. This is used by the `gonbui` functions described above, and doesn't need to be accessed directly." ] }, { "cell_type": "markdown", "id": "fc3e1354-7a50-4db9-a82b-ad42d6e9c102", "metadata": {}, "source": [ "## Developing Go libraries with a notebook: `go.mod` and `go.work`\n", "\n", "*GoNB* uses `go.mod` and understands `go.work` -- but won't create it by default.\n", "\n", "### \"Replace\" modules in `go.mod`\n", "\n", "Using the `!*` command above we can easily \"replace\" a module to a local directory. This can be very handy\n", "for developing a library in a powerful IDE on the side, and using the *GoNB* notebook to execute tests\n", "and experiments. Changes in the library (in the IDE) when saved immediate take effect on the next cell execution.\n", "\n", "\n", "The accompaining library *gonbui* was implemented mostly in this fashion using a notebook, that started with:\n", "\n", "```\n", "!*go mod edit -replace github.com/janpfeifer/gonb=/home/janpf/Projects/gonb\n", "```\n", "\n", "Check out the results with:\n", "\n", "```\n", "!*cat go.mod\n", "```" ] }, { "cell_type": "code", "execution_count": 23, "id": "3391f12e-131b-45b8-b270-6ba06abaac8c", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "module gonb_036046a6\n", "\n", "go 1.20\n", "\n", "require (\n", "\tgithub.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b\n", "\tgithub.com/benc-uk/gofract v0.0.0-20230120162050-a6f644f92fd6\n", "\tgithub.com/erkkah/margaid v0.1.1-0.20230128143048-d60b2efd2f5a\n", "\tgithub.com/janpfeifer/gonb v0.7.3\n", "\tgithub.com/schollz/progressbar/v3 v3.13.1\n", "\tgolang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1\n", "\tgonum.org/v1/plot v0.13.0\n", ")\n", "\n", "require (\n", "\tgit.sr.ht/~sbinet/gg v0.4.1 // indirect\n", "\tgithub.com/go-fonts/liberation v0.3.1 // indirect\n", "\tgithub.com/go-latex/latex v0.0.0-20230307184459-12ec69307ad9 // indirect\n", "\tgithub.com/go-pdf/fpdf v0.8.0 // indirect\n", "\tgithub.com/gofrs/uuid v4.4.0+incompatible // indirect\n", "\tgithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect\n", "\tgithub.com/lucasb-eyer/go-colorful v1.0.3 // indirect\n", "\tgithub.com/mattn/go-runewidth v0.0.14 // indirect\n", "\tgithub.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect\n", "\tgithub.com/pkg/errors v0.9.1 // indirect\n", "\tgithub.com/rivo/uniseg v0.2.0 // indirect\n", "\tgolang.org/x/image v0.7.0 // indirect\n", "\tgolang.org/x/sys v0.7.0 // indirect\n", "\tgolang.org/x/term v0.6.0 // indirect\n", "\tgolang.org/x/text v0.9.0 // indirect\n", "\tgopkg.in/yaml.v2 v2.3.0 // indirect\n", ")\n", "\n", "replace github.com/janpfeifer/gonb => /home/janpf/Projects/gonb\n" ] } ], "source": [ "!*go mod edit -replace \"github.com/janpfeifer/gonb=${HOME}/Projects/gonb\"\n", "!*cat go.mod" ] }, { "cell_type": "markdown", "id": "1e46fc85-fb7a-43dd-9434-43d2d5faded8", "metadata": {}, "source": [ "### \"Use\" modules in `go.work`\n", "\n", "Another way to refer to modules that are being co-developed in local file is using [Go workspaces](https://go.dev/doc/tutorial/workspaces).\n", " \n", "In **GoNB**, a convenient way to achive this is by first creating a `go.work` and then selecting the modules to be use from the local disk. Example: " ] }, { "cell_type": "code", "execution_count": 24, "id": "45cf4a12-4b93-480f-bd83-2d375e7a475d", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\t- replace rule for module \"github.com/janpfeifer/gonb\" to local directory \"/home/janpf/Projects/gonb\" already exists." ] } ], "source": [ "!*rm -f go.work && go work init && go work use . \"${HOME}/Projects/gonb\"\n", "%goworkfix" ] }, { "cell_type": "markdown", "id": "29f2828e-a7e7-4264-aca8-c47ed4377c17", "metadata": {}, "source": [ "> **Note**:\n", "> - **GoNB** uses `go get` to automatically fetch missing imports.\n", "> Unfortunately `go get` doesn't handle `go.work` `use` definitions.\n", "> The special command `%goworkfix` handles that by adding a `replace` entry in `go.mod` for\n", "> all modules pointed to by `go.work`.\n", "> - One can use the env variable `GONB_DIR` to refer to the current kernel directory (changed with `%cd`)." ] }, { "cell_type": "markdown", "id": "6594c119-e2e9-4d93-a4bd-506b4ab190fc", "metadata": {}, "source": [ "### Tracked directories\n", "\n", "**GoNB** tracks for changes in local files in target directories of `replace` rules in `go.mod` or `use` rules in `go.work`. This way auto-complete and contextual help stay up-to-date with changes on local files you may be editing on a separate editor.\n", "\n", "See `%track` and `%untrack` to list and control tracking. For instance, in our tutorial, this is what **GoNB** is tracking:" ] }, { "cell_type": "code", "execution_count": 25, "id": "f6d836c1-3dfd-41a0-b097-b157f33289a8", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "List of files/directories being tracked:\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%track" ] }, { "cell_type": "markdown", "id": "1c54e53a-037c-451e-9fd4-116d27c58296", "metadata": {}, "source": [ "## More ... and Help\n", "\n", "Some other features:\n", "\n", "* **Errors reported** by the Go compiler are parsed and a **_mouse-over_ context is displayed**. This facilitates understanding the error, since the line numbers reported by Go are not the same as in the cell being executed.\n", "* **Contextual Help**: can be activated with **\"Shift+Tab\"\"** (floating note) or **\"Control+I\"** (for a separate sub-window). Notice it may be slow if some new import needs to be fetched -- consider executing once some code with the imports before using the contextual help.\n", "\n", "The library is new, and there is still development going on, with still some features in the pipeline (more on the displaying side, auto-complete). For those\n", "who enjoy coding, help in improving *GoNB* is very welcome!\n", "\n", "Finally, there is also the `%help` command, which lists all the currently supported features:" ] }, { "cell_type": "code", "execution_count": 26, "id": "ba9172b8-ede5-44cd-baa1-a58a1d668a98", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GoNB is a Go kernel that compiles and executed on-the-fly Go code. \n", "\n", "When executing a cell, *GoNB* will save the cell contents (except non-Go commands see\n", "below) into a \"main.go\" file, compile and execute it.\n", "\n", "It also saves any global declarations (imports, functions, types, variables, constants)\n", "and reuse them at the next cell execution -- so you can define a function in one\n", "cell, and reuse in the next one. Just the \"func main()\" is not reused.\n", "\n", "A \"hello world\" example would look like:\n", "\n", "\tfunc main() {\n", "\t\tfmt.Printf(\"Hello world!\\n\");\n", "\t}\n", "\n", "But to avoid having to type \"func main()\" all the time, you can use \"%%\" and everything\n", "after is wrapped inside a \"func main() { ... }\". So our revised \"hello world\" looks like:\n", "\n", "\t%%\n", "\tfmt.Printf(\"Hello world!\\n\")\n", "\n", "\n", "- \"init()\" functions: since there is always only one definition per function name, \n", " it's not possible for each cell to have it's own init() function. Instead GoNB\n", " converts any function named \"init_()\" to \"init()\" before compiling and\n", " executing. This way each cell can create its own \"init_...()\" and have it called\n", " at every cell execution.\n", "\n", "Special non-Go commands: \n", "\n", "- \"%%\" or \"%main\": Marks the lines as follows to be wrapped in a \"func main() {...}\" during \n", " execution. A shortcut to quickly execute code. It also automatically includes \"flag.Parse()\"\n", " as the very first statement. Anything \"%%\" or \"%main\" are taken as arguments\n", " to be passed to the program -- it resets previous values given by \"%args\".\n", "- \"%args\": Sets arguments to be passed when executing the Go code. This allows one to\n", " use flags as a normal program. Notice that if a value after \"%%\" or \"%main\" is given, it will\n", " overwrite the values here.\n", "- \"%autoget\" and \"%noautoget\": Default is \"%autoget\", which automatically does \"go get\" for\n", " packages not yet available.\n", "- \"%cd []\": Change current directory of the Go kernel, and the directory from where\n", " the cells are executed. If no directory is given it reports the current directory.\n", "- \"%env VAR value\": Sets the environment variable VAR to the given value. These variables\n", " will be available both for Go code as well as for shell scripts.\n", "- \"%with_inputs\": will prompt for inputs for the next shell command. Use this if\n", " the next shell command (\"!\") you execute reads the stdin. Jupyter will require\n", " you to enter one last value after the shell script executes.\n", "- \"%with_password\": will prompt for a password passed to the next shell command.\n", " Do this is if your next shell command requires a password.\n", "\n", "Managing memorized definitions;\n", "\n", "- \"%list\" (or \"%ls\"): Lists all memorized definitions (imports, constants, types, variables and\n", " functions) that are carried from one cell to another.\n", "- \"%remove \" (or \"%rm \"): Removes (forgets) given definition(s). Use as key the\n", " value(s) listed with \"%ls\".\n", "- \"%reset\" clears memory of memorized definitions.\n", "\n", "Executing shell commands:\n", "\n", "- \"!\": executes the given command on a new shell. It makes it easy to run\n", " commands on the kernels box, for instance to install requirements, or quickly\n", " check contents of directories or files. Lines ending in \"\\\" are continued on\n", " the next line -- so multi-line commands can be entered. But each command is\n", " executed in its own shell, that is, variables and state is not carried over.\n", "- \"!*\": same as \"!\" except it first changes directory to\n", " the temporary directory used to compile the go code -- the latest execution\n", " is always saved in the file \"main.go\". It's also where the \"go.mod\" file for\n", " the notebook is created and maintained. Useful for manipulating \"go.mod\",\n", " for instance to get a package from some specific version, something \n", " like \"!*go get github.com/my/package@v3\".\n", "\n", "Tracking of Go files being developed:\n", "\n", "- \"%track [file_or_directory]\": add file or directory to list of tracked files,\n", " which are monitored by GoNB (and 'gopls') for auto-complete or contextual help.\n", " If no file is given, it lists the currently tracked files.\n", "- \"%untrack [file_or_directory][...]\": remove file or directory from list of tracked files.\n", " If suffixed with \"...\" it will remove all files prefixed with the string given (without the\n", " \"...\"). If no file is given, it lists the currently tracked files. \n", "\n", "Other:\n", "\n", "- \"%goworkfix\": work around 'go get' inability to handle 'go.work' files. If you are\n", " using 'go.work' file to point to locally modified modules, consider using this. It creates\n", " 'go mod edit --replace' rules to point to the modules pointed to the 'use' rules in 'go.work'\n", " file. It overwrites/updates 'replace' rules for those modules, if they already exist. See tutorial\n", " for an example.\n" ] } ], "source": [ "%help" ] } ], "metadata": { "kernelspec": { "display_name": "Go (gonb)", "language": "go", "name": "gonb" }, "language_info": { "codemirror_mode": "", "file_extension": ".go", "mimetype": "", "name": "go", "nbconvert_exporter": "", "pygments_lexer": "", "version": "go1.20.5" } }, "nbformat": 4, "nbformat_minor": 5 }