aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony DiGirolamo <tonymd@google.com>2022-03-06 10:13:51 -0800
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-03-16 18:18:35 +0000
commit6e6f440f401b3ff386efcc313dfefc40ebc1fdda (patch)
treec20001985094a1746e7cbc8ed310f3868ae81e3c
parent86698c0b9620febe11cc274a44c9457e6127dd62 (diff)
downloadpigweed-6e6f440f401b3ff386efcc313dfefc40ebc1fdda.tar.gz
pw_console: Fuzzy command runner dialog
- New command runner for searching and running menu item actions - Open logger menu converted to a command runner action instead of a large nested submenu. - Renamed some menu items for better searchability - Removed unused WindowPane after_render_hooks - border.py now accepts a title to display in the upper left. - Numerous fixes to window focus behavior when opening and closing the command runner dialog. - Added 'Copy all Python Input' and Output menu options. Change-Id: I1430dd3215fa45eee48e00d40ec309bb6b1b8f10 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/86900 Reviewed-by: Chad Norvell <chadnorvell@google.com> Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
-rw-r--r--pw_console/BUILD.gn1
-rw-r--r--pw_console/images/command_runner_main_menu.svg1984
-rw-r--r--pw_console/py/BUILD.gn2
-rw-r--r--pw_console/py/command_runner_test.py258
-rw-r--r--pw_console/py/log_view_test.py4
-rw-r--r--pw_console/py/pw_console/command_runner.py517
-rw-r--r--pw_console/py/pw_console/console_app.py216
-rw-r--r--pw_console/py/pw_console/console_prefs.py27
-rw-r--r--pw_console/py/pw_console/docs/user_guide.rst76
-rw-r--r--pw_console/py/pw_console/help_window.py13
-rw-r--r--pw_console/py/pw_console/key_bindings.py7
-rw-r--r--pw_console/py/pw_console/log_pane.py8
-rw-r--r--pw_console/py/pw_console/repl_pane.py15
-rw-r--r--pw_console/py/pw_console/search_toolbar.py1
-rw-r--r--pw_console/py/pw_console/style.py30
-rw-r--r--pw_console/py/pw_console/widgets/border.py16
-rw-r--r--pw_console/py/pw_console/widgets/window_pane.py10
-rw-r--r--pw_console/py/pw_console/widgets/window_pane_toolbar.py10
-rw-r--r--pw_console/py/pw_console/window_list.py13
-rw-r--r--pw_console/py/pw_console/window_manager.py8
-rw-r--r--pw_console/py/window_manager_test.py82
21 files changed, 3116 insertions, 182 deletions
diff --git a/pw_console/BUILD.gn b/pw_console/BUILD.gn
index 119377c4b..eee9a4ff2 100644
--- a/pw_console/BUILD.gn
+++ b/pw_console/BUILD.gn
@@ -19,6 +19,7 @@ import("$dir_pw_docgen/docs.gni")
pw_doc_group("docs") {
inputs = [
"images/serial_debug.svg",
+ "images/command_runner_main_menu.svg",
"images/calculator_plugin.png",
"images/clock_plugin1.png",
"images/clock_plugin2.png",
diff --git a/pw_console/images/command_runner_main_menu.svg b/pw_console/images/command_runner_main_menu.svg
new file mode 100644
index 000000000..4ef98ef2a
--- /dev/null
+++ b/pw_console/images/command_runner_main_menu.svg
@@ -0,0 +1,1984 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1428pt" height="682pt" viewBox="0 0 1428 682" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 3.203125 -1.046875 L 10.796875 -1.046875 L 10.796875 -19.8125 L 3.203125 -19.8125 Z M 1.265625 0.875 L 1.265625 -21.734375 L 12.734375 -21.734375 L 12.734375 0.875 Z M 7.59375 -9.09375 L 7.59375 -8.375 L 5.671875 -8.375 L 5.671875 -9.109375 C 5.671875 -9.796875 5.878906 -10.441406 6.296875 -11.046875 L 7.828125 -13.296875 C 8.097656 -13.679688 8.234375 -14.035156 8.234375 -14.359375 C 8.234375 -14.816406 8.097656 -15.207031 7.828125 -15.53125 C 7.566406 -15.851562 7.210938 -16.015625 6.765625 -16.015625 C 5.960938 -16.015625 5.34375 -15.484375 4.90625 -14.421875 L 3.34375 -15.34375 C 4.1875 -16.957031 5.332031 -17.765625 6.78125 -17.765625 C 7.75 -17.765625 8.550781 -17.4375 9.1875 -16.78125 C 9.820312 -16.132812 10.140625 -15.320312 10.140625 -14.34375 C 10.140625 -13.644531 9.898438 -12.941406 9.421875 -12.234375 L 7.8125 -9.890625 C 7.664062 -9.679688 7.59375 -9.414062 7.59375 -9.09375 Z M 6.78125 -6.75 C 7.144531 -6.75 7.457031 -6.617188 7.71875 -6.359375 C 7.988281 -6.109375 8.125 -5.796875 8.125 -5.421875 C 8.125 -5.046875 7.988281 -4.726562 7.71875 -4.46875 C 7.457031 -4.207031 7.144531 -4.078125 6.78125 -4.078125 C 6.394531 -4.078125 6.070312 -4.207031 5.8125 -4.46875 C 5.5625 -4.726562 5.4375 -5.046875 5.4375 -5.421875 C 5.4375 -5.796875 5.5625 -6.109375 5.8125 -6.359375 C 6.070312 -6.617188 6.394531 -6.75 6.78125 -6.75 Z M 6.78125 -6.75 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d=""/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 11.546875 1.8125 L 4.296875 1.8125 L 4.296875 -22.671875 L 11.546875 -22.671875 L 11.546875 -20.609375 L 6.625 -20.609375 L 6.625 -0.265625 L 11.546875 -0.265625 Z M 11.546875 1.8125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 12.8125 -18.875 L 5.25 -18.875 L 5.25 -12.125 L 11.328125 -12.125 L 11.328125 -10.140625 L 5.25 -10.140625 L 5.25 0 L 2.921875 0 L 2.921875 -20.859375 L 12.8125 -20.859375 Z M 12.8125 -18.875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 8.484375 -20.734375 C 8.484375 -20.234375 8.3125 -19.804688 7.96875 -19.453125 C 7.632812 -19.109375 7.210938 -18.9375 6.703125 -18.9375 C 6.191406 -18.9375 5.765625 -19.109375 5.421875 -19.453125 C 5.078125 -19.804688 4.90625 -20.234375 4.90625 -20.734375 C 4.90625 -21.222656 5.078125 -21.640625 5.421875 -21.984375 C 5.765625 -22.335938 6.191406 -22.515625 6.703125 -22.515625 C 7.210938 -22.515625 7.632812 -22.335938 7.96875 -21.984375 C 8.3125 -21.640625 8.484375 -21.222656 8.484375 -20.734375 Z M 12 0 L 2.25 0 L 2.25 -1.984375 L 5.96875 -1.984375 L 5.96875 -13.5 L 3.296875 -13.5 L 3.296875 -15.484375 L 8.296875 -15.484375 L 8.296875 -1.984375 L 12 -1.984375 Z M 12 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 11.875 0 L 2.125 0 L 2.125 -1.984375 L 5.84375 -1.984375 L 5.84375 -18.875 L 3.1875 -18.875 L 3.1875 -20.859375 L 8.171875 -20.859375 L 8.171875 -1.984375 L 11.875 -1.984375 Z M 11.875 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 12.203125 -7.28125 L 4.109375 -7.28125 L 4.109375 -6.8125 C 4.109375 -4.8125 4.398438 -3.484375 4.984375 -2.828125 C 5.566406 -2.171875 6.359375 -1.84375 7.359375 -1.84375 C 8.628906 -1.84375 9.644531 -2.488281 10.40625 -3.78125 L 12.296875 -2.578125 C 11.109375 -0.679688 9.410156 0.265625 7.203125 0.265625 C 5.628906 0.265625 4.332031 -0.296875 3.3125 -1.421875 C 2.289062 -2.554688 1.78125 -4.351562 1.78125 -6.8125 L 1.78125 -8.6875 C 1.78125 -11.132812 2.289062 -12.925781 3.3125 -14.0625 C 4.332031 -15.195312 5.5625 -15.765625 7 -15.765625 C 8.53125 -15.765625 9.78125 -15.238281 10.75 -14.1875 C 11.71875 -13.144531 12.203125 -11.441406 12.203125 -9.078125 Z M 9.890625 -9.328125 C 9.890625 -10.898438 9.617188 -12.015625 9.078125 -12.671875 C 8.535156 -13.328125 7.84375 -13.65625 7 -13.65625 C 6.195312 -13.65625 5.515625 -13.328125 4.953125 -12.671875 C 4.390625 -12.015625 4.109375 -10.898438 4.109375 -9.328125 Z M 9.890625 -9.328125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 9.703125 1.8125 L 2.46875 1.8125 L 2.46875 -0.265625 L 7.375 -0.265625 L 7.375 -20.609375 L 2.46875 -20.609375 L 2.46875 -22.671875 L 9.703125 -22.671875 Z M 9.703125 1.8125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 12.203125 0 L 2.578125 0 L 2.578125 -20.859375 L 12.203125 -20.859375 L 12.203125 -18.875 L 4.90625 -18.875 L 4.90625 -12.125 L 10.296875 -12.125 L 10.296875 -10.140625 L 4.90625 -10.140625 L 4.90625 -1.984375 L 12.203125 -1.984375 Z M 12.203125 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 1.59375 -8.8125 C 1.59375 -11.28125 2.03125 -13.054688 2.90625 -14.140625 C 3.789062 -15.222656 4.847656 -15.765625 6.078125 -15.765625 C 7.671875 -15.765625 8.875 -15.046875 9.6875 -13.609375 L 9.6875 -20.859375 L 12 -20.859375 L 12 0 L 9.6875 0 L 9.6875 -1.859375 C 8.875 -0.441406 7.671875 0.265625 6.078125 0.265625 C 4.847656 0.265625 3.789062 -0.269531 2.90625 -1.34375 C 2.03125 -2.425781 1.59375 -4.203125 1.59375 -6.671875 Z M 3.984375 -6.671875 C 3.984375 -4.878906 4.207031 -3.625 4.65625 -2.90625 C 5.113281 -2.195312 5.78125 -1.84375 6.65625 -1.84375 C 8.1875 -1.84375 9.195312 -2.867188 9.6875 -4.921875 L 9.6875 -10.4375 C 9.207031 -12.582031 8.195312 -13.65625 6.65625 -13.65625 C 5.78125 -13.65625 5.113281 -13.296875 4.65625 -12.578125 C 4.207031 -11.867188 3.984375 -10.613281 3.984375 -8.8125 Z M 3.984375 -6.671875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-10">
+<path style="stroke:none;" d="M 12.953125 -2.15625 C 11.867188 -0.539062 10.414062 0.265625 8.59375 0.265625 C 7.394531 0.265625 6.382812 -0.140625 5.5625 -0.953125 C 4.75 -1.773438 4.34375 -2.984375 4.34375 -4.578125 L 4.34375 -13.5 L 1.75 -13.5 L 1.75 -15.484375 L 4.34375 -15.484375 L 4.34375 -20.859375 L 6.671875 -20.859375 L 6.671875 -15.484375 L 11.890625 -15.484375 L 11.890625 -13.5 L 6.671875 -13.5 L 6.671875 -4.4375 C 6.671875 -3.582031 6.851562 -2.9375 7.21875 -2.5 C 7.582031 -2.0625 8.085938 -1.84375 8.734375 -1.84375 C 9.804688 -1.84375 10.625 -2.378906 11.1875 -3.453125 Z M 12.953125 -2.15625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-11">
+<path style="stroke:none;" d="M 5.6875 0 L 3.109375 -9.609375 C 1.941406 -13.910156 1.359375 -17.273438 1.359375 -19.703125 L 1.359375 -20.859375 L 3.6875 -20.859375 L 3.6875 -19.703125 C 3.6875 -17.691406 4.125 -14.804688 5 -11.046875 L 7 -2.609375 L 9 -11.046875 C 9.875 -14.804688 10.3125 -17.691406 10.3125 -19.703125 L 10.3125 -20.859375 L 12.640625 -20.859375 L 12.640625 -19.703125 C 12.640625 -17.273438 12.054688 -13.910156 10.890625 -9.609375 L 8.3125 0 Z M 5.6875 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-12">
+<path style="stroke:none;" d="M 9.578125 -1.28125 L 10.125 -6.296875 C 10.351562 -8.390625 10.46875 -10.53125 10.46875 -12.71875 L 10.46875 -15.484375 L 12.75 -15.484375 L 12.75 -13.421875 C 12.75 -11.554688 12.484375 -9.179688 11.953125 -6.296875 L 10.796875 0 L 8.609375 0 L 7 -6.96875 L 5.390625 0 L 3.203125 0 L 2.046875 -6.296875 C 1.523438 -9.179688 1.265625 -11.554688 1.265625 -13.421875 L 1.265625 -15.484375 L 3.53125 -15.484375 L 3.53125 -12.71875 C 3.53125 -10.53125 3.644531 -8.390625 3.875 -6.296875 L 4.421875 -1.28125 L 6.265625 -9.25 L 7.734375 -9.25 Z M 9.578125 -1.28125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-13">
+<path style="stroke:none;" d="M 9.734375 -1.265625 L 10.09375 -6.1875 C 10.226562 -8.007812 10.296875 -10.070312 10.296875 -12.375 L 10.296875 -20.859375 L 12.625 -20.859375 L 12.625 -15.828125 C 12.625 -12.398438 12.375 -9.1875 11.875 -6.1875 L 10.90625 0 L 8.71875 0 L 7 -8.078125 L 5.28125 0 L 3.09375 0 L 2.125 -6.1875 C 1.625 -9.1875 1.375 -12.398438 1.375 -15.828125 L 1.375 -20.859375 L 3.703125 -20.859375 L 3.703125 -12.375 C 3.703125 -10.070312 3.769531 -8.007812 3.90625 -6.1875 L 4.265625 -1.265625 L 6.265625 -10.671875 L 7.734375 -10.671875 Z M 9.734375 -1.265625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-14">
+<path style="stroke:none;" d="M 12.015625 0 L 9.6875 0 L 9.6875 -10.03125 C 9.6875 -11.375 9.476562 -12.304688 9.0625 -12.828125 C 8.644531 -13.359375 8.070312 -13.625 7.34375 -13.625 C 5.8125 -13.625 4.800781 -12.570312 4.3125 -10.46875 L 4.3125 0 L 1.984375 0 L 1.984375 -15.484375 L 4.3125 -15.484375 L 4.3125 -13.5 C 5.300781 -15.007812 6.503906 -15.765625 7.921875 -15.765625 C 9.066406 -15.765625 10.035156 -15.335938 10.828125 -14.484375 C 11.617188 -13.628906 12.015625 -12.191406 12.015625 -10.171875 Z M 12.015625 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-15">
+<path style="stroke:none;" d="M 12.21875 -6.703125 C 12.21875 -4.328125 11.726562 -2.570312 10.75 -1.4375 C 9.78125 -0.300781 8.53125 0.265625 7 0.265625 C 5.46875 0.265625 4.21875 -0.300781 3.25 -1.4375 C 2.28125 -2.570312 1.796875 -4.328125 1.796875 -6.703125 L 1.796875 -8.8125 C 1.796875 -11.175781 2.28125 -12.925781 3.25 -14.0625 C 4.21875 -15.195312 5.46875 -15.765625 7 -15.765625 C 8.53125 -15.765625 9.78125 -15.195312 10.75 -14.0625 C 11.726562 -12.925781 12.21875 -11.175781 12.21875 -8.8125 Z M 9.90625 -6.703125 L 9.90625 -8.8125 C 9.90625 -10.632812 9.628906 -11.894531 9.078125 -12.59375 C 8.535156 -13.300781 7.84375 -13.65625 7 -13.65625 C 6.15625 -13.65625 5.460938 -13.300781 4.921875 -12.59375 C 4.378906 -11.894531 4.109375 -10.632812 4.109375 -8.8125 L 4.109375 -6.703125 C 4.109375 -4.867188 4.378906 -3.597656 4.921875 -2.890625 C 5.460938 -2.191406 6.15625 -1.84375 7 -1.84375 C 7.84375 -1.84375 8.535156 -2.191406 9.078125 -2.890625 C 9.628906 -3.597656 9.90625 -4.867188 9.90625 -6.703125 Z M 9.90625 -6.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-16">
+<path style="stroke:none;" d="M 7.0625 -1.796875 C 8.019531 -1.796875 8.75 -2.023438 9.25 -2.484375 C 9.75 -2.941406 10 -3.5 10 -4.15625 C 10 -5.0625 9.445312 -5.765625 8.34375 -6.265625 L 5.359375 -7.625 C 3.503906 -8.5 2.578125 -9.75 2.578125 -11.375 C 2.578125 -12.644531 3.03125 -13.691406 3.9375 -14.515625 C 4.851562 -15.347656 6.035156 -15.765625 7.484375 -15.765625 C 9.546875 -15.765625 11.128906 -14.8125 12.234375 -12.90625 L 10.34375 -11.765625 C 9.757812 -13.054688 8.804688 -13.703125 7.484375 -13.703125 C 6.691406 -13.703125 6.0625 -13.5 5.59375 -13.09375 C 5.132812 -12.695312 4.90625 -12.203125 4.90625 -11.609375 C 4.90625 -10.816406 5.421875 -10.175781 6.453125 -9.6875 L 9.265625 -8.375 C 11.296875 -7.425781 12.3125 -5.984375 12.3125 -4.046875 C 12.3125 -2.898438 11.835938 -1.894531 10.890625 -1.03125 C 9.941406 -0.164062 8.65625 0.265625 7.03125 0.265625 C 4.75 0.265625 2.96875 -0.789062 1.6875 -2.90625 L 3.59375 -4.0625 C 4.351562 -2.550781 5.507812 -1.796875 7.0625 -1.796875 Z M 7.0625 -1.796875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-17">
+<path style="stroke:none;" d="M 12.015625 0 L 9.6875 0 L 9.6875 -10.4375 L 4.3125 -10.4375 L 4.3125 0 L 1.984375 0 L 1.984375 -20.859375 L 4.3125 -20.859375 L 4.3125 -12.421875 L 9.6875 -12.421875 L 9.6875 -20.859375 L 12.015625 -20.859375 Z M 12.015625 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-18">
+<path style="stroke:none;" d="M 12.421875 -6.65625 C 12.421875 -4.21875 11.953125 -2.453125 11.015625 -1.359375 C 10.085938 -0.273438 9.054688 0.265625 7.921875 0.265625 C 6.328125 0.265625 5.128906 -0.457031 4.328125 -1.90625 L 4.328125 4.828125 L 2 4.828125 L 2 -15.484375 L 4.328125 -15.484375 L 4.328125 -13.640625 C 5.128906 -15.054688 6.328125 -15.765625 7.921875 -15.765625 C 9.054688 -15.765625 10.085938 -15.222656 11.015625 -14.140625 C 11.953125 -13.066406 12.421875 -11.289062 12.421875 -8.8125 Z M 10.015625 -8.8125 C 10.015625 -10.625 9.765625 -11.882812 9.265625 -12.59375 C 8.765625 -13.300781 8.125 -13.65625 7.34375 -13.65625 C 5.8125 -13.65625 4.804688 -12.59375 4.328125 -10.46875 L 4.328125 -5.046875 C 4.796875 -2.910156 5.800781 -1.84375 7.34375 -1.84375 C 8.125 -1.84375 8.765625 -2.203125 9.265625 -2.921875 C 9.765625 -3.640625 10.015625 -4.882812 10.015625 -6.65625 Z M 10.015625 -8.8125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-19">
+<path style="stroke:none;" d="M 12.953125 -3.09375 C 11.648438 -0.851562 9.878906 0.265625 7.640625 0.265625 C 6.128906 0.265625 4.851562 -0.238281 3.8125 -1.25 C 2.769531 -2.269531 2.25 -4.132812 2.25 -6.84375 L 2.25 -14.046875 C 2.25 -16.679688 2.769531 -18.523438 3.8125 -19.578125 C 4.851562 -20.640625 6.117188 -21.171875 7.609375 -21.171875 C 9.953125 -21.171875 11.6875 -20.039062 12.8125 -17.78125 L 10.90625 -16.625 C 10.21875 -18.238281 9.125 -19.046875 7.625 -19.046875 C 6.757812 -19.046875 6.035156 -18.726562 5.453125 -18.09375 C 4.878906 -17.457031 4.59375 -16.109375 4.59375 -14.046875 L 4.59375 -6.84375 C 4.59375 -4.78125 4.878906 -3.429688 5.453125 -2.796875 C 6.035156 -2.160156 6.757812 -1.84375 7.625 -1.84375 C 9.125 -1.84375 10.265625 -2.6875 11.046875 -4.375 Z M 12.953125 -3.09375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-20">
+<path style="stroke:none;" d="M 12.453125 -18.875 L 8.15625 -18.875 L 8.15625 0 L 5.84375 0 L 5.84375 -18.875 L 1.546875 -18.875 L 1.546875 -20.859375 L 12.453125 -20.859375 Z M 12.453125 -18.875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-21">
+<path style="stroke:none;" d="M 12.328125 0 L 10.015625 0 L 10.015625 -5.515625 C 10.015625 -9.023438 10.148438 -13.148438 10.421875 -17.890625 L 7.71875 -9.25 L 6.28125 -9.25 L 3.578125 -17.890625 C 3.859375 -13.148438 4 -9.023438 4 -5.515625 L 4 0 L 1.671875 0 L 1.671875 -20.859375 L 4 -20.859375 L 7 -12.203125 L 10.015625 -20.859375 L 12.328125 -20.859375 Z M 12.328125 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-22">
+<path style="stroke:none;" d="M 12.53125 -4.875 C 12.53125 -3.457031 12.054688 -2.242188 11.109375 -1.234375 C 10.171875 -0.234375 8.867188 0.265625 7.203125 0.265625 C 4.578125 0.265625 2.660156 -0.878906 1.453125 -3.171875 L 3.171875 -4.46875 C 4.078125 -2.71875 5.414062 -1.84375 7.1875 -1.84375 C 8.007812 -1.84375 8.71875 -2.09375 9.3125 -2.59375 C 9.90625 -3.101562 10.203125 -3.859375 10.203125 -4.859375 C 10.203125 -5.671875 9.691406 -6.554688 8.671875 -7.515625 L 4.1875 -11.703125 C 2.9375 -12.878906 2.3125 -14.359375 2.3125 -16.140625 C 2.3125 -17.554688 2.769531 -18.75 3.6875 -19.71875 C 4.613281 -20.6875 5.878906 -21.171875 7.484375 -21.171875 C 9.566406 -21.171875 11.253906 -20.21875 12.546875 -18.3125 L 10.765625 -16.90625 C 9.992188 -18.332031 8.90625 -19.046875 7.5 -19.046875 C 6.6875 -19.046875 6.007812 -18.8125 5.46875 -18.34375 C 4.925781 -17.882812 4.65625 -17.148438 4.65625 -16.140625 C 4.65625 -15.109375 5.0625 -14.210938 5.875 -13.453125 L 10.34375 -9.296875 C 11.800781 -7.910156 12.53125 -6.4375 12.53125 -4.875 Z M 12.53125 -4.875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-23">
+<path style="stroke:none;" d="M 11.671875 0 L 9.359375 0 L 9.359375 -1.75 C 8.367188 -0.40625 7.125 0.265625 5.625 0.265625 C 4.351562 0.265625 3.328125 -0.164062 2.546875 -1.03125 C 1.765625 -1.90625 1.375 -3 1.375 -4.3125 C 1.375 -5.65625 1.863281 -6.78125 2.84375 -7.6875 C 3.820312 -8.601562 5.253906 -9.0625 7.140625 -9.0625 L 9.359375 -9.0625 L 9.359375 -10.734375 C 9.359375 -12.679688 8.429688 -13.65625 6.578125 -13.65625 C 5.210938 -13.65625 4.191406 -13.054688 3.515625 -11.859375 L 1.75 -13.171875 C 2.96875 -14.898438 4.582031 -15.765625 6.59375 -15.765625 C 8.070312 -15.765625 9.285156 -15.335938 10.234375 -14.484375 C 11.191406 -13.640625 11.671875 -12.390625 11.671875 -10.734375 Z M 9.359375 -3.640625 L 9.359375 -7.1875 L 7.140625 -7.1875 C 6.023438 -7.1875 5.1875 -6.925781 4.625 -6.40625 C 4.0625 -5.894531 3.78125 -5.195312 3.78125 -4.3125 C 3.78125 -2.664062 4.582031 -1.84375 6.1875 -1.84375 C 7.457031 -1.84375 8.515625 -2.441406 9.359375 -3.640625 Z M 9.359375 -3.640625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-24">
+<path style="stroke:none;" d="M 13 -12.859375 L 10.984375 -11.96875 C 10.523438 -13.09375 9.753906 -13.65625 8.671875 -13.65625 C 6.390625 -13.65625 5.25 -11.535156 5.25 -7.296875 L 5.25 0 L 2.921875 0 L 2.921875 -15.484375 L 5.25 -15.484375 L 5.25 -13 C 6.164062 -14.84375 7.425781 -15.765625 9.03125 -15.765625 C 10.894531 -15.765625 12.21875 -14.796875 13 -12.859375 Z M 13 -12.859375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-25">
+<path style="stroke:none;" d="M 12.84375 -2.578125 C 11.65625 -0.679688 9.957031 0.265625 7.75 0.265625 C 6.164062 0.265625 4.863281 -0.296875 3.84375 -1.421875 C 2.820312 -2.554688 2.3125 -4.347656 2.3125 -6.796875 L 2.3125 -8.703125 C 2.3125 -11.140625 2.820312 -12.925781 3.84375 -14.0625 C 4.863281 -15.195312 6.164062 -15.765625 7.75 -15.765625 C 9.957031 -15.765625 11.65625 -14.8125 12.84375 -12.90625 L 10.953125 -11.71875 C 10.179688 -13.007812 9.160156 -13.65625 7.890625 -13.65625 C 6.898438 -13.65625 6.113281 -13.328125 5.53125 -12.671875 C 4.945312 -12.015625 4.65625 -10.691406 4.65625 -8.703125 L 4.65625 -6.796875 C 4.65625 -4.804688 4.945312 -3.484375 5.53125 -2.828125 C 6.113281 -2.171875 6.898438 -1.84375 7.890625 -1.84375 C 9.160156 -1.84375 10.179688 -2.488281 10.953125 -3.78125 Z M 12.84375 -2.578125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-26">
+<path style="stroke:none;" d="M 12.015625 0 L 9.6875 0 L 9.6875 -10.015625 C 9.6875 -11.398438 9.476562 -12.351562 9.0625 -12.875 C 8.644531 -13.394531 8.070312 -13.65625 7.34375 -13.65625 C 5.8125 -13.65625 4.800781 -12.59375 4.3125 -10.46875 L 4.3125 0 L 1.984375 0 L 1.984375 -20.859375 L 4.3125 -20.859375 L 4.3125 -13.625 C 5.300781 -15.050781 6.503906 -15.765625 7.921875 -15.765625 C 9.066406 -15.765625 10.035156 -15.335938 10.828125 -14.484375 C 11.617188 -13.628906 12.015625 -12.179688 12.015625 -10.140625 Z M 12.015625 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-27">
+<path style="stroke:none;" d="M 12.015625 0 L 9.6875 0 L 9.6875 -2.015625 C 8.695312 -0.492188 7.492188 0.265625 6.078125 0.265625 C 4.929688 0.265625 3.960938 -0.164062 3.171875 -1.03125 C 2.378906 -1.90625 1.984375 -3.460938 1.984375 -5.703125 L 1.984375 -15.484375 L 4.3125 -15.484375 L 4.3125 -5.703125 C 4.3125 -4.203125 4.519531 -3.179688 4.9375 -2.640625 C 5.351562 -2.109375 5.925781 -1.84375 6.65625 -1.84375 C 8.1875 -1.84375 9.195312 -2.851562 9.6875 -4.875 L 9.6875 -15.484375 L 12.015625 -15.484375 Z M 12.015625 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-28">
+<path style="stroke:none;" d="M 12.28125 -7.296875 L 1.71875 -7.296875 L 1.71875 -9.28125 L 12.28125 -9.28125 Z M 12.28125 -7.296875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-29">
+<path style="stroke:none;" d="M 12.8125 0 L 10.484375 0 C 10.410156 -1.132812 9.851562 -2.460938 8.8125 -3.984375 L 6.5 -7.28125 L 4.765625 -5.1875 L 4.765625 0 L 2.453125 0 L 2.453125 -20.859375 L 4.765625 -20.859375 L 4.765625 -8.046875 L 8.1875 -12.25 C 9.332031 -13.65625 9.914062 -14.734375 9.9375 -15.484375 L 12.265625 -15.484375 L 12.234375 -14.96875 C 12.191406 -14.15625 11.421875 -12.835938 9.921875 -11.015625 L 8.0625 -8.734375 L 10.46875 -5.25 C 11.9375 -3.125 12.703125 -1.554688 12.765625 -0.546875 Z M 12.8125 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-30">
+<path style="stroke:none;" d="M 4.96875 0 L 2.640625 0 L 2.640625 -20.859375 L 7.1875 -20.859375 C 9.039062 -20.859375 10.441406 -20.351562 11.390625 -19.34375 C 12.335938 -18.34375 12.8125 -17.003906 12.8125 -15.328125 C 12.8125 -13.441406 12.289062 -11.992188 11.25 -10.984375 C 10.207031 -9.972656 8.851562 -9.46875 7.1875 -9.46875 L 4.96875 -9.46875 Z M 4.96875 -11.453125 L 7.171875 -11.453125 C 8.242188 -11.453125 9.050781 -11.722656 9.59375 -12.265625 C 10.132812 -12.804688 10.40625 -13.828125 10.40625 -15.328125 C 10.40625 -16.609375 10.15625 -17.519531 9.65625 -18.0625 C 9.164062 -18.601562 8.335938 -18.875 7.171875 -18.875 L 4.96875 -18.875 Z M 4.96875 -11.453125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-31">
+<path style="stroke:none;" d="M 12.671875 -8.5625 C 12.671875 -5.832031 12.046875 -3.722656 10.796875 -2.234375 C 9.554688 -0.742188 7.875 0 5.75 0 L 2.296875 0 L 2.296875 -20.859375 L 5.75 -20.859375 C 7.875 -20.859375 9.554688 -20.15625 10.796875 -18.75 C 12.046875 -17.351562 12.671875 -15.300781 12.671875 -12.59375 Z M 10.28125 -8.5625 L 10.28125 -12.59375 C 10.28125 -14.71875 9.875 -16.296875 9.0625 -17.328125 C 8.25 -18.359375 7.144531 -18.875 5.75 -18.875 L 4.609375 -18.875 L 4.609375 -1.984375 L 5.75 -1.984375 C 7.144531 -1.984375 8.25 -2.535156 9.0625 -3.640625 C 9.875 -4.742188 10.28125 -6.382812 10.28125 -8.5625 Z M 10.28125 -8.5625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-32">
+<path style="stroke:none;" d="M 12.421875 -6.671875 C 12.421875 -4.203125 11.976562 -2.425781 11.09375 -1.34375 C 10.207031 -0.269531 9.148438 0.265625 7.921875 0.265625 C 6.328125 0.265625 5.128906 -0.441406 4.328125 -1.859375 L 4.328125 0 L 2 0 L 2 -20.859375 L 4.328125 -20.859375 L 4.328125 -13.609375 C 5.128906 -15.046875 6.328125 -15.765625 7.921875 -15.765625 C 9.148438 -15.765625 10.207031 -15.222656 11.09375 -14.140625 C 11.976562 -13.054688 12.421875 -11.28125 12.421875 -8.8125 Z M 10.015625 -6.671875 L 10.015625 -8.8125 C 10.015625 -10.613281 9.785156 -11.867188 9.328125 -12.578125 C 8.878906 -13.296875 8.21875 -13.65625 7.34375 -13.65625 C 5.800781 -13.65625 4.796875 -12.625 4.328125 -10.5625 L 4.328125 -4.921875 C 4.804688 -2.867188 5.8125 -1.84375 7.34375 -1.84375 C 8.21875 -1.84375 8.878906 -2.195312 9.328125 -2.90625 C 9.785156 -3.625 10.015625 -4.878906 10.015625 -6.671875 Z M 10.015625 -6.671875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-33">
+<path style="stroke:none;" d="M 13.046875 -13.625 L 12.234375 -13.625 L 10.984375 -13.75 C 11.671875 -12.90625 12.015625 -12.046875 12.015625 -11.171875 C 12.015625 -9.972656 11.582031 -8.976562 10.71875 -8.1875 C 9.851562 -7.394531 8.671875 -7 7.171875 -7 C 6.609375 -7 6.097656 -7 5.640625 -7 C 4.898438 -6.519531 4.53125 -6.054688 4.53125 -5.609375 C 4.53125 -5.140625 4.675781 -4.789062 4.96875 -4.5625 C 5.257812 -4.34375 5.738281 -4.234375 6.40625 -4.234375 L 7.703125 -4.234375 C 9.628906 -4.234375 11.023438 -3.820312 11.890625 -3 C 12.753906 -2.1875 13.1875 -1.15625 13.1875 0.09375 C 13.1875 1.5 12.632812 2.660156 11.53125 3.578125 C 10.4375 4.492188 8.988281 4.953125 7.1875 4.953125 C 5.3125 4.953125 3.882812 4.523438 2.90625 3.671875 C 1.9375 2.828125 1.453125 1.800781 1.453125 0.59375 C 1.453125 -0.988281 2.25 -2.1875 3.84375 -3 C 2.664062 -3.488281 2.078125 -4.238281 2.078125 -5.25 C 2.078125 -6.269531 2.703125 -7.132812 3.953125 -7.84375 C 2.671875 -8.707031 2.03125 -9.898438 2.03125 -11.421875 C 2.03125 -12.679688 2.484375 -13.707031 3.390625 -14.5 C 4.296875 -15.300781 5.554688 -15.703125 7.171875 -15.703125 C 7.648438 -15.703125 8.804688 -15.628906 10.640625 -15.484375 L 13.046875 -15.484375 Z M 9.78125 -11.4375 C 9.78125 -12.050781 9.550781 -12.59375 9.09375 -13.0625 C 8.632812 -13.53125 7.953125 -13.765625 7.046875 -13.765625 C 6.109375 -13.765625 5.414062 -13.539062 4.96875 -13.09375 C 4.519531 -12.65625 4.296875 -12.085938 4.296875 -11.390625 C 4.296875 -10.585938 4.53125 -9.972656 5 -9.546875 C 5.476562 -9.128906 6.144531 -8.921875 7 -8.921875 C 7.925781 -8.921875 8.617188 -9.140625 9.078125 -9.578125 C 9.546875 -10.015625 9.78125 -10.632812 9.78125 -11.4375 Z M 10.78125 0.09375 C 10.78125 -0.59375 10.554688 -1.132812 10.109375 -1.53125 C 9.660156 -1.9375 8.859375 -2.140625 7.703125 -2.140625 L 6.765625 -2.140625 C 5.710938 -2.140625 4.960938 -1.898438 4.515625 -1.421875 C 4.066406 -0.941406 3.84375 -0.328125 3.84375 0.421875 C 3.84375 1.203125 4.132812 1.800781 4.71875 2.21875 C 5.300781 2.644531 6.070312 2.859375 7.03125 2.859375 C 9.53125 2.859375 10.78125 1.9375 10.78125 0.09375 Z M 10.78125 0.09375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-34">
+<path style="stroke:none;" d="M 4.140625 2.5 L 5.921875 -2.125 L 2.703125 -10.015625 C 1.941406 -11.910156 1.53125 -13.332031 1.46875 -14.28125 L 1.390625 -15.484375 L 3.71875 -15.484375 L 3.78125 -14.375 C 3.820312 -13.738281 4.179688 -12.503906 4.859375 -10.671875 L 7 -4.828125 L 9.140625 -10.59375 C 9.804688 -12.457031 10.164062 -13.71875 10.21875 -14.375 L 10.28125 -15.484375 L 12.609375 -15.484375 L 12.53125 -14.28125 C 12.476562 -13.4375 12.066406 -12.015625 11.296875 -10.015625 L 6.359375 2.796875 C 6.179688 3.234375 6.078125 3.742188 6.046875 4.328125 L 6.015625 4.828125 L 3.6875 4.828125 L 3.71875 4.328125 C 3.757812 3.742188 3.898438 3.132812 4.140625 2.5 Z M 4.140625 2.5 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-35">
+<path style="stroke:none;" d="M 7.265625 -9.515625 L 4.84375 -9.515625 L 4.84375 0 L 2.515625 0 L 2.515625 -20.859375 L 7.0625 -20.859375 C 8.914062 -20.859375 10.289062 -20.359375 11.1875 -19.359375 C 12.09375 -18.359375 12.546875 -17.015625 12.546875 -15.328125 C 12.546875 -13.898438 12.253906 -12.722656 11.671875 -11.796875 C 11.097656 -10.878906 10.382812 -10.257812 9.53125 -9.9375 L 9.78125 -9.5625 C 11.507812 -6.863281 12.460938 -3.988281 12.640625 -0.9375 L 12.703125 0 L 10.375 0 L 10.34375 -0.71875 C 10.164062 -3.632812 9.253906 -6.378906 7.609375 -8.953125 Z M 4.84375 -11.484375 L 7.0625 -11.484375 C 8.132812 -11.484375 8.914062 -11.800781 9.40625 -12.4375 C 9.894531 -13.082031 10.140625 -14.050781 10.140625 -15.34375 C 10.140625 -16.613281 9.894531 -17.519531 9.40625 -18.0625 C 8.914062 -18.601562 8.132812 -18.875 7.0625 -18.875 L 4.84375 -18.875 Z M 4.84375 -11.484375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-36">
+<path style="stroke:none;" d="M 3.8125 -1.15625 L 3.8125 0 L 1.484375 0 L 1.484375 -1.15625 C 1.484375 -3.15625 2.082031 -6.519531 3.28125 -11.25 L 5.6875 -20.859375 L 8.3125 -20.859375 L 10.71875 -11.25 C 11.914062 -6.519531 12.515625 -3.15625 12.515625 -1.15625 L 12.515625 0 L 10.1875 0 L 10.1875 -1.15625 C 10.1875 -2.101562 10.054688 -3.34375 9.796875 -4.875 L 4.203125 -4.875 C 3.941406 -3.34375 3.8125 -2.101562 3.8125 -1.15625 Z M 7 -17.171875 L 5.265625 -9.953125 C 4.992188 -8.835938 4.757812 -7.804688 4.5625 -6.859375 L 9.421875 -6.859375 C 9.234375 -7.804688 9.003906 -8.835938 8.734375 -9.953125 Z M 7 -17.171875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-37">
+<path style="stroke:none;" d="M 12.8125 0 L 3.328125 0 L 3.328125 -20.859375 L 5.640625 -20.859375 L 5.640625 -1.984375 L 12.8125 -1.984375 Z M 12.8125 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-38">
+<path style="stroke:none;" d="M 8.34375 0 L 5.65625 0 L 2.984375 -8.09375 C 2.054688 -10.863281 1.550781 -12.957031 1.46875 -14.375 L 1.390625 -15.484375 L 3.71875 -15.484375 L 3.78125 -14.375 C 3.863281 -13.03125 4.304688 -11.046875 5.109375 -8.421875 L 7 -2.1875 L 8.890625 -8.421875 C 9.691406 -11.046875 10.132812 -13.03125 10.21875 -14.375 L 10.28125 -15.484375 L 12.609375 -15.484375 L 12.53125 -14.375 C 12.445312 -12.957031 11.941406 -10.863281 11.015625 -8.09375 Z M 8.34375 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-39">
+<path style="stroke:none;" d="M 12.609375 -8.21875 L 10.125 -8.21875 L 6.984375 -17.765625 L 3.765625 -8.21875 L 1.375 -8.21875 L 5.765625 -20.859375 L 8.171875 -20.859375 Z M 12.609375 -8.21875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-40">
+<path style="stroke:none;" d="M 14 -13.703125 L 14 -7.125 L 10.296875 -7.125 L 10.296875 4.953125 L 3.703125 4.953125 L 3.703125 -13.703125 Z M 14 -13.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-41">
+<path style="stroke:none;" d="M 14.265625 -13.703125 L 14.265625 -7.125 L -0.265625 -7.125 L -0.265625 -13.703125 Z M 14.265625 -13.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-42">
+<path style="stroke:none;" d="M 11.453125 0 L 2.53125 0 L 2.53125 -1.984375 L 5.828125 -1.984375 L 5.828125 -18.875 L 3.234375 -18.875 L 3.234375 -20.859375 L 10.75 -20.859375 L 10.75 -18.875 L 8.15625 -18.875 L 8.15625 -1.984375 L 11.453125 -1.984375 Z M 11.453125 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-43">
+<path style="stroke:none;" d="M 12.65625 0 L 10.765625 0 L 10.765625 -11.6875 C 10.765625 -13.007812 10.375 -13.671875 9.59375 -13.671875 C 8.914062 -13.671875 8.363281 -13.160156 7.9375 -12.140625 L 7.9375 0 L 6.0625 0 L 6.0625 -11.6875 C 6.039062 -13.007812 5.726562 -13.671875 5.125 -13.671875 C 4.351562 -13.671875 3.726562 -13.160156 3.25 -12.140625 L 3.25 0 L 1.34375 0 L 1.34375 -15.484375 L 3.25 -15.484375 L 3.25 -13.953125 C 3.945312 -15.160156 4.804688 -15.765625 5.828125 -15.765625 C 6.742188 -15.765625 7.375 -15.160156 7.71875 -13.953125 C 8.375 -15.160156 9.195312 -15.765625 10.1875 -15.765625 C 11.832031 -15.765625 12.65625 -14.441406 12.65625 -11.796875 Z M 12.65625 0 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-44">
+<path style="stroke:none;" d="M 10.296875 -13.703125 L 10.296875 4.953125 L 3.703125 4.953125 L 3.703125 -7.125 L 0 -7.125 L 0 -13.703125 Z M 10.296875 -13.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-45">
+<path style="stroke:none;" d="M 10.296875 4.953125 L 3.703125 4.953125 L 3.703125 -25.765625 L 10.296875 -25.765625 Z M 10.296875 4.953125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-46">
+<path style="stroke:none;" d="M 1.59375 -13.4375 L 1.59375 -15.9375 L 12.9375 -9.765625 L 12.9375 -6.828125 L 1.59375 -0.640625 L 1.59375 -3.140625 L 11.234375 -8.296875 Z M 1.59375 -13.4375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-47">
+<path style="stroke:none;" d="M 12.171875 -6.515625 C 12.171875 -4.359375 11.648438 -2.6875 10.609375 -1.5 C 9.566406 -0.320312 8.300781 0.265625 6.8125 0.265625 C 4.550781 0.265625 2.847656 -0.804688 1.703125 -2.953125 L 3.609375 -4.21875 C 4.253906 -2.632812 5.316406 -1.84375 6.796875 -1.84375 C 7.597656 -1.84375 8.300781 -2.203125 8.90625 -2.921875 C 9.519531 -3.640625 9.828125 -4.835938 9.828125 -6.515625 C 9.828125 -8.203125 9.523438 -9.382812 8.921875 -10.0625 C 8.328125 -10.738281 7.351562 -11.078125 6 -11.078125 L 2.90625 -11.078125 L 2.90625 -20.859375 L 11.734375 -20.859375 L 11.734375 -18.875 L 5.234375 -18.875 L 5.234375 -13.1875 L 6.40625 -13.1875 C 8.132812 -13.1875 9.523438 -12.664062 10.578125 -11.625 C 11.640625 -10.59375 12.171875 -8.890625 12.171875 -6.515625 Z M 12.171875 -6.515625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-48">
+<path style="stroke:none;" d="M 9.6875 -2.421875 C 9.6875 -1.710938 9.429688 -1.085938 8.921875 -0.546875 C 8.410156 -0.00390625 7.765625 0.265625 6.984375 0.265625 C 6.203125 0.265625 5.5625 -0.00390625 5.0625 -0.546875 C 4.570312 -1.085938 4.328125 -1.710938 4.328125 -2.421875 C 4.328125 -3.117188 4.570312 -3.738281 5.0625 -4.28125 C 5.5625 -4.832031 6.203125 -5.109375 6.984375 -5.109375 C 7.765625 -5.109375 8.410156 -4.832031 8.921875 -4.28125 C 9.429688 -3.726562 9.6875 -3.109375 9.6875 -2.421875 Z M 9.6875 -13.078125 C 9.6875 -12.359375 9.429688 -11.726562 8.921875 -11.1875 C 8.410156 -10.65625 7.765625 -10.390625 6.984375 -10.390625 C 6.203125 -10.390625 5.5625 -10.65625 5.0625 -11.1875 C 4.570312 -11.726562 4.328125 -12.359375 4.328125 -13.078125 C 4.328125 -13.785156 4.570312 -14.410156 5.0625 -14.953125 C 5.5625 -15.492188 6.203125 -15.765625 6.984375 -15.765625 C 7.765625 -15.765625 8.410156 -15.488281 8.921875 -14.9375 C 9.429688 -14.394531 9.6875 -13.773438 9.6875 -13.078125 Z M 9.6875 -13.078125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-49">
+<path style="stroke:none;" d="M 3.5625 -7.390625 C 3.90625 -7.390625 4.191406 -7.1875 4.421875 -6.78125 C 4.984375 -5.882812 5.367188 -5.4375 5.578125 -5.4375 C 5.679688 -5.4375 5.75 -5.503906 5.78125 -5.640625 C 6.664062 -8.816406 7.515625 -11.3125 8.328125 -13.125 C 9.148438 -14.945312 9.847656 -16.269531 10.421875 -17.09375 C 11.078125 -18 11.707031 -18.453125 12.3125 -18.453125 C 12.46875 -18.453125 12.597656 -18.410156 12.703125 -18.328125 C 12.816406 -18.253906 12.875 -18.140625 12.875 -17.984375 C 12.875 -17.796875 12.753906 -17.507812 12.515625 -17.125 C 10.628906 -13.84375 8.894531 -9.082031 7.3125 -2.84375 C 7.1875 -2.425781 6.875 -2.117188 6.375 -1.921875 C 5.875 -1.722656 5.484375 -1.625 5.203125 -1.625 C 4.640625 -1.625 3.957031 -2.203125 3.15625 -3.359375 C 2.351562 -4.515625 1.953125 -5.25 1.953125 -5.5625 C 1.953125 -5.957031 2.148438 -6.359375 2.546875 -6.765625 C 2.953125 -7.179688 3.289062 -7.390625 3.5625 -7.390625 Z M 3.5625 -7.390625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-50">
+<path style="stroke:none;" d="M 12.5 -20.859375 L 3.75 1.75 L 1.484375 1.75 L 10.25 -20.859375 Z M 12.5 -20.859375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-51">
+<path style="stroke:none;" d="M 4.90625 -3.234375 C 4.175781 -2.210938 3.773438 -1.132812 3.703125 0 L 1.375 0 L 1.40625 -0.53125 C 1.46875 -1.550781 2.050781 -2.835938 3.15625 -4.390625 L 5.703125 -7.984375 L 3.515625 -11.09375 C 2.410156 -12.632812 1.828125 -13.921875 1.765625 -14.953125 L 1.75 -15.484375 L 4.078125 -15.484375 C 4.140625 -14.359375 4.535156 -13.28125 5.265625 -12.25 L 7 -9.8125 L 8.734375 -12.25 C 9.460938 -13.28125 9.859375 -14.359375 9.921875 -15.484375 L 12.25 -15.484375 L 12.234375 -14.953125 C 12.171875 -13.921875 11.585938 -12.632812 10.484375 -11.09375 L 8.28125 -7.984375 L 10.84375 -4.390625 C 11.945312 -2.835938 12.53125 -1.550781 12.59375 -0.53125 L 12.625 0 L 10.296875 0 C 10.222656 -1.132812 9.820312 -2.210938 9.09375 -3.234375 L 7 -6.171875 Z M 4.90625 -3.234375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-52">
+<path style="stroke:none;" d="M 11.0625 -17.859375 C 10.695312 -18.640625 10.019531 -19.03125 9.03125 -19.03125 C 8.382812 -19.03125 7.878906 -18.820312 7.515625 -18.40625 C 7.160156 -17.988281 6.984375 -17.242188 6.984375 -16.171875 L 6.984375 -14.609375 L 12.203125 -14.609375 L 12.203125 -12.640625 L 6.984375 -12.640625 L 6.984375 0 L 4.65625 0 L 4.65625 -12.640625 L 2.046875 -12.640625 L 2.046875 -14.609375 L 4.65625 -14.609375 L 4.65625 -16.03125 C 4.65625 -17.789062 5.0625 -19.082031 5.875 -19.90625 C 6.695312 -20.738281 7.703125 -21.15625 8.890625 -21.15625 C 10.710938 -21.15625 12.019531 -20.523438 12.8125 -19.265625 Z M 11.0625 -17.859375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-53">
+<path style="stroke:none;" d="M 3.703125 -7.140625 L 3.703125 -25.765625 L 10.296875 -25.765625 L 10.296875 -13.703125 L 14 -13.703125 L 14 -7.125 Z M 3.703125 -7.140625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-54">
+<path style="stroke:none;" d="M 0 -7.125 L 0 -13.703125 L 3.703125 -13.703125 L 3.703125 -25.765625 L 10.296875 -25.765625 L 10.296875 -7.125 Z M 0 -7.125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-55">
+<path style="stroke:none;" d="M -0.265625 -9.421875 L -0.265625 -11.390625 L 14.265625 -11.390625 L 14.265625 -9.421875 Z M -0.265625 -9.421875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-56">
+<path style="stroke:none;" d="M 0 -7.125 L 0 -9.109375 L 14 -9.109375 L 14 -7.125 Z M 0 -11.71875 L 0 -13.703125 L 14 -13.703125 L 14 -11.71875 Z M 0 -11.71875 "/>
+</symbol>
+</g>
+</defs>
+<g id="surface89756">
+<rect x="0" y="0" width="1428" height="682" style="fill:rgb(16.078431%,17.647059%,24.313725%);fill-opacity:1;stroke:none;"/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 434 124 L 448 124 L 448 155 L 434 155 Z M 434 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 0 0 L 854 0 L 854 31 L 0 31 Z M 0 0 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="0" y="26"/>
+ <use xlink:href="#glyph0-2" x="14" y="26"/>
+ <use xlink:href="#glyph0-3" x="28" y="26"/>
+ <use xlink:href="#glyph0-4" x="42" y="26"/>
+ <use xlink:href="#glyph0-5" x="56" y="26"/>
+ <use xlink:href="#glyph0-6" x="70" y="26"/>
+ <use xlink:href="#glyph0-7" x="84" y="26"/>
+ <use xlink:href="#glyph0-1" x="98" y="26"/>
+ <use xlink:href="#glyph0-2" x="112" y="26"/>
+ <use xlink:href="#glyph0-8" x="126" y="26"/>
+ <use xlink:href="#glyph0-9" x="140" y="26"/>
+ <use xlink:href="#glyph0-4" x="154" y="26"/>
+ <use xlink:href="#glyph0-10" x="168" y="26"/>
+ <use xlink:href="#glyph0-7" x="182" y="26"/>
+ <use xlink:href="#glyph0-1" x="196" y="26"/>
+ <use xlink:href="#glyph0-2" x="210" y="26"/>
+ <use xlink:href="#glyph0-11" x="224" y="26"/>
+ <use xlink:href="#glyph0-4" x="238" y="26"/>
+ <use xlink:href="#glyph0-6" x="252" y="26"/>
+ <use xlink:href="#glyph0-12" x="266" y="26"/>
+ <use xlink:href="#glyph0-7" x="280" y="26"/>
+ <use xlink:href="#glyph0-1" x="294" y="26"/>
+ <use xlink:href="#glyph0-2" x="308" y="26"/>
+ <use xlink:href="#glyph0-13" x="322" y="26"/>
+ <use xlink:href="#glyph0-4" x="336" y="26"/>
+ <use xlink:href="#glyph0-14" x="350" y="26"/>
+ <use xlink:href="#glyph0-9" x="364" y="26"/>
+ <use xlink:href="#glyph0-15" x="378" y="26"/>
+ <use xlink:href="#glyph0-12" x="392" y="26"/>
+ <use xlink:href="#glyph0-16" x="406" y="26"/>
+ <use xlink:href="#glyph0-7" x="420" y="26"/>
+ <use xlink:href="#glyph0-1" x="434" y="26"/>
+ <use xlink:href="#glyph0-2" x="448" y="26"/>
+ <use xlink:href="#glyph0-17" x="462" y="26"/>
+ <use xlink:href="#glyph0-6" x="476" y="26"/>
+ <use xlink:href="#glyph0-5" x="490" y="26"/>
+ <use xlink:href="#glyph0-18" x="504" y="26"/>
+ <use xlink:href="#glyph0-7" x="518" y="26"/>
+ <use xlink:href="#glyph0-1" x="532" y="26"/>
+ <use xlink:href="#glyph0-1" x="546" y="26"/>
+ <use xlink:href="#glyph0-1" x="560" y="26"/>
+ <use xlink:href="#glyph0-1" x="574" y="26"/>
+ <use xlink:href="#glyph0-1" x="588" y="26"/>
+ <use xlink:href="#glyph0-1" x="602" y="26"/>
+ <use xlink:href="#glyph0-1" x="616" y="26"/>
+ <use xlink:href="#glyph0-1" x="630" y="26"/>
+ <use xlink:href="#glyph0-1" x="644" y="26"/>
+ <use xlink:href="#glyph0-1" x="658" y="26"/>
+ <use xlink:href="#glyph0-1" x="672" y="26"/>
+ <use xlink:href="#glyph0-1" x="686" y="26"/>
+ <use xlink:href="#glyph0-1" x="700" y="26"/>
+ <use xlink:href="#glyph0-1" x="714" y="26"/>
+ <use xlink:href="#glyph0-1" x="728" y="26"/>
+ <use xlink:href="#glyph0-1" x="742" y="26"/>
+ <use xlink:href="#glyph0-1" x="756" y="26"/>
+ <use xlink:href="#glyph0-1" x="770" y="26"/>
+ <use xlink:href="#glyph0-1" x="784" y="26"/>
+ <use xlink:href="#glyph0-1" x="798" y="26"/>
+ <use xlink:href="#glyph0-1" x="812" y="26"/>
+ <use xlink:href="#glyph0-1" x="826" y="26"/>
+ <use xlink:href="#glyph0-1" x="840" y="26"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 854 0 L 1092 0 L 1092 31 L 854 31 Z M 854 0 "/>
+<g style="fill:rgb(100%,72.156863%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="854" y="26"/>
+ <use xlink:href="#glyph0-15" x="868" y="26"/>
+ <use xlink:href="#glyph0-14" x="882" y="26"/>
+ <use xlink:href="#glyph0-16" x="896" y="26"/>
+ <use xlink:href="#glyph0-15" x="910" y="26"/>
+ <use xlink:href="#glyph0-5" x="924" y="26"/>
+ <use xlink:href="#glyph0-6" x="938" y="26"/>
+ <use xlink:href="#glyph0-1" x="952" y="26"/>
+ <use xlink:href="#glyph0-20" x="966" y="26"/>
+ <use xlink:href="#glyph0-6" x="980" y="26"/>
+ <use xlink:href="#glyph0-16" x="994" y="26"/>
+ <use xlink:href="#glyph0-10" x="1008" y="26"/>
+ <use xlink:href="#glyph0-1" x="1022" y="26"/>
+ <use xlink:href="#glyph0-21" x="1036" y="26"/>
+ <use xlink:href="#glyph0-15" x="1050" y="26"/>
+ <use xlink:href="#glyph0-9" x="1064" y="26"/>
+ <use xlink:href="#glyph0-6" x="1078" y="26"/>
+</g>
+<g style="fill:rgb(100%,72.156863%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="855" y="26"/>
+ <use xlink:href="#glyph0-15" x="869" y="26"/>
+ <use xlink:href="#glyph0-14" x="883" y="26"/>
+ <use xlink:href="#glyph0-16" x="897" y="26"/>
+ <use xlink:href="#glyph0-15" x="911" y="26"/>
+ <use xlink:href="#glyph0-5" x="925" y="26"/>
+ <use xlink:href="#glyph0-6" x="939" y="26"/>
+ <use xlink:href="#glyph0-1" x="953" y="26"/>
+ <use xlink:href="#glyph0-20" x="967" y="26"/>
+ <use xlink:href="#glyph0-6" x="981" y="26"/>
+ <use xlink:href="#glyph0-16" x="995" y="26"/>
+ <use xlink:href="#glyph0-10" x="1009" y="26"/>
+ <use xlink:href="#glyph0-1" x="1023" y="26"/>
+ <use xlink:href="#glyph0-21" x="1037" y="26"/>
+ <use xlink:href="#glyph0-15" x="1051" y="26"/>
+ <use xlink:href="#glyph0-9" x="1065" y="26"/>
+ <use xlink:href="#glyph0-6" x="1079" y="26"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1092 0 L 1120 0 L 1120 31 L 1092 31 Z M 1092 0 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1120 0 L 1134 0 L 1134 31 L 1120 31 Z M 1120 0 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1134 0 L 1302 0 L 1302 31 L 1134 31 Z M 1134 0 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-22" x="1134" y="26"/>
+ <use xlink:href="#glyph0-6" x="1148" y="26"/>
+ <use xlink:href="#glyph0-23" x="1162" y="26"/>
+ <use xlink:href="#glyph0-24" x="1176" y="26"/>
+ <use xlink:href="#glyph0-25" x="1190" y="26"/>
+ <use xlink:href="#glyph0-26" x="1204" y="26"/>
+ <use xlink:href="#glyph0-1" x="1218" y="26"/>
+ <use xlink:href="#glyph0-21" x="1232" y="26"/>
+ <use xlink:href="#glyph0-6" x="1246" y="26"/>
+ <use xlink:href="#glyph0-14" x="1260" y="26"/>
+ <use xlink:href="#glyph0-27" x="1274" y="26"/>
+ <use xlink:href="#glyph0-1" x="1288" y="26"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1302 0 L 1386 0 L 1386 31 L 1302 31 Z M 1302 0 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="1302" y="26"/>
+ <use xlink:href="#glyph0-10" x="1316" y="26"/>
+ <use xlink:href="#glyph0-24" x="1330" y="26"/>
+ <use xlink:href="#glyph0-5" x="1344" y="26"/>
+ <use xlink:href="#glyph0-28" x="1358" y="26"/>
+ <use xlink:href="#glyph0-18" x="1372" y="26"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="1303" y="26"/>
+ <use xlink:href="#glyph0-10" x="1317" y="26"/>
+ <use xlink:href="#glyph0-24" x="1331" y="26"/>
+ <use xlink:href="#glyph0-5" x="1345" y="26"/>
+ <use xlink:href="#glyph0-28" x="1359" y="26"/>
+ <use xlink:href="#glyph0-18" x="1373" y="26"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1386 0 L 1400 0 L 1400 31 L 1386 31 Z M 1386 0 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1400 0 L 1414 0 L 1414 31 L 1400 31 Z M 1400 0 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 0 L 1428 0 L 1428 31 L 1414 31 Z M 1414 0 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 0 31 L 14 31 L 14 62 L 0 62 Z M 0 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 14 31 L 112 31 L 112 62 L 14 62 Z M 14 31 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="14" y="57"/>
+ <use xlink:href="#glyph0-19" x="28" y="57"/>
+ <use xlink:href="#glyph0-5" x="42" y="57"/>
+ <use xlink:href="#glyph0-15" x="56" y="57"/>
+ <use xlink:href="#glyph0-25" x="70" y="57"/>
+ <use xlink:href="#glyph0-29" x="84" y="57"/>
+ <use xlink:href="#glyph0-1" x="98" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 112 31 L 126 31 L 126 62 L 112 62 Z M 112 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 126 31 L 364 31 L 364 62 L 126 62 Z M 126 31 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="126" y="57"/>
+ <use xlink:href="#glyph0-30" x="140" y="57"/>
+ <use xlink:href="#glyph0-12" x="154" y="57"/>
+ <use xlink:href="#glyph0-19" x="168" y="57"/>
+ <use xlink:href="#glyph0-15" x="182" y="57"/>
+ <use xlink:href="#glyph0-14" x="196" y="57"/>
+ <use xlink:href="#glyph0-16" x="210" y="57"/>
+ <use xlink:href="#glyph0-15" x="224" y="57"/>
+ <use xlink:href="#glyph0-5" x="238" y="57"/>
+ <use xlink:href="#glyph0-6" x="252" y="57"/>
+ <use xlink:href="#glyph0-1" x="266" y="57"/>
+ <use xlink:href="#glyph0-31" x="280" y="57"/>
+ <use xlink:href="#glyph0-6" x="294" y="57"/>
+ <use xlink:href="#glyph0-32" x="308" y="57"/>
+ <use xlink:href="#glyph0-27" x="322" y="57"/>
+ <use xlink:href="#glyph0-33" x="336" y="57"/>
+ <use xlink:href="#glyph0-1" x="350" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 364 31 L 378 31 L 378 62 L 364 62 Z M 364 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 378 31 L 560 31 L 560 62 L 378 62 Z M 378 31 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="378" y="57"/>
+ <use xlink:href="#glyph0-30" x="392" y="57"/>
+ <use xlink:href="#glyph0-34" x="406" y="57"/>
+ <use xlink:href="#glyph0-10" x="420" y="57"/>
+ <use xlink:href="#glyph0-26" x="434" y="57"/>
+ <use xlink:href="#glyph0-15" x="448" y="57"/>
+ <use xlink:href="#glyph0-14" x="462" y="57"/>
+ <use xlink:href="#glyph0-1" x="476" y="57"/>
+ <use xlink:href="#glyph0-35" x="490" y="57"/>
+ <use xlink:href="#glyph0-6" x="504" y="57"/>
+ <use xlink:href="#glyph0-18" x="518" y="57"/>
+ <use xlink:href="#glyph0-5" x="532" y="57"/>
+ <use xlink:href="#glyph0-1" x="546" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 560 31 L 574 31 L 574 62 L 560 62 Z M 560 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 574 31 L 714 31 L 714 62 L 574 62 Z M 574 31 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="574" y="57"/>
+ <use xlink:href="#glyph0-36" x="588" y="57"/>
+ <use xlink:href="#glyph0-5" x="602" y="57"/>
+ <use xlink:href="#glyph0-5" x="616" y="57"/>
+ <use xlink:href="#glyph0-1" x="630" y="57"/>
+ <use xlink:href="#glyph0-37" x="644" y="57"/>
+ <use xlink:href="#glyph0-15" x="658" y="57"/>
+ <use xlink:href="#glyph0-33" x="672" y="57"/>
+ <use xlink:href="#glyph0-16" x="686" y="57"/>
+ <use xlink:href="#glyph0-1" x="700" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 714 31 L 728 31 L 728 62 L 714 62 Z M 714 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 728 31 L 980 31 L 980 62 L 728 62 Z M 728 31 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="728" y="57"/>
+ <use xlink:href="#glyph0-3" x="742" y="57"/>
+ <use xlink:href="#glyph0-23" x="756" y="57"/>
+ <use xlink:href="#glyph0-29" x="770" y="57"/>
+ <use xlink:href="#glyph0-6" x="784" y="57"/>
+ <use xlink:href="#glyph0-1" x="798" y="57"/>
+ <use xlink:href="#glyph0-31" x="812" y="57"/>
+ <use xlink:href="#glyph0-6" x="826" y="57"/>
+ <use xlink:href="#glyph0-38" x="840" y="57"/>
+ <use xlink:href="#glyph0-4" x="854" y="57"/>
+ <use xlink:href="#glyph0-25" x="868" y="57"/>
+ <use xlink:href="#glyph0-6" x="882" y="57"/>
+ <use xlink:href="#glyph0-1" x="896" y="57"/>
+ <use xlink:href="#glyph0-37" x="910" y="57"/>
+ <use xlink:href="#glyph0-15" x="924" y="57"/>
+ <use xlink:href="#glyph0-33" x="938" y="57"/>
+ <use xlink:href="#glyph0-16" x="952" y="57"/>
+ <use xlink:href="#glyph0-1" x="966" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 980 31 L 994 31 L 994 62 L 980 62 Z M 980 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 994 31 L 1162 31 L 1162 62 L 994 62 Z M 994 31 "/>
+<g style="fill:rgb(74.901961%,75.294118%,76.862745%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="994" y="57"/>
+ <use xlink:href="#glyph0-19" x="1008" y="57"/>
+ <use xlink:href="#glyph0-23" x="1022" y="57"/>
+ <use xlink:href="#glyph0-5" x="1036" y="57"/>
+ <use xlink:href="#glyph0-25" x="1050" y="57"/>
+ <use xlink:href="#glyph0-27" x="1064" y="57"/>
+ <use xlink:href="#glyph0-5" x="1078" y="57"/>
+ <use xlink:href="#glyph0-23" x="1092" y="57"/>
+ <use xlink:href="#glyph0-10" x="1106" y="57"/>
+ <use xlink:href="#glyph0-15" x="1120" y="57"/>
+ <use xlink:href="#glyph0-24" x="1134" y="57"/>
+ <use xlink:href="#glyph0-1" x="1148" y="57"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 1162 31 L 1414 31 L 1414 62 L 1162 62 Z M 1162 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 31 L 1428 31 L 1428 62 L 1414 62 Z M 1414 31 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 62 L 1400 62 L 1400 93 L 0 93 Z M 0 62 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 1400 62 L 1414 62 L 1414 93 L 1400 93 Z M 1400 62 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-39" x="1400" y="88"/>
+</g>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-39" x="1401" y="88"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 62 L 1428 62 L 1428 93 L 1414 93 Z M 1414 62 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 93 L 140 93 L 140 124 L 0 124 Z M 0 93 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 93 L 1260 93 L 1260 124 L 140 124 Z M 140 93 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-40" x="140" y="119"/>
+ <use xlink:href="#glyph0-41" x="154" y="119"/>
+ <use xlink:href="#glyph0-41" x="168" y="119"/>
+ <use xlink:href="#glyph0-1" x="182" y="119"/>
+ <use xlink:href="#glyph0-21" x="196" y="119"/>
+ <use xlink:href="#glyph0-6" x="210" y="119"/>
+ <use xlink:href="#glyph0-14" x="224" y="119"/>
+ <use xlink:href="#glyph0-27" x="238" y="119"/>
+ <use xlink:href="#glyph0-1" x="252" y="119"/>
+ <use xlink:href="#glyph0-42" x="266" y="119"/>
+ <use xlink:href="#glyph0-10" x="280" y="119"/>
+ <use xlink:href="#glyph0-6" x="294" y="119"/>
+ <use xlink:href="#glyph0-43" x="308" y="119"/>
+ <use xlink:href="#glyph0-16" x="322" y="119"/>
+ <use xlink:href="#glyph0-1" x="336" y="119"/>
+ <use xlink:href="#glyph0-41" x="350" y="119"/>
+ <use xlink:href="#glyph0-41" x="364" y="119"/>
+ <use xlink:href="#glyph0-41" x="378" y="119"/>
+ <use xlink:href="#glyph0-41" x="392" y="119"/>
+ <use xlink:href="#glyph0-41" x="406" y="119"/>
+ <use xlink:href="#glyph0-41" x="420" y="119"/>
+ <use xlink:href="#glyph0-41" x="434" y="119"/>
+ <use xlink:href="#glyph0-41" x="448" y="119"/>
+ <use xlink:href="#glyph0-41" x="462" y="119"/>
+ <use xlink:href="#glyph0-41" x="476" y="119"/>
+ <use xlink:href="#glyph0-41" x="490" y="119"/>
+ <use xlink:href="#glyph0-41" x="504" y="119"/>
+ <use xlink:href="#glyph0-41" x="518" y="119"/>
+ <use xlink:href="#glyph0-41" x="532" y="119"/>
+ <use xlink:href="#glyph0-41" x="546" y="119"/>
+ <use xlink:href="#glyph0-41" x="560" y="119"/>
+ <use xlink:href="#glyph0-41" x="574" y="119"/>
+ <use xlink:href="#glyph0-41" x="588" y="119"/>
+ <use xlink:href="#glyph0-41" x="602" y="119"/>
+ <use xlink:href="#glyph0-41" x="616" y="119"/>
+ <use xlink:href="#glyph0-41" x="630" y="119"/>
+ <use xlink:href="#glyph0-41" x="644" y="119"/>
+ <use xlink:href="#glyph0-41" x="658" y="119"/>
+ <use xlink:href="#glyph0-41" x="672" y="119"/>
+ <use xlink:href="#glyph0-41" x="686" y="119"/>
+ <use xlink:href="#glyph0-41" x="700" y="119"/>
+ <use xlink:href="#glyph0-41" x="714" y="119"/>
+ <use xlink:href="#glyph0-41" x="728" y="119"/>
+ <use xlink:href="#glyph0-41" x="742" y="119"/>
+ <use xlink:href="#glyph0-41" x="756" y="119"/>
+ <use xlink:href="#glyph0-41" x="770" y="119"/>
+ <use xlink:href="#glyph0-41" x="784" y="119"/>
+ <use xlink:href="#glyph0-41" x="798" y="119"/>
+ <use xlink:href="#glyph0-41" x="812" y="119"/>
+ <use xlink:href="#glyph0-41" x="826" y="119"/>
+ <use xlink:href="#glyph0-41" x="840" y="119"/>
+ <use xlink:href="#glyph0-41" x="854" y="119"/>
+ <use xlink:href="#glyph0-41" x="868" y="119"/>
+ <use xlink:href="#glyph0-41" x="882" y="119"/>
+ <use xlink:href="#glyph0-41" x="896" y="119"/>
+ <use xlink:href="#glyph0-41" x="910" y="119"/>
+ <use xlink:href="#glyph0-41" x="924" y="119"/>
+ <use xlink:href="#glyph0-41" x="938" y="119"/>
+ <use xlink:href="#glyph0-41" x="952" y="119"/>
+ <use xlink:href="#glyph0-41" x="966" y="119"/>
+ <use xlink:href="#glyph0-41" x="980" y="119"/>
+ <use xlink:href="#glyph0-41" x="994" y="119"/>
+ <use xlink:href="#glyph0-41" x="1008" y="119"/>
+ <use xlink:href="#glyph0-41" x="1022" y="119"/>
+ <use xlink:href="#glyph0-41" x="1036" y="119"/>
+ <use xlink:href="#glyph0-41" x="1050" y="119"/>
+ <use xlink:href="#glyph0-41" x="1064" y="119"/>
+ <use xlink:href="#glyph0-41" x="1078" y="119"/>
+ <use xlink:href="#glyph0-41" x="1092" y="119"/>
+ <use xlink:href="#glyph0-41" x="1106" y="119"/>
+ <use xlink:href="#glyph0-41" x="1120" y="119"/>
+ <use xlink:href="#glyph0-41" x="1134" y="119"/>
+ <use xlink:href="#glyph0-41" x="1148" y="119"/>
+ <use xlink:href="#glyph0-41" x="1162" y="119"/>
+ <use xlink:href="#glyph0-41" x="1176" y="119"/>
+ <use xlink:href="#glyph0-41" x="1190" y="119"/>
+ <use xlink:href="#glyph0-41" x="1204" y="119"/>
+ <use xlink:href="#glyph0-41" x="1218" y="119"/>
+ <use xlink:href="#glyph0-41" x="1232" y="119"/>
+ <use xlink:href="#glyph0-44" x="1246" y="119"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 93 L 1400 93 L 1400 124 L 1260 124 Z M 1260 93 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 93 L 1414 93 L 1414 124 L 1400 124 Z M 1400 93 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 93 L 1428 93 L 1428 124 L 1414 124 Z M 1414 93 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 124 L 140 124 L 140 155 L 0 155 Z M 0 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 124 L 196 124 L 196 155 L 140 155 Z M 140 124 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="150"/>
+ <use xlink:href="#glyph0-1" x="154" y="150"/>
+ <use xlink:href="#glyph0-46" x="168" y="150"/>
+ <use xlink:href="#glyph0-1" x="182" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 196 124 L 854 124 L 854 155 L 196 155 Z M 196 124 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-9" x="196" y="150"/>
+ <use xlink:href="#glyph0-6" x="210" y="150"/>
+ <use xlink:href="#glyph0-38" x="224" y="150"/>
+ <use xlink:href="#glyph0-4" x="238" y="150"/>
+ <use xlink:href="#glyph0-25" x="252" y="150"/>
+ <use xlink:href="#glyph0-6" x="266" y="150"/>
+ <use xlink:href="#glyph0-1" x="280" y="150"/>
+ <use xlink:href="#glyph0-5" x="294" y="150"/>
+ <use xlink:href="#glyph0-15" x="308" y="150"/>
+ <use xlink:href="#glyph0-33" x="322" y="150"/>
+ <use xlink:href="#glyph0-1" x="336" y="150"/>
+ <use xlink:href="#glyph0-12" x="350" y="150"/>
+ <use xlink:href="#glyph0-4" x="364" y="150"/>
+ <use xlink:href="#glyph0-14" x="378" y="150"/>
+ <use xlink:href="#glyph0-9" x="392" y="150"/>
+ <use xlink:href="#glyph0-15" x="406" y="150"/>
+ <use xlink:href="#glyph0-12" x="420" y="150"/>
+ <use xlink:href="#glyph0-1" x="434" y="150"/>
+ <use xlink:href="#glyph0-1" x="448" y="150"/>
+ <use xlink:href="#glyph0-1" x="462" y="150"/>
+ <use xlink:href="#glyph0-1" x="476" y="150"/>
+ <use xlink:href="#glyph0-1" x="490" y="150"/>
+ <use xlink:href="#glyph0-1" x="504" y="150"/>
+ <use xlink:href="#glyph0-1" x="518" y="150"/>
+ <use xlink:href="#glyph0-1" x="532" y="150"/>
+ <use xlink:href="#glyph0-1" x="546" y="150"/>
+ <use xlink:href="#glyph0-1" x="560" y="150"/>
+ <use xlink:href="#glyph0-1" x="574" y="150"/>
+ <use xlink:href="#glyph0-1" x="588" y="150"/>
+ <use xlink:href="#glyph0-1" x="602" y="150"/>
+ <use xlink:href="#glyph0-1" x="616" y="150"/>
+ <use xlink:href="#glyph0-1" x="630" y="150"/>
+ <use xlink:href="#glyph0-1" x="644" y="150"/>
+ <use xlink:href="#glyph0-1" x="658" y="150"/>
+ <use xlink:href="#glyph0-1" x="672" y="150"/>
+ <use xlink:href="#glyph0-1" x="686" y="150"/>
+ <use xlink:href="#glyph0-1" x="700" y="150"/>
+ <use xlink:href="#glyph0-1" x="714" y="150"/>
+ <use xlink:href="#glyph0-1" x="728" y="150"/>
+ <use xlink:href="#glyph0-1" x="742" y="150"/>
+ <use xlink:href="#glyph0-1" x="756" y="150"/>
+ <use xlink:href="#glyph0-1" x="770" y="150"/>
+ <use xlink:href="#glyph0-1" x="784" y="150"/>
+ <use xlink:href="#glyph0-1" x="798" y="150"/>
+ <use xlink:href="#glyph0-1" x="812" y="150"/>
+ <use xlink:href="#glyph0-1" x="826" y="150"/>
+ <use xlink:href="#glyph0-1" x="840" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 854 124 L 868 124 L 868 155 L 854 155 Z M 854 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 868 124 L 966 124 L 966 155 L 868 155 Z M 868 124 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="868" y="150"/>
+ <use xlink:href="#glyph0-23" x="882" y="150"/>
+ <use xlink:href="#glyph0-14" x="896" y="150"/>
+ <use xlink:href="#glyph0-25" x="910" y="150"/>
+ <use xlink:href="#glyph0-6" x="924" y="150"/>
+ <use xlink:href="#glyph0-5" x="938" y="150"/>
+ <use xlink:href="#glyph0-1" x="952" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 966 124 L 1050 124 L 1050 155 L 966 155 Z M 966 124 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="966" y="150"/>
+ <use xlink:href="#glyph0-10" x="980" y="150"/>
+ <use xlink:href="#glyph0-24" x="994" y="150"/>
+ <use xlink:href="#glyph0-5" x="1008" y="150"/>
+ <use xlink:href="#glyph0-28" x="1022" y="150"/>
+ <use xlink:href="#glyph0-25" x="1036" y="150"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="967" y="150"/>
+ <use xlink:href="#glyph0-10" x="981" y="150"/>
+ <use xlink:href="#glyph0-24" x="995" y="150"/>
+ <use xlink:href="#glyph0-5" x="1009" y="150"/>
+ <use xlink:href="#glyph0-28" x="1023" y="150"/>
+ <use xlink:href="#glyph0-25" x="1037" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1050 124 L 1064 124 L 1064 155 L 1050 155 Z M 1050 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1064 124 L 1078 124 L 1078 155 L 1064 155 Z M 1064 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1078 124 L 1092 124 L 1092 155 L 1078 155 Z M 1078 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1092 124 L 1148 124 L 1148 155 L 1092 155 Z M 1092 124 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-35" x="1092" y="150"/>
+ <use xlink:href="#glyph0-27" x="1106" y="150"/>
+ <use xlink:href="#glyph0-14" x="1120" y="150"/>
+ <use xlink:href="#glyph0-1" x="1134" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1148 124 L 1218 124 L 1218 155 L 1148 155 Z M 1148 124 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-8" x="1148" y="150"/>
+ <use xlink:href="#glyph0-14" x="1162" y="150"/>
+ <use xlink:href="#glyph0-10" x="1176" y="150"/>
+ <use xlink:href="#glyph0-6" x="1190" y="150"/>
+ <use xlink:href="#glyph0-24" x="1204" y="150"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-8" x="1149" y="150"/>
+ <use xlink:href="#glyph0-14" x="1163" y="150"/>
+ <use xlink:href="#glyph0-10" x="1177" y="150"/>
+ <use xlink:href="#glyph0-6" x="1191" y="150"/>
+ <use xlink:href="#glyph0-24" x="1205" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1218 124 L 1232 124 L 1232 155 L 1218 155 Z M 1218 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 124 L 1260 124 L 1260 155 L 1232 155 Z M 1232 124 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="150"/>
+ <use xlink:href="#glyph0-45" x="1246" y="150"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 124 L 1400 124 L 1400 155 L 1260 155 Z M 1260 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 124 L 1414 124 L 1414 155 L 1400 155 Z M 1400 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 124 L 1428 124 L 1428 155 L 1414 155 Z M 1414 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 155 L 140 155 L 140 186 L 0 186 Z M 0 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 155 L 168 155 L 168 186 L 140 186 Z M 140 155 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="181"/>
+ <use xlink:href="#glyph0-1" x="154" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 168 155 L 182 155 L 182 186 L 168 186 Z M 168 155 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 182 155 L 266 155 L 266 186 L 182 186 Z M 182 155 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="181"/>
+ <use xlink:href="#glyph0-4" x="196" y="181"/>
+ <use xlink:href="#glyph0-14" x="210" y="181"/>
+ <use xlink:href="#glyph0-9" x="224" y="181"/>
+ <use xlink:href="#glyph0-15" x="238" y="181"/>
+ <use xlink:href="#glyph0-12" x="252" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 266 155 L 448 155 L 448 186 L 266 186 Z M 266 155 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="181"/>
+ <use xlink:href="#glyph0-7" x="280" y="181"/>
+ <use xlink:href="#glyph0-1" x="294" y="181"/>
+ <use xlink:href="#glyph0-46" x="308" y="181"/>
+ <use xlink:href="#glyph0-1" x="322" y="181"/>
+ <use xlink:href="#glyph0-47" x="336" y="181"/>
+ <use xlink:href="#glyph0-48" x="350" y="181"/>
+ <use xlink:href="#glyph0-1" x="364" y="181"/>
+ <use xlink:href="#glyph0-3" x="378" y="181"/>
+ <use xlink:href="#glyph0-23" x="392" y="181"/>
+ <use xlink:href="#glyph0-29" x="406" y="181"/>
+ <use xlink:href="#glyph0-6" x="420" y="181"/>
+ <use xlink:href="#glyph0-1" x="434" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 448 155 L 532 155 L 532 186 L 448 186 Z M 448 155 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="181"/>
+ <use xlink:href="#glyph0-6" x="462" y="181"/>
+ <use xlink:href="#glyph0-38" x="476" y="181"/>
+ <use xlink:href="#glyph0-4" x="490" y="181"/>
+ <use xlink:href="#glyph0-25" x="504" y="181"/>
+ <use xlink:href="#glyph0-6" x="518" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 532 155 L 546 155 L 546 186 L 532 186 Z M 532 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 546 155 L 588 155 L 588 186 L 546 186 Z M 546 155 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="181"/>
+ <use xlink:href="#glyph0-15" x="560" y="181"/>
+ <use xlink:href="#glyph0-33" x="574" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 588 155 L 840 155 L 840 186 L 588 186 Z M 588 155 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="181"/>
+ <use xlink:href="#glyph0-1" x="602" y="181"/>
+ <use xlink:href="#glyph0-46" x="616" y="181"/>
+ <use xlink:href="#glyph0-1" x="630" y="181"/>
+ <use xlink:href="#glyph0-2" x="644" y="181"/>
+ <use xlink:href="#glyph0-49" x="658" y="181"/>
+ <use xlink:href="#glyph0-7" x="672" y="181"/>
+ <use xlink:href="#glyph0-1" x="686" y="181"/>
+ <use xlink:href="#glyph0-22" x="700" y="181"/>
+ <use xlink:href="#glyph0-26" x="714" y="181"/>
+ <use xlink:href="#glyph0-15" x="728" y="181"/>
+ <use xlink:href="#glyph0-12" x="742" y="181"/>
+ <use xlink:href="#glyph0-50" x="756" y="181"/>
+ <use xlink:href="#glyph0-17" x="770" y="181"/>
+ <use xlink:href="#glyph0-4" x="784" y="181"/>
+ <use xlink:href="#glyph0-9" x="798" y="181"/>
+ <use xlink:href="#glyph0-6" x="812" y="181"/>
+ <use xlink:href="#glyph0-1" x="826" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 840 155 L 924 155 L 924 186 L 840 186 Z M 840 155 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="840" y="181"/>
+ <use xlink:href="#glyph0-4" x="854" y="181"/>
+ <use xlink:href="#glyph0-14" x="868" y="181"/>
+ <use xlink:href="#glyph0-9" x="882" y="181"/>
+ <use xlink:href="#glyph0-15" x="896" y="181"/>
+ <use xlink:href="#glyph0-12" x="910" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(30.588235%,30.588235%,30.588235%);fill-opacity:1;" d="M 924 155 L 1232 155 L 1232 186 L 924 186 Z M 924 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 155 L 1260 155 L 1260 186 L 1232 186 Z M 1232 155 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="181"/>
+ <use xlink:href="#glyph0-45" x="1246" y="181"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 155 L 1400 155 L 1400 186 L 1260 186 Z M 1260 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 155 L 1414 155 L 1414 186 L 1400 186 Z M 1400 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 155 L 1428 155 L 1428 186 L 1414 186 Z M 1414 155 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 186 L 140 186 L 140 217 L 0 217 Z M 0 186 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 186 L 168 186 L 168 217 L 140 217 Z M 140 186 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="212"/>
+ <use xlink:href="#glyph0-1" x="154" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 186 L 182 186 L 182 217 L 168 217 Z M 168 186 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 186 L 266 186 L 266 217 L 182 217 Z M 182 186 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="212"/>
+ <use xlink:href="#glyph0-4" x="196" y="212"/>
+ <use xlink:href="#glyph0-14" x="210" y="212"/>
+ <use xlink:href="#glyph0-9" x="224" y="212"/>
+ <use xlink:href="#glyph0-15" x="238" y="212"/>
+ <use xlink:href="#glyph0-12" x="252" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 186 L 448 186 L 448 217 L 266 217 Z M 266 186 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="212"/>
+ <use xlink:href="#glyph0-7" x="280" y="212"/>
+ <use xlink:href="#glyph0-1" x="294" y="212"/>
+ <use xlink:href="#glyph0-46" x="308" y="212"/>
+ <use xlink:href="#glyph0-1" x="322" y="212"/>
+ <use xlink:href="#glyph0-47" x="336" y="212"/>
+ <use xlink:href="#glyph0-48" x="350" y="212"/>
+ <use xlink:href="#glyph0-1" x="364" y="212"/>
+ <use xlink:href="#glyph0-3" x="378" y="212"/>
+ <use xlink:href="#glyph0-23" x="392" y="212"/>
+ <use xlink:href="#glyph0-29" x="406" y="212"/>
+ <use xlink:href="#glyph0-6" x="420" y="212"/>
+ <use xlink:href="#glyph0-1" x="434" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 186 L 532 186 L 532 217 L 448 217 Z M 448 186 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="212"/>
+ <use xlink:href="#glyph0-6" x="462" y="212"/>
+ <use xlink:href="#glyph0-38" x="476" y="212"/>
+ <use xlink:href="#glyph0-4" x="490" y="212"/>
+ <use xlink:href="#glyph0-25" x="504" y="212"/>
+ <use xlink:href="#glyph0-6" x="518" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 186 L 546 186 L 546 217 L 532 217 Z M 532 186 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 186 L 588 186 L 588 217 L 546 217 Z M 546 186 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="212"/>
+ <use xlink:href="#glyph0-15" x="560" y="212"/>
+ <use xlink:href="#glyph0-33" x="574" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 186 L 1232 186 L 1232 217 L 588 217 Z M 588 186 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="212"/>
+ <use xlink:href="#glyph0-1" x="602" y="212"/>
+ <use xlink:href="#glyph0-46" x="616" y="212"/>
+ <use xlink:href="#glyph0-1" x="630" y="212"/>
+ <use xlink:href="#glyph0-22" x="644" y="212"/>
+ <use xlink:href="#glyph0-23" x="658" y="212"/>
+ <use xlink:href="#glyph0-38" x="672" y="212"/>
+ <use xlink:href="#glyph0-6" x="686" y="212"/>
+ <use xlink:href="#glyph0-50" x="700" y="212"/>
+ <use xlink:href="#glyph0-8" x="714" y="212"/>
+ <use xlink:href="#glyph0-51" x="728" y="212"/>
+ <use xlink:href="#glyph0-18" x="742" y="212"/>
+ <use xlink:href="#glyph0-15" x="756" y="212"/>
+ <use xlink:href="#glyph0-24" x="770" y="212"/>
+ <use xlink:href="#glyph0-10" x="784" y="212"/>
+ <use xlink:href="#glyph0-1" x="798" y="212"/>
+ <use xlink:href="#glyph0-23" x="812" y="212"/>
+ <use xlink:href="#glyph0-1" x="826" y="212"/>
+ <use xlink:href="#glyph0-25" x="840" y="212"/>
+ <use xlink:href="#glyph0-15" x="854" y="212"/>
+ <use xlink:href="#glyph0-18" x="868" y="212"/>
+ <use xlink:href="#glyph0-34" x="882" y="212"/>
+ <use xlink:href="#glyph0-1" x="896" y="212"/>
+ <use xlink:href="#glyph0-1" x="910" y="212"/>
+ <use xlink:href="#glyph0-1" x="924" y="212"/>
+ <use xlink:href="#glyph0-1" x="938" y="212"/>
+ <use xlink:href="#glyph0-1" x="952" y="212"/>
+ <use xlink:href="#glyph0-1" x="966" y="212"/>
+ <use xlink:href="#glyph0-1" x="980" y="212"/>
+ <use xlink:href="#glyph0-1" x="994" y="212"/>
+ <use xlink:href="#glyph0-1" x="1008" y="212"/>
+ <use xlink:href="#glyph0-1" x="1022" y="212"/>
+ <use xlink:href="#glyph0-1" x="1036" y="212"/>
+ <use xlink:href="#glyph0-1" x="1050" y="212"/>
+ <use xlink:href="#glyph0-1" x="1064" y="212"/>
+ <use xlink:href="#glyph0-1" x="1078" y="212"/>
+ <use xlink:href="#glyph0-1" x="1092" y="212"/>
+ <use xlink:href="#glyph0-1" x="1106" y="212"/>
+ <use xlink:href="#glyph0-1" x="1120" y="212"/>
+ <use xlink:href="#glyph0-1" x="1134" y="212"/>
+ <use xlink:href="#glyph0-1" x="1148" y="212"/>
+ <use xlink:href="#glyph0-1" x="1162" y="212"/>
+ <use xlink:href="#glyph0-1" x="1176" y="212"/>
+ <use xlink:href="#glyph0-1" x="1190" y="212"/>
+ <use xlink:href="#glyph0-1" x="1204" y="212"/>
+ <use xlink:href="#glyph0-1" x="1218" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 186 L 1260 186 L 1260 217 L 1232 217 Z M 1232 186 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="212"/>
+ <use xlink:href="#glyph0-45" x="1246" y="212"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 186 L 1400 186 L 1400 217 L 1260 217 Z M 1260 186 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 186 L 1414 186 L 1414 217 L 1400 217 Z M 1400 186 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 186 L 1428 186 L 1428 217 L 1414 217 Z M 1414 186 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 217 L 140 217 L 140 248 L 0 248 Z M 0 217 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 217 L 168 217 L 168 248 L 140 248 Z M 140 217 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="243"/>
+ <use xlink:href="#glyph0-1" x="154" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 217 L 182 217 L 182 248 L 168 248 Z M 168 217 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 217 L 266 217 L 266 248 L 182 248 Z M 182 217 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="243"/>
+ <use xlink:href="#glyph0-4" x="196" y="243"/>
+ <use xlink:href="#glyph0-14" x="210" y="243"/>
+ <use xlink:href="#glyph0-9" x="224" y="243"/>
+ <use xlink:href="#glyph0-15" x="238" y="243"/>
+ <use xlink:href="#glyph0-12" x="252" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 217 L 448 217 L 448 248 L 266 248 Z M 266 217 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="243"/>
+ <use xlink:href="#glyph0-7" x="280" y="243"/>
+ <use xlink:href="#glyph0-1" x="294" y="243"/>
+ <use xlink:href="#glyph0-46" x="308" y="243"/>
+ <use xlink:href="#glyph0-1" x="322" y="243"/>
+ <use xlink:href="#glyph0-47" x="336" y="243"/>
+ <use xlink:href="#glyph0-48" x="350" y="243"/>
+ <use xlink:href="#glyph0-1" x="364" y="243"/>
+ <use xlink:href="#glyph0-3" x="378" y="243"/>
+ <use xlink:href="#glyph0-23" x="392" y="243"/>
+ <use xlink:href="#glyph0-29" x="406" y="243"/>
+ <use xlink:href="#glyph0-6" x="420" y="243"/>
+ <use xlink:href="#glyph0-1" x="434" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 217 L 532 217 L 532 248 L 448 248 Z M 448 217 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="243"/>
+ <use xlink:href="#glyph0-6" x="462" y="243"/>
+ <use xlink:href="#glyph0-38" x="476" y="243"/>
+ <use xlink:href="#glyph0-4" x="490" y="243"/>
+ <use xlink:href="#glyph0-25" x="504" y="243"/>
+ <use xlink:href="#glyph0-6" x="518" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 217 L 546 217 L 546 248 L 532 248 Z M 532 217 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 217 L 588 217 L 588 248 L 546 248 Z M 546 217 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="243"/>
+ <use xlink:href="#glyph0-15" x="560" y="243"/>
+ <use xlink:href="#glyph0-33" x="574" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 217 L 1232 217 L 1232 248 L 588 248 Z M 588 217 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="243"/>
+ <use xlink:href="#glyph0-1" x="602" y="243"/>
+ <use xlink:href="#glyph0-46" x="616" y="243"/>
+ <use xlink:href="#glyph0-1" x="630" y="243"/>
+ <use xlink:href="#glyph0-2" x="644" y="243"/>
+ <use xlink:href="#glyph0-1" x="658" y="243"/>
+ <use xlink:href="#glyph0-7" x="672" y="243"/>
+ <use xlink:href="#glyph0-1" x="686" y="243"/>
+ <use xlink:href="#glyph0-37" x="700" y="243"/>
+ <use xlink:href="#glyph0-4" x="714" y="243"/>
+ <use xlink:href="#glyph0-14" x="728" y="243"/>
+ <use xlink:href="#glyph0-6" x="742" y="243"/>
+ <use xlink:href="#glyph0-1" x="756" y="243"/>
+ <use xlink:href="#glyph0-12" x="770" y="243"/>
+ <use xlink:href="#glyph0-24" x="784" y="243"/>
+ <use xlink:href="#glyph0-23" x="798" y="243"/>
+ <use xlink:href="#glyph0-18" x="812" y="243"/>
+ <use xlink:href="#glyph0-18" x="826" y="243"/>
+ <use xlink:href="#glyph0-4" x="840" y="243"/>
+ <use xlink:href="#glyph0-14" x="854" y="243"/>
+ <use xlink:href="#glyph0-33" x="868" y="243"/>
+ <use xlink:href="#glyph0-1" x="882" y="243"/>
+ <use xlink:href="#glyph0-1" x="896" y="243"/>
+ <use xlink:href="#glyph0-1" x="910" y="243"/>
+ <use xlink:href="#glyph0-1" x="924" y="243"/>
+ <use xlink:href="#glyph0-1" x="938" y="243"/>
+ <use xlink:href="#glyph0-1" x="952" y="243"/>
+ <use xlink:href="#glyph0-1" x="966" y="243"/>
+ <use xlink:href="#glyph0-1" x="980" y="243"/>
+ <use xlink:href="#glyph0-1" x="994" y="243"/>
+ <use xlink:href="#glyph0-1" x="1008" y="243"/>
+ <use xlink:href="#glyph0-1" x="1022" y="243"/>
+ <use xlink:href="#glyph0-1" x="1036" y="243"/>
+ <use xlink:href="#glyph0-1" x="1050" y="243"/>
+ <use xlink:href="#glyph0-1" x="1064" y="243"/>
+ <use xlink:href="#glyph0-1" x="1078" y="243"/>
+ <use xlink:href="#glyph0-1" x="1092" y="243"/>
+ <use xlink:href="#glyph0-1" x="1106" y="243"/>
+ <use xlink:href="#glyph0-1" x="1120" y="243"/>
+ <use xlink:href="#glyph0-1" x="1134" y="243"/>
+ <use xlink:href="#glyph0-1" x="1148" y="243"/>
+ <use xlink:href="#glyph0-1" x="1162" y="243"/>
+ <use xlink:href="#glyph0-1" x="1176" y="243"/>
+ <use xlink:href="#glyph0-1" x="1190" y="243"/>
+ <use xlink:href="#glyph0-1" x="1204" y="243"/>
+ <use xlink:href="#glyph0-1" x="1218" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 217 L 1260 217 L 1260 248 L 1232 248 Z M 1232 217 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="243"/>
+ <use xlink:href="#glyph0-45" x="1246" y="243"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 217 L 1400 217 L 1400 248 L 1260 248 Z M 1260 217 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 217 L 1414 217 L 1414 248 L 1400 248 Z M 1400 217 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 217 L 1428 217 L 1428 248 L 1414 248 Z M 1414 217 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 248 L 140 248 L 140 279 L 0 279 Z M 0 248 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 248 L 168 248 L 168 279 L 140 279 Z M 140 248 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="274"/>
+ <use xlink:href="#glyph0-1" x="154" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 248 L 182 248 L 182 279 L 168 279 Z M 168 248 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 248 L 266 248 L 266 279 L 182 279 Z M 182 248 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="274"/>
+ <use xlink:href="#glyph0-4" x="196" y="274"/>
+ <use xlink:href="#glyph0-14" x="210" y="274"/>
+ <use xlink:href="#glyph0-9" x="224" y="274"/>
+ <use xlink:href="#glyph0-15" x="238" y="274"/>
+ <use xlink:href="#glyph0-12" x="252" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 248 L 448 248 L 448 279 L 266 279 Z M 266 248 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="274"/>
+ <use xlink:href="#glyph0-7" x="280" y="274"/>
+ <use xlink:href="#glyph0-1" x="294" y="274"/>
+ <use xlink:href="#glyph0-46" x="308" y="274"/>
+ <use xlink:href="#glyph0-1" x="322" y="274"/>
+ <use xlink:href="#glyph0-47" x="336" y="274"/>
+ <use xlink:href="#glyph0-48" x="350" y="274"/>
+ <use xlink:href="#glyph0-1" x="364" y="274"/>
+ <use xlink:href="#glyph0-3" x="378" y="274"/>
+ <use xlink:href="#glyph0-23" x="392" y="274"/>
+ <use xlink:href="#glyph0-29" x="406" y="274"/>
+ <use xlink:href="#glyph0-6" x="420" y="274"/>
+ <use xlink:href="#glyph0-1" x="434" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 248 L 532 248 L 532 279 L 448 279 Z M 448 248 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="274"/>
+ <use xlink:href="#glyph0-6" x="462" y="274"/>
+ <use xlink:href="#glyph0-38" x="476" y="274"/>
+ <use xlink:href="#glyph0-4" x="490" y="274"/>
+ <use xlink:href="#glyph0-25" x="504" y="274"/>
+ <use xlink:href="#glyph0-6" x="518" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 248 L 546 248 L 546 279 L 532 279 Z M 532 248 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 248 L 588 248 L 588 279 L 546 279 Z M 546 248 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="274"/>
+ <use xlink:href="#glyph0-15" x="560" y="274"/>
+ <use xlink:href="#glyph0-33" x="574" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 248 L 1232 248 L 1232 279 L 588 279 Z M 588 248 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="274"/>
+ <use xlink:href="#glyph0-1" x="602" y="274"/>
+ <use xlink:href="#glyph0-46" x="616" y="274"/>
+ <use xlink:href="#glyph0-1" x="630" y="274"/>
+ <use xlink:href="#glyph0-2" x="644" y="274"/>
+ <use xlink:href="#glyph0-49" x="658" y="274"/>
+ <use xlink:href="#glyph0-7" x="672" y="274"/>
+ <use xlink:href="#glyph0-1" x="686" y="274"/>
+ <use xlink:href="#glyph0-20" x="700" y="274"/>
+ <use xlink:href="#glyph0-23" x="714" y="274"/>
+ <use xlink:href="#glyph0-32" x="728" y="274"/>
+ <use xlink:href="#glyph0-5" x="742" y="274"/>
+ <use xlink:href="#glyph0-6" x="756" y="274"/>
+ <use xlink:href="#glyph0-1" x="770" y="274"/>
+ <use xlink:href="#glyph0-38" x="784" y="274"/>
+ <use xlink:href="#glyph0-4" x="798" y="274"/>
+ <use xlink:href="#glyph0-6" x="812" y="274"/>
+ <use xlink:href="#glyph0-12" x="826" y="274"/>
+ <use xlink:href="#glyph0-1" x="840" y="274"/>
+ <use xlink:href="#glyph0-1" x="854" y="274"/>
+ <use xlink:href="#glyph0-1" x="868" y="274"/>
+ <use xlink:href="#glyph0-1" x="882" y="274"/>
+ <use xlink:href="#glyph0-1" x="896" y="274"/>
+ <use xlink:href="#glyph0-1" x="910" y="274"/>
+ <use xlink:href="#glyph0-1" x="924" y="274"/>
+ <use xlink:href="#glyph0-1" x="938" y="274"/>
+ <use xlink:href="#glyph0-1" x="952" y="274"/>
+ <use xlink:href="#glyph0-1" x="966" y="274"/>
+ <use xlink:href="#glyph0-1" x="980" y="274"/>
+ <use xlink:href="#glyph0-1" x="994" y="274"/>
+ <use xlink:href="#glyph0-1" x="1008" y="274"/>
+ <use xlink:href="#glyph0-1" x="1022" y="274"/>
+ <use xlink:href="#glyph0-1" x="1036" y="274"/>
+ <use xlink:href="#glyph0-1" x="1050" y="274"/>
+ <use xlink:href="#glyph0-1" x="1064" y="274"/>
+ <use xlink:href="#glyph0-1" x="1078" y="274"/>
+ <use xlink:href="#glyph0-1" x="1092" y="274"/>
+ <use xlink:href="#glyph0-1" x="1106" y="274"/>
+ <use xlink:href="#glyph0-1" x="1120" y="274"/>
+ <use xlink:href="#glyph0-1" x="1134" y="274"/>
+ <use xlink:href="#glyph0-1" x="1148" y="274"/>
+ <use xlink:href="#glyph0-1" x="1162" y="274"/>
+ <use xlink:href="#glyph0-1" x="1176" y="274"/>
+ <use xlink:href="#glyph0-1" x="1190" y="274"/>
+ <use xlink:href="#glyph0-1" x="1204" y="274"/>
+ <use xlink:href="#glyph0-1" x="1218" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 248 L 1260 248 L 1260 279 L 1232 279 Z M 1232 248 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="274"/>
+ <use xlink:href="#glyph0-45" x="1246" y="274"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 248 L 1400 248 L 1400 279 L 1260 279 Z M 1260 248 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 248 L 1414 248 L 1414 279 L 1400 279 Z M 1400 248 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 248 L 1428 248 L 1428 279 L 1414 279 Z M 1414 248 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 279 L 140 279 L 140 310 L 0 310 Z M 0 279 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 279 L 168 279 L 168 310 L 140 310 Z M 140 279 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="305"/>
+ <use xlink:href="#glyph0-1" x="154" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 279 L 182 279 L 182 310 L 168 310 Z M 168 279 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 279 L 266 279 L 266 310 L 182 310 Z M 182 279 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="305"/>
+ <use xlink:href="#glyph0-4" x="196" y="305"/>
+ <use xlink:href="#glyph0-14" x="210" y="305"/>
+ <use xlink:href="#glyph0-9" x="224" y="305"/>
+ <use xlink:href="#glyph0-15" x="238" y="305"/>
+ <use xlink:href="#glyph0-12" x="252" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 279 L 448 279 L 448 310 L 266 310 Z M 266 279 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="305"/>
+ <use xlink:href="#glyph0-7" x="280" y="305"/>
+ <use xlink:href="#glyph0-1" x="294" y="305"/>
+ <use xlink:href="#glyph0-46" x="308" y="305"/>
+ <use xlink:href="#glyph0-1" x="322" y="305"/>
+ <use xlink:href="#glyph0-47" x="336" y="305"/>
+ <use xlink:href="#glyph0-48" x="350" y="305"/>
+ <use xlink:href="#glyph0-1" x="364" y="305"/>
+ <use xlink:href="#glyph0-3" x="378" y="305"/>
+ <use xlink:href="#glyph0-23" x="392" y="305"/>
+ <use xlink:href="#glyph0-29" x="406" y="305"/>
+ <use xlink:href="#glyph0-6" x="420" y="305"/>
+ <use xlink:href="#glyph0-1" x="434" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 279 L 532 279 L 532 310 L 448 310 Z M 448 279 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="305"/>
+ <use xlink:href="#glyph0-6" x="462" y="305"/>
+ <use xlink:href="#glyph0-38" x="476" y="305"/>
+ <use xlink:href="#glyph0-4" x="490" y="305"/>
+ <use xlink:href="#glyph0-25" x="504" y="305"/>
+ <use xlink:href="#glyph0-6" x="518" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 279 L 546 279 L 546 310 L 532 310 Z M 532 279 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 279 L 588 279 L 588 310 L 546 310 Z M 546 279 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="305"/>
+ <use xlink:href="#glyph0-15" x="560" y="305"/>
+ <use xlink:href="#glyph0-33" x="574" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 279 L 1232 279 L 1232 310 L 588 310 Z M 588 279 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="305"/>
+ <use xlink:href="#glyph0-1" x="602" y="305"/>
+ <use xlink:href="#glyph0-46" x="616" y="305"/>
+ <use xlink:href="#glyph0-1" x="630" y="305"/>
+ <use xlink:href="#glyph0-2" x="644" y="305"/>
+ <use xlink:href="#glyph0-49" x="658" y="305"/>
+ <use xlink:href="#glyph0-7" x="672" y="305"/>
+ <use xlink:href="#glyph0-1" x="686" y="305"/>
+ <use xlink:href="#glyph0-3" x="700" y="305"/>
+ <use xlink:href="#glyph0-15" x="714" y="305"/>
+ <use xlink:href="#glyph0-5" x="728" y="305"/>
+ <use xlink:href="#glyph0-5" x="742" y="305"/>
+ <use xlink:href="#glyph0-15" x="756" y="305"/>
+ <use xlink:href="#glyph0-12" x="770" y="305"/>
+ <use xlink:href="#glyph0-1" x="784" y="305"/>
+ <use xlink:href="#glyph0-1" x="798" y="305"/>
+ <use xlink:href="#glyph0-1" x="812" y="305"/>
+ <use xlink:href="#glyph0-1" x="826" y="305"/>
+ <use xlink:href="#glyph0-1" x="840" y="305"/>
+ <use xlink:href="#glyph0-1" x="854" y="305"/>
+ <use xlink:href="#glyph0-1" x="868" y="305"/>
+ <use xlink:href="#glyph0-1" x="882" y="305"/>
+ <use xlink:href="#glyph0-1" x="896" y="305"/>
+ <use xlink:href="#glyph0-1" x="910" y="305"/>
+ <use xlink:href="#glyph0-1" x="924" y="305"/>
+ <use xlink:href="#glyph0-1" x="938" y="305"/>
+ <use xlink:href="#glyph0-1" x="952" y="305"/>
+ <use xlink:href="#glyph0-1" x="966" y="305"/>
+ <use xlink:href="#glyph0-1" x="980" y="305"/>
+ <use xlink:href="#glyph0-1" x="994" y="305"/>
+ <use xlink:href="#glyph0-1" x="1008" y="305"/>
+ <use xlink:href="#glyph0-1" x="1022" y="305"/>
+ <use xlink:href="#glyph0-1" x="1036" y="305"/>
+ <use xlink:href="#glyph0-1" x="1050" y="305"/>
+ <use xlink:href="#glyph0-1" x="1064" y="305"/>
+ <use xlink:href="#glyph0-1" x="1078" y="305"/>
+ <use xlink:href="#glyph0-1" x="1092" y="305"/>
+ <use xlink:href="#glyph0-1" x="1106" y="305"/>
+ <use xlink:href="#glyph0-1" x="1120" y="305"/>
+ <use xlink:href="#glyph0-1" x="1134" y="305"/>
+ <use xlink:href="#glyph0-1" x="1148" y="305"/>
+ <use xlink:href="#glyph0-1" x="1162" y="305"/>
+ <use xlink:href="#glyph0-1" x="1176" y="305"/>
+ <use xlink:href="#glyph0-1" x="1190" y="305"/>
+ <use xlink:href="#glyph0-1" x="1204" y="305"/>
+ <use xlink:href="#glyph0-1" x="1218" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 279 L 1260 279 L 1260 310 L 1232 310 Z M 1232 279 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="305"/>
+ <use xlink:href="#glyph0-45" x="1246" y="305"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 279 L 1400 279 L 1400 310 L 1260 310 Z M 1260 279 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;" d="M 1400 279 L 1414 279 L 1414 310 L 1400 310 Z M 1400 279 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 279 L 1428 279 L 1428 310 L 1414 310 Z M 1414 279 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 310 L 140 310 L 140 341 L 0 341 Z M 0 310 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 310 L 168 310 L 168 341 L 140 341 Z M 140 310 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="336"/>
+ <use xlink:href="#glyph0-1" x="154" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 310 L 182 310 L 182 341 L 168 341 Z M 168 310 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 310 L 266 310 L 266 341 L 182 341 Z M 182 310 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="336"/>
+ <use xlink:href="#glyph0-4" x="196" y="336"/>
+ <use xlink:href="#glyph0-14" x="210" y="336"/>
+ <use xlink:href="#glyph0-9" x="224" y="336"/>
+ <use xlink:href="#glyph0-15" x="238" y="336"/>
+ <use xlink:href="#glyph0-12" x="252" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 310 L 448 310 L 448 341 L 266 341 Z M 266 310 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="336"/>
+ <use xlink:href="#glyph0-7" x="280" y="336"/>
+ <use xlink:href="#glyph0-1" x="294" y="336"/>
+ <use xlink:href="#glyph0-46" x="308" y="336"/>
+ <use xlink:href="#glyph0-1" x="322" y="336"/>
+ <use xlink:href="#glyph0-47" x="336" y="336"/>
+ <use xlink:href="#glyph0-48" x="350" y="336"/>
+ <use xlink:href="#glyph0-1" x="364" y="336"/>
+ <use xlink:href="#glyph0-3" x="378" y="336"/>
+ <use xlink:href="#glyph0-23" x="392" y="336"/>
+ <use xlink:href="#glyph0-29" x="406" y="336"/>
+ <use xlink:href="#glyph0-6" x="420" y="336"/>
+ <use xlink:href="#glyph0-1" x="434" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 310 L 532 310 L 532 341 L 448 341 Z M 448 310 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="336"/>
+ <use xlink:href="#glyph0-6" x="462" y="336"/>
+ <use xlink:href="#glyph0-38" x="476" y="336"/>
+ <use xlink:href="#glyph0-4" x="490" y="336"/>
+ <use xlink:href="#glyph0-25" x="504" y="336"/>
+ <use xlink:href="#glyph0-6" x="518" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 310 L 546 310 L 546 341 L 532 341 Z M 532 310 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 310 L 588 310 L 588 341 L 546 341 Z M 546 310 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="336"/>
+ <use xlink:href="#glyph0-15" x="560" y="336"/>
+ <use xlink:href="#glyph0-33" x="574" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 310 L 1232 310 L 1232 341 L 588 341 Z M 588 310 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="336"/>
+ <use xlink:href="#glyph0-1" x="602" y="336"/>
+ <use xlink:href="#glyph0-46" x="616" y="336"/>
+ <use xlink:href="#glyph0-1" x="630" y="336"/>
+ <use xlink:href="#glyph0-19" x="644" y="336"/>
+ <use xlink:href="#glyph0-5" x="658" y="336"/>
+ <use xlink:href="#glyph0-6" x="672" y="336"/>
+ <use xlink:href="#glyph0-23" x="686" y="336"/>
+ <use xlink:href="#glyph0-24" x="700" y="336"/>
+ <use xlink:href="#glyph0-1" x="714" y="336"/>
+ <use xlink:href="#glyph0-26" x="728" y="336"/>
+ <use xlink:href="#glyph0-4" x="742" y="336"/>
+ <use xlink:href="#glyph0-16" x="756" y="336"/>
+ <use xlink:href="#glyph0-10" x="770" y="336"/>
+ <use xlink:href="#glyph0-15" x="784" y="336"/>
+ <use xlink:href="#glyph0-24" x="798" y="336"/>
+ <use xlink:href="#glyph0-34" x="812" y="336"/>
+ <use xlink:href="#glyph0-1" x="826" y="336"/>
+ <use xlink:href="#glyph0-1" x="840" y="336"/>
+ <use xlink:href="#glyph0-1" x="854" y="336"/>
+ <use xlink:href="#glyph0-1" x="868" y="336"/>
+ <use xlink:href="#glyph0-1" x="882" y="336"/>
+ <use xlink:href="#glyph0-1" x="896" y="336"/>
+ <use xlink:href="#glyph0-1" x="910" y="336"/>
+ <use xlink:href="#glyph0-1" x="924" y="336"/>
+ <use xlink:href="#glyph0-1" x="938" y="336"/>
+ <use xlink:href="#glyph0-1" x="952" y="336"/>
+ <use xlink:href="#glyph0-1" x="966" y="336"/>
+ <use xlink:href="#glyph0-1" x="980" y="336"/>
+ <use xlink:href="#glyph0-1" x="994" y="336"/>
+ <use xlink:href="#glyph0-1" x="1008" y="336"/>
+ <use xlink:href="#glyph0-1" x="1022" y="336"/>
+ <use xlink:href="#glyph0-1" x="1036" y="336"/>
+ <use xlink:href="#glyph0-1" x="1050" y="336"/>
+ <use xlink:href="#glyph0-1" x="1064" y="336"/>
+ <use xlink:href="#glyph0-1" x="1078" y="336"/>
+ <use xlink:href="#glyph0-1" x="1092" y="336"/>
+ <use xlink:href="#glyph0-1" x="1106" y="336"/>
+ <use xlink:href="#glyph0-1" x="1120" y="336"/>
+ <use xlink:href="#glyph0-1" x="1134" y="336"/>
+ <use xlink:href="#glyph0-1" x="1148" y="336"/>
+ <use xlink:href="#glyph0-1" x="1162" y="336"/>
+ <use xlink:href="#glyph0-1" x="1176" y="336"/>
+ <use xlink:href="#glyph0-1" x="1190" y="336"/>
+ <use xlink:href="#glyph0-1" x="1204" y="336"/>
+ <use xlink:href="#glyph0-1" x="1218" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 310 L 1260 310 L 1260 341 L 1232 341 Z M 1232 310 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="336"/>
+ <use xlink:href="#glyph0-45" x="1246" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 310 L 1400 310 L 1400 341 L 1260 341 Z M 1260 310 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(6.27451%,5.882353%,6.27451%);fill-opacity:1;" d="M 1400 310 L 1414 310 L 1414 341 L 1400 341 Z M 1400 310 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-38" x="1400" y="336"/>
+</g>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-38" x="1401" y="336"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 310 L 1428 310 L 1428 341 L 1414 341 Z M 1414 310 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 0 341 L 14 341 L 14 372 L 0 372 Z M 0 341 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 14 341 L 168 341 L 168 372 L 14 372 Z M 14 341 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="14" y="367"/>
+ <use xlink:href="#glyph0-30" x="28" y="367"/>
+ <use xlink:href="#glyph0-34" x="42" y="367"/>
+ <use xlink:href="#glyph0-10" x="56" y="367"/>
+ <use xlink:href="#glyph0-26" x="70" y="367"/>
+ <use xlink:href="#glyph0-15" x="84" y="367"/>
+ <use xlink:href="#glyph0-14" x="98" y="367"/>
+ <use xlink:href="#glyph0-1" x="112" y="367"/>
+ <use xlink:href="#glyph0-35" x="126" y="367"/>
+ <use xlink:href="#glyph0-45" x="140" y="367"/>
+ <use xlink:href="#glyph0-1" x="154" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 341 L 182 341 L 182 372 L 168 372 Z M 168 341 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 341 L 266 341 L 266 372 L 182 372 Z M 182 341 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="367"/>
+ <use xlink:href="#glyph0-4" x="196" y="367"/>
+ <use xlink:href="#glyph0-14" x="210" y="367"/>
+ <use xlink:href="#glyph0-9" x="224" y="367"/>
+ <use xlink:href="#glyph0-15" x="238" y="367"/>
+ <use xlink:href="#glyph0-12" x="252" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 341 L 448 341 L 448 372 L 266 372 Z M 266 341 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="367"/>
+ <use xlink:href="#glyph0-7" x="280" y="367"/>
+ <use xlink:href="#glyph0-1" x="294" y="367"/>
+ <use xlink:href="#glyph0-46" x="308" y="367"/>
+ <use xlink:href="#glyph0-1" x="322" y="367"/>
+ <use xlink:href="#glyph0-47" x="336" y="367"/>
+ <use xlink:href="#glyph0-48" x="350" y="367"/>
+ <use xlink:href="#glyph0-1" x="364" y="367"/>
+ <use xlink:href="#glyph0-3" x="378" y="367"/>
+ <use xlink:href="#glyph0-23" x="392" y="367"/>
+ <use xlink:href="#glyph0-29" x="406" y="367"/>
+ <use xlink:href="#glyph0-6" x="420" y="367"/>
+ <use xlink:href="#glyph0-1" x="434" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 341 L 532 341 L 532 372 L 448 372 Z M 448 341 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="367"/>
+ <use xlink:href="#glyph0-6" x="462" y="367"/>
+ <use xlink:href="#glyph0-38" x="476" y="367"/>
+ <use xlink:href="#glyph0-4" x="490" y="367"/>
+ <use xlink:href="#glyph0-25" x="504" y="367"/>
+ <use xlink:href="#glyph0-6" x="518" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 341 L 546 341 L 546 372 L 532 372 Z M 532 341 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 341 L 588 341 L 588 372 L 546 372 Z M 546 341 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="367"/>
+ <use xlink:href="#glyph0-15" x="560" y="367"/>
+ <use xlink:href="#glyph0-33" x="574" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 341 L 1232 341 L 1232 372 L 588 372 Z M 588 341 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="367"/>
+ <use xlink:href="#glyph0-1" x="602" y="367"/>
+ <use xlink:href="#glyph0-46" x="616" y="367"/>
+ <use xlink:href="#glyph0-1" x="630" y="367"/>
+ <use xlink:href="#glyph0-31" x="644" y="367"/>
+ <use xlink:href="#glyph0-27" x="658" y="367"/>
+ <use xlink:href="#glyph0-18" x="672" y="367"/>
+ <use xlink:href="#glyph0-5" x="686" y="367"/>
+ <use xlink:href="#glyph0-4" x="700" y="367"/>
+ <use xlink:href="#glyph0-25" x="714" y="367"/>
+ <use xlink:href="#glyph0-23" x="728" y="367"/>
+ <use xlink:href="#glyph0-10" x="742" y="367"/>
+ <use xlink:href="#glyph0-6" x="756" y="367"/>
+ <use xlink:href="#glyph0-1" x="770" y="367"/>
+ <use xlink:href="#glyph0-18" x="784" y="367"/>
+ <use xlink:href="#glyph0-23" x="798" y="367"/>
+ <use xlink:href="#glyph0-14" x="812" y="367"/>
+ <use xlink:href="#glyph0-6" x="826" y="367"/>
+ <use xlink:href="#glyph0-1" x="840" y="367"/>
+ <use xlink:href="#glyph0-1" x="854" y="367"/>
+ <use xlink:href="#glyph0-1" x="868" y="367"/>
+ <use xlink:href="#glyph0-1" x="882" y="367"/>
+ <use xlink:href="#glyph0-1" x="896" y="367"/>
+ <use xlink:href="#glyph0-1" x="910" y="367"/>
+ <use xlink:href="#glyph0-1" x="924" y="367"/>
+ <use xlink:href="#glyph0-1" x="938" y="367"/>
+ <use xlink:href="#glyph0-1" x="952" y="367"/>
+ <use xlink:href="#glyph0-1" x="966" y="367"/>
+ <use xlink:href="#glyph0-1" x="980" y="367"/>
+ <use xlink:href="#glyph0-1" x="994" y="367"/>
+ <use xlink:href="#glyph0-1" x="1008" y="367"/>
+ <use xlink:href="#glyph0-1" x="1022" y="367"/>
+ <use xlink:href="#glyph0-1" x="1036" y="367"/>
+ <use xlink:href="#glyph0-1" x="1050" y="367"/>
+ <use xlink:href="#glyph0-1" x="1064" y="367"/>
+ <use xlink:href="#glyph0-1" x="1078" y="367"/>
+ <use xlink:href="#glyph0-1" x="1092" y="367"/>
+ <use xlink:href="#glyph0-1" x="1106" y="367"/>
+ <use xlink:href="#glyph0-1" x="1120" y="367"/>
+ <use xlink:href="#glyph0-1" x="1134" y="367"/>
+ <use xlink:href="#glyph0-1" x="1148" y="367"/>
+ <use xlink:href="#glyph0-1" x="1162" y="367"/>
+ <use xlink:href="#glyph0-1" x="1176" y="367"/>
+ <use xlink:href="#glyph0-1" x="1190" y="367"/>
+ <use xlink:href="#glyph0-1" x="1204" y="367"/>
+ <use xlink:href="#glyph0-1" x="1218" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 341 L 1260 341 L 1260 372 L 1232 372 Z M 1232 341 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="367"/>
+ <use xlink:href="#glyph0-45" x="1246" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1260 341 L 1358 341 L 1358 372 L 1260 372 Z M 1260 341 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-15" x="1260" y="367"/>
+ <use xlink:href="#glyph0-1" x="1274" y="367"/>
+ <use xlink:href="#glyph0-52" x="1288" y="367"/>
+ <use xlink:href="#glyph0-15" x="1302" y="367"/>
+ <use xlink:href="#glyph0-25" x="1316" y="367"/>
+ <use xlink:href="#glyph0-27" x="1330" y="367"/>
+ <use xlink:href="#glyph0-16" x="1344" y="367"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1358 341 L 1372 341 L 1372 372 L 1358 372 Z M 1358 341 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1372 341 L 1414 341 L 1414 372 L 1372 372 Z M 1372 341 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 341 L 1428 341 L 1428 372 L 1414 372 Z M 1414 341 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 372 L 56 372 L 56 403 L 0 403 Z M 0 372 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-46" x="0" y="398"/>
+ <use xlink:href="#glyph0-46" x="14" y="398"/>
+ <use xlink:href="#glyph0-46" x="28" y="398"/>
+ <use xlink:href="#glyph0-1" x="42" y="398"/>
+</g>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-46" x="1" y="398"/>
+ <use xlink:href="#glyph0-46" x="15" y="398"/>
+ <use xlink:href="#glyph0-46" x="29" y="398"/>
+ <use xlink:href="#glyph0-1" x="43" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 56 372 L 140 372 L 140 403 L 56 403 Z M 56 372 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 372 L 168 372 L 168 403 L 140 403 Z M 140 372 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="398"/>
+ <use xlink:href="#glyph0-1" x="154" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 372 L 182 372 L 182 403 L 168 403 Z M 168 372 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 372 L 266 372 L 266 403 L 182 403 Z M 182 372 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="398"/>
+ <use xlink:href="#glyph0-4" x="196" y="398"/>
+ <use xlink:href="#glyph0-14" x="210" y="398"/>
+ <use xlink:href="#glyph0-9" x="224" y="398"/>
+ <use xlink:href="#glyph0-15" x="238" y="398"/>
+ <use xlink:href="#glyph0-12" x="252" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 372 L 448 372 L 448 403 L 266 403 Z M 266 372 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="398"/>
+ <use xlink:href="#glyph0-7" x="280" y="398"/>
+ <use xlink:href="#glyph0-1" x="294" y="398"/>
+ <use xlink:href="#glyph0-46" x="308" y="398"/>
+ <use xlink:href="#glyph0-1" x="322" y="398"/>
+ <use xlink:href="#glyph0-47" x="336" y="398"/>
+ <use xlink:href="#glyph0-48" x="350" y="398"/>
+ <use xlink:href="#glyph0-1" x="364" y="398"/>
+ <use xlink:href="#glyph0-3" x="378" y="398"/>
+ <use xlink:href="#glyph0-23" x="392" y="398"/>
+ <use xlink:href="#glyph0-29" x="406" y="398"/>
+ <use xlink:href="#glyph0-6" x="420" y="398"/>
+ <use xlink:href="#glyph0-1" x="434" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 372 L 532 372 L 532 403 L 448 403 Z M 448 372 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="398"/>
+ <use xlink:href="#glyph0-6" x="462" y="398"/>
+ <use xlink:href="#glyph0-38" x="476" y="398"/>
+ <use xlink:href="#glyph0-4" x="490" y="398"/>
+ <use xlink:href="#glyph0-25" x="504" y="398"/>
+ <use xlink:href="#glyph0-6" x="518" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 372 L 546 372 L 546 403 L 532 403 Z M 532 372 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 372 L 588 372 L 588 403 L 546 403 Z M 546 372 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="398"/>
+ <use xlink:href="#glyph0-15" x="560" y="398"/>
+ <use xlink:href="#glyph0-33" x="574" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 372 L 1232 372 L 1232 403 L 588 403 Z M 588 372 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="398"/>
+ <use xlink:href="#glyph0-1" x="602" y="398"/>
+ <use xlink:href="#glyph0-46" x="616" y="398"/>
+ <use xlink:href="#glyph0-1" x="630" y="398"/>
+ <use xlink:href="#glyph0-17" x="644" y="398"/>
+ <use xlink:href="#glyph0-4" x="658" y="398"/>
+ <use xlink:href="#glyph0-9" x="672" y="398"/>
+ <use xlink:href="#glyph0-6" x="686" y="398"/>
+ <use xlink:href="#glyph0-1" x="700" y="398"/>
+ <use xlink:href="#glyph0-16" x="714" y="398"/>
+ <use xlink:href="#glyph0-6" x="728" y="398"/>
+ <use xlink:href="#glyph0-23" x="742" y="398"/>
+ <use xlink:href="#glyph0-24" x="756" y="398"/>
+ <use xlink:href="#glyph0-25" x="770" y="398"/>
+ <use xlink:href="#glyph0-26" x="784" y="398"/>
+ <use xlink:href="#glyph0-1" x="798" y="398"/>
+ <use xlink:href="#glyph0-26" x="812" y="398"/>
+ <use xlink:href="#glyph0-4" x="826" y="398"/>
+ <use xlink:href="#glyph0-33" x="840" y="398"/>
+ <use xlink:href="#glyph0-26" x="854" y="398"/>
+ <use xlink:href="#glyph0-5" x="868" y="398"/>
+ <use xlink:href="#glyph0-4" x="882" y="398"/>
+ <use xlink:href="#glyph0-33" x="896" y="398"/>
+ <use xlink:href="#glyph0-26" x="910" y="398"/>
+ <use xlink:href="#glyph0-10" x="924" y="398"/>
+ <use xlink:href="#glyph0-4" x="938" y="398"/>
+ <use xlink:href="#glyph0-14" x="952" y="398"/>
+ <use xlink:href="#glyph0-33" x="966" y="398"/>
+ <use xlink:href="#glyph0-1" x="980" y="398"/>
+ <use xlink:href="#glyph0-1" x="994" y="398"/>
+ <use xlink:href="#glyph0-1" x="1008" y="398"/>
+ <use xlink:href="#glyph0-1" x="1022" y="398"/>
+ <use xlink:href="#glyph0-1" x="1036" y="398"/>
+ <use xlink:href="#glyph0-1" x="1050" y="398"/>
+ <use xlink:href="#glyph0-1" x="1064" y="398"/>
+ <use xlink:href="#glyph0-1" x="1078" y="398"/>
+ <use xlink:href="#glyph0-1" x="1092" y="398"/>
+ <use xlink:href="#glyph0-1" x="1106" y="398"/>
+ <use xlink:href="#glyph0-1" x="1120" y="398"/>
+ <use xlink:href="#glyph0-1" x="1134" y="398"/>
+ <use xlink:href="#glyph0-1" x="1148" y="398"/>
+ <use xlink:href="#glyph0-1" x="1162" y="398"/>
+ <use xlink:href="#glyph0-1" x="1176" y="398"/>
+ <use xlink:href="#glyph0-1" x="1190" y="398"/>
+ <use xlink:href="#glyph0-1" x="1204" y="398"/>
+ <use xlink:href="#glyph0-1" x="1218" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 372 L 1260 372 L 1260 403 L 1232 403 Z M 1232 372 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="398"/>
+ <use xlink:href="#glyph0-45" x="1246" y="398"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 372 L 1414 372 L 1414 403 L 1260 403 Z M 1260 372 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 372 L 1428 372 L 1428 403 L 1414 403 Z M 1414 372 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 403 L 140 403 L 140 434 L 0 434 Z M 0 403 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 403 L 168 403 L 168 434 L 140 434 Z M 140 403 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="429"/>
+ <use xlink:href="#glyph0-1" x="154" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 403 L 182 403 L 182 434 L 168 434 Z M 168 403 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 403 L 266 403 L 266 434 L 182 434 Z M 182 403 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="429"/>
+ <use xlink:href="#glyph0-4" x="196" y="429"/>
+ <use xlink:href="#glyph0-14" x="210" y="429"/>
+ <use xlink:href="#glyph0-9" x="224" y="429"/>
+ <use xlink:href="#glyph0-15" x="238" y="429"/>
+ <use xlink:href="#glyph0-12" x="252" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 403 L 448 403 L 448 434 L 266 434 Z M 266 403 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="429"/>
+ <use xlink:href="#glyph0-7" x="280" y="429"/>
+ <use xlink:href="#glyph0-1" x="294" y="429"/>
+ <use xlink:href="#glyph0-46" x="308" y="429"/>
+ <use xlink:href="#glyph0-1" x="322" y="429"/>
+ <use xlink:href="#glyph0-47" x="336" y="429"/>
+ <use xlink:href="#glyph0-48" x="350" y="429"/>
+ <use xlink:href="#glyph0-1" x="364" y="429"/>
+ <use xlink:href="#glyph0-3" x="378" y="429"/>
+ <use xlink:href="#glyph0-23" x="392" y="429"/>
+ <use xlink:href="#glyph0-29" x="406" y="429"/>
+ <use xlink:href="#glyph0-6" x="420" y="429"/>
+ <use xlink:href="#glyph0-1" x="434" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 403 L 532 403 L 532 434 L 448 434 Z M 448 403 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="429"/>
+ <use xlink:href="#glyph0-6" x="462" y="429"/>
+ <use xlink:href="#glyph0-38" x="476" y="429"/>
+ <use xlink:href="#glyph0-4" x="490" y="429"/>
+ <use xlink:href="#glyph0-25" x="504" y="429"/>
+ <use xlink:href="#glyph0-6" x="518" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 403 L 546 403 L 546 434 L 532 434 Z M 532 403 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 403 L 588 403 L 588 434 L 546 434 Z M 546 403 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="429"/>
+ <use xlink:href="#glyph0-15" x="560" y="429"/>
+ <use xlink:href="#glyph0-33" x="574" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 403 L 1232 403 L 1232 434 L 588 434 Z M 588 403 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="429"/>
+ <use xlink:href="#glyph0-1" x="602" y="429"/>
+ <use xlink:href="#glyph0-46" x="616" y="429"/>
+ <use xlink:href="#glyph0-1" x="630" y="429"/>
+ <use xlink:href="#glyph0-19" x="644" y="429"/>
+ <use xlink:href="#glyph0-24" x="658" y="429"/>
+ <use xlink:href="#glyph0-6" x="672" y="429"/>
+ <use xlink:href="#glyph0-23" x="686" y="429"/>
+ <use xlink:href="#glyph0-10" x="700" y="429"/>
+ <use xlink:href="#glyph0-6" x="714" y="429"/>
+ <use xlink:href="#glyph0-1" x="728" y="429"/>
+ <use xlink:href="#glyph0-52" x="742" y="429"/>
+ <use xlink:href="#glyph0-4" x="756" y="429"/>
+ <use xlink:href="#glyph0-5" x="770" y="429"/>
+ <use xlink:href="#glyph0-10" x="784" y="429"/>
+ <use xlink:href="#glyph0-6" x="798" y="429"/>
+ <use xlink:href="#glyph0-24" x="812" y="429"/>
+ <use xlink:href="#glyph0-1" x="826" y="429"/>
+ <use xlink:href="#glyph0-52" x="840" y="429"/>
+ <use xlink:href="#glyph0-24" x="854" y="429"/>
+ <use xlink:href="#glyph0-15" x="868" y="429"/>
+ <use xlink:href="#glyph0-43" x="882" y="429"/>
+ <use xlink:href="#glyph0-1" x="896" y="429"/>
+ <use xlink:href="#glyph0-16" x="910" y="429"/>
+ <use xlink:href="#glyph0-6" x="924" y="429"/>
+ <use xlink:href="#glyph0-23" x="938" y="429"/>
+ <use xlink:href="#glyph0-24" x="952" y="429"/>
+ <use xlink:href="#glyph0-25" x="966" y="429"/>
+ <use xlink:href="#glyph0-26" x="980" y="429"/>
+ <use xlink:href="#glyph0-1" x="994" y="429"/>
+ <use xlink:href="#glyph0-24" x="1008" y="429"/>
+ <use xlink:href="#glyph0-6" x="1022" y="429"/>
+ <use xlink:href="#glyph0-16" x="1036" y="429"/>
+ <use xlink:href="#glyph0-27" x="1050" y="429"/>
+ <use xlink:href="#glyph0-5" x="1064" y="429"/>
+ <use xlink:href="#glyph0-10" x="1078" y="429"/>
+ <use xlink:href="#glyph0-16" x="1092" y="429"/>
+ <use xlink:href="#glyph0-1" x="1106" y="429"/>
+ <use xlink:href="#glyph0-1" x="1120" y="429"/>
+ <use xlink:href="#glyph0-1" x="1134" y="429"/>
+ <use xlink:href="#glyph0-1" x="1148" y="429"/>
+ <use xlink:href="#glyph0-1" x="1162" y="429"/>
+ <use xlink:href="#glyph0-1" x="1176" y="429"/>
+ <use xlink:href="#glyph0-1" x="1190" y="429"/>
+ <use xlink:href="#glyph0-1" x="1204" y="429"/>
+ <use xlink:href="#glyph0-1" x="1218" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 403 L 1260 403 L 1260 434 L 1232 434 Z M 1232 403 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="429"/>
+ <use xlink:href="#glyph0-45" x="1246" y="429"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 403 L 1414 403 L 1414 434 L 1260 434 Z M 1260 403 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 403 L 1428 403 L 1428 434 L 1414 434 Z M 1414 403 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 434 L 140 434 L 140 465 L 0 465 Z M 0 434 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 434 L 168 434 L 168 465 L 140 465 Z M 140 434 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-45" x="140" y="460"/>
+ <use xlink:href="#glyph0-1" x="154" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 168 434 L 182 434 L 182 465 L 168 465 Z M 168 434 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="168" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 182 434 L 266 434 L 266 465 L 182 465 Z M 182 434 "/>
+<g style="fill:rgb(53.333333%,93.72549%,53.333333%);fill-opacity:1;">
+ <use xlink:href="#glyph0-13" x="182" y="460"/>
+ <use xlink:href="#glyph0-4" x="196" y="460"/>
+ <use xlink:href="#glyph0-14" x="210" y="460"/>
+ <use xlink:href="#glyph0-9" x="224" y="460"/>
+ <use xlink:href="#glyph0-15" x="238" y="460"/>
+ <use xlink:href="#glyph0-12" x="252" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 266 434 L 448 434 L 448 465 L 266 465 Z M 266 434 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="266" y="460"/>
+ <use xlink:href="#glyph0-7" x="280" y="460"/>
+ <use xlink:href="#glyph0-1" x="294" y="460"/>
+ <use xlink:href="#glyph0-46" x="308" y="460"/>
+ <use xlink:href="#glyph0-1" x="322" y="460"/>
+ <use xlink:href="#glyph0-47" x="336" y="460"/>
+ <use xlink:href="#glyph0-48" x="350" y="460"/>
+ <use xlink:href="#glyph0-1" x="364" y="460"/>
+ <use xlink:href="#glyph0-3" x="378" y="460"/>
+ <use xlink:href="#glyph0-23" x="392" y="460"/>
+ <use xlink:href="#glyph0-29" x="406" y="460"/>
+ <use xlink:href="#glyph0-6" x="420" y="460"/>
+ <use xlink:href="#glyph0-1" x="434" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 448 434 L 532 434 L 532 465 L 448 465 Z M 448 434 "/>
+<g style="fill:rgb(57.254902%,85.098039%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-31" x="448" y="460"/>
+ <use xlink:href="#glyph0-6" x="462" y="460"/>
+ <use xlink:href="#glyph0-38" x="476" y="460"/>
+ <use xlink:href="#glyph0-4" x="490" y="460"/>
+ <use xlink:href="#glyph0-25" x="504" y="460"/>
+ <use xlink:href="#glyph0-6" x="518" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 532 434 L 546 434 L 546 465 L 532 465 Z M 532 434 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 546 434 L 588 434 L 588 465 L 546 465 Z M 546 434 "/>
+<g style="fill:rgb(37.647059%,90.588235%,87.843137%);fill-opacity:1;">
+ <use xlink:href="#glyph0-37" x="546" y="460"/>
+ <use xlink:href="#glyph0-15" x="560" y="460"/>
+ <use xlink:href="#glyph0-33" x="574" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 588 434 L 1232 434 L 1232 465 L 588 465 Z M 588 434 "/>
+<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-16" x="588" y="460"/>
+ <use xlink:href="#glyph0-1" x="602" y="460"/>
+ <use xlink:href="#glyph0-46" x="616" y="460"/>
+ <use xlink:href="#glyph0-1" x="630" y="460"/>
+ <use xlink:href="#glyph0-19" x="644" y="460"/>
+ <use xlink:href="#glyph0-5" x="658" y="460"/>
+ <use xlink:href="#glyph0-6" x="672" y="460"/>
+ <use xlink:href="#glyph0-23" x="686" y="460"/>
+ <use xlink:href="#glyph0-24" x="700" y="460"/>
+ <use xlink:href="#glyph0-50" x="714" y="460"/>
+ <use xlink:href="#glyph0-35" x="728" y="460"/>
+ <use xlink:href="#glyph0-6" x="742" y="460"/>
+ <use xlink:href="#glyph0-16" x="756" y="460"/>
+ <use xlink:href="#glyph0-6" x="770" y="460"/>
+ <use xlink:href="#glyph0-10" x="784" y="460"/>
+ <use xlink:href="#glyph0-1" x="798" y="460"/>
+ <use xlink:href="#glyph0-23" x="812" y="460"/>
+ <use xlink:href="#glyph0-25" x="826" y="460"/>
+ <use xlink:href="#glyph0-10" x="840" y="460"/>
+ <use xlink:href="#glyph0-4" x="854" y="460"/>
+ <use xlink:href="#glyph0-38" x="868" y="460"/>
+ <use xlink:href="#glyph0-6" x="882" y="460"/>
+ <use xlink:href="#glyph0-1" x="896" y="460"/>
+ <use xlink:href="#glyph0-52" x="910" y="460"/>
+ <use xlink:href="#glyph0-4" x="924" y="460"/>
+ <use xlink:href="#glyph0-5" x="938" y="460"/>
+ <use xlink:href="#glyph0-10" x="952" y="460"/>
+ <use xlink:href="#glyph0-6" x="966" y="460"/>
+ <use xlink:href="#glyph0-24" x="980" y="460"/>
+ <use xlink:href="#glyph0-16" x="994" y="460"/>
+ <use xlink:href="#glyph0-1" x="1008" y="460"/>
+ <use xlink:href="#glyph0-1" x="1022" y="460"/>
+ <use xlink:href="#glyph0-1" x="1036" y="460"/>
+ <use xlink:href="#glyph0-1" x="1050" y="460"/>
+ <use xlink:href="#glyph0-1" x="1064" y="460"/>
+ <use xlink:href="#glyph0-1" x="1078" y="460"/>
+ <use xlink:href="#glyph0-1" x="1092" y="460"/>
+ <use xlink:href="#glyph0-1" x="1106" y="460"/>
+ <use xlink:href="#glyph0-1" x="1120" y="460"/>
+ <use xlink:href="#glyph0-1" x="1134" y="460"/>
+ <use xlink:href="#glyph0-1" x="1148" y="460"/>
+ <use xlink:href="#glyph0-1" x="1162" y="460"/>
+ <use xlink:href="#glyph0-1" x="1176" y="460"/>
+ <use xlink:href="#glyph0-1" x="1190" y="460"/>
+ <use xlink:href="#glyph0-1" x="1204" y="460"/>
+ <use xlink:href="#glyph0-1" x="1218" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1232 434 L 1260 434 L 1260 465 L 1232 465 Z M 1232 434 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="1232" y="460"/>
+ <use xlink:href="#glyph0-45" x="1246" y="460"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 434 L 1414 434 L 1414 465 L 1260 465 Z M 1260 434 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 434 L 1428 434 L 1428 465 L 1414 465 Z M 1414 434 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 465 L 140 465 L 140 496 L 0 496 Z M 0 465 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 140 465 L 1260 465 L 1260 496 L 140 496 Z M 140 465 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-53" x="140" y="491"/>
+ <use xlink:href="#glyph0-41" x="154" y="491"/>
+ <use xlink:href="#glyph0-41" x="168" y="491"/>
+ <use xlink:href="#glyph0-41" x="182" y="491"/>
+ <use xlink:href="#glyph0-41" x="196" y="491"/>
+ <use xlink:href="#glyph0-41" x="210" y="491"/>
+ <use xlink:href="#glyph0-41" x="224" y="491"/>
+ <use xlink:href="#glyph0-41" x="238" y="491"/>
+ <use xlink:href="#glyph0-41" x="252" y="491"/>
+ <use xlink:href="#glyph0-41" x="266" y="491"/>
+ <use xlink:href="#glyph0-41" x="280" y="491"/>
+ <use xlink:href="#glyph0-41" x="294" y="491"/>
+ <use xlink:href="#glyph0-41" x="308" y="491"/>
+ <use xlink:href="#glyph0-41" x="322" y="491"/>
+ <use xlink:href="#glyph0-41" x="336" y="491"/>
+ <use xlink:href="#glyph0-41" x="350" y="491"/>
+ <use xlink:href="#glyph0-41" x="364" y="491"/>
+ <use xlink:href="#glyph0-41" x="378" y="491"/>
+ <use xlink:href="#glyph0-41" x="392" y="491"/>
+ <use xlink:href="#glyph0-41" x="406" y="491"/>
+ <use xlink:href="#glyph0-41" x="420" y="491"/>
+ <use xlink:href="#glyph0-41" x="434" y="491"/>
+ <use xlink:href="#glyph0-41" x="448" y="491"/>
+ <use xlink:href="#glyph0-41" x="462" y="491"/>
+ <use xlink:href="#glyph0-41" x="476" y="491"/>
+ <use xlink:href="#glyph0-41" x="490" y="491"/>
+ <use xlink:href="#glyph0-41" x="504" y="491"/>
+ <use xlink:href="#glyph0-41" x="518" y="491"/>
+ <use xlink:href="#glyph0-41" x="532" y="491"/>
+ <use xlink:href="#glyph0-41" x="546" y="491"/>
+ <use xlink:href="#glyph0-41" x="560" y="491"/>
+ <use xlink:href="#glyph0-41" x="574" y="491"/>
+ <use xlink:href="#glyph0-41" x="588" y="491"/>
+ <use xlink:href="#glyph0-41" x="602" y="491"/>
+ <use xlink:href="#glyph0-41" x="616" y="491"/>
+ <use xlink:href="#glyph0-41" x="630" y="491"/>
+ <use xlink:href="#glyph0-41" x="644" y="491"/>
+ <use xlink:href="#glyph0-41" x="658" y="491"/>
+ <use xlink:href="#glyph0-41" x="672" y="491"/>
+ <use xlink:href="#glyph0-41" x="686" y="491"/>
+ <use xlink:href="#glyph0-41" x="700" y="491"/>
+ <use xlink:href="#glyph0-41" x="714" y="491"/>
+ <use xlink:href="#glyph0-41" x="728" y="491"/>
+ <use xlink:href="#glyph0-41" x="742" y="491"/>
+ <use xlink:href="#glyph0-41" x="756" y="491"/>
+ <use xlink:href="#glyph0-41" x="770" y="491"/>
+ <use xlink:href="#glyph0-41" x="784" y="491"/>
+ <use xlink:href="#glyph0-41" x="798" y="491"/>
+ <use xlink:href="#glyph0-41" x="812" y="491"/>
+ <use xlink:href="#glyph0-41" x="826" y="491"/>
+ <use xlink:href="#glyph0-41" x="840" y="491"/>
+ <use xlink:href="#glyph0-41" x="854" y="491"/>
+ <use xlink:href="#glyph0-41" x="868" y="491"/>
+ <use xlink:href="#glyph0-41" x="882" y="491"/>
+ <use xlink:href="#glyph0-41" x="896" y="491"/>
+ <use xlink:href="#glyph0-41" x="910" y="491"/>
+ <use xlink:href="#glyph0-41" x="924" y="491"/>
+ <use xlink:href="#glyph0-41" x="938" y="491"/>
+ <use xlink:href="#glyph0-41" x="952" y="491"/>
+ <use xlink:href="#glyph0-41" x="966" y="491"/>
+ <use xlink:href="#glyph0-41" x="980" y="491"/>
+ <use xlink:href="#glyph0-41" x="994" y="491"/>
+ <use xlink:href="#glyph0-41" x="1008" y="491"/>
+ <use xlink:href="#glyph0-41" x="1022" y="491"/>
+ <use xlink:href="#glyph0-41" x="1036" y="491"/>
+ <use xlink:href="#glyph0-41" x="1050" y="491"/>
+ <use xlink:href="#glyph0-41" x="1064" y="491"/>
+ <use xlink:href="#glyph0-41" x="1078" y="491"/>
+ <use xlink:href="#glyph0-41" x="1092" y="491"/>
+ <use xlink:href="#glyph0-41" x="1106" y="491"/>
+ <use xlink:href="#glyph0-41" x="1120" y="491"/>
+ <use xlink:href="#glyph0-41" x="1134" y="491"/>
+ <use xlink:href="#glyph0-41" x="1148" y="491"/>
+ <use xlink:href="#glyph0-41" x="1162" y="491"/>
+ <use xlink:href="#glyph0-41" x="1176" y="491"/>
+ <use xlink:href="#glyph0-41" x="1190" y="491"/>
+ <use xlink:href="#glyph0-41" x="1204" y="491"/>
+ <use xlink:href="#glyph0-41" x="1218" y="491"/>
+ <use xlink:href="#glyph0-41" x="1232" y="491"/>
+ <use xlink:href="#glyph0-54" x="1246" y="491"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 1260 465 L 1414 465 L 1414 496 L 1260 496 Z M 1260 465 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 465 L 1428 465 L 1428 496 L 1414 496 Z M 1414 465 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 496 L 1414 496 L 1414 527 L 0 527 Z M 0 496 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 496 L 1428 496 L 1428 527 L 1414 527 Z M 1414 496 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 527 L 1414 527 L 1414 558 L 0 558 Z M 0 527 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 527 L 1428 527 L 1428 558 L 1414 558 Z M 1414 527 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 558 L 1414 558 L 1414 589 L 0 589 Z M 0 558 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 558 L 1428 558 L 1428 589 L 1414 589 Z M 1414 558 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 589 L 1414 589 L 1414 620 L 0 620 Z M 0 589 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 589 L 1428 589 L 1428 620 L 1414 620 Z M 1414 589 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 0 620 L 14 620 L 14 651 L 0 651 Z M 0 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 14 620 L 196 620 L 196 651 L 14 651 Z M 14 620 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="14" y="646"/>
+ <use xlink:href="#glyph0-30" x="28" y="646"/>
+ <use xlink:href="#glyph0-34" x="42" y="646"/>
+ <use xlink:href="#glyph0-10" x="56" y="646"/>
+ <use xlink:href="#glyph0-26" x="70" y="646"/>
+ <use xlink:href="#glyph0-15" x="84" y="646"/>
+ <use xlink:href="#glyph0-14" x="98" y="646"/>
+ <use xlink:href="#glyph0-1" x="112" y="646"/>
+ <use xlink:href="#glyph0-35" x="126" y="646"/>
+ <use xlink:href="#glyph0-6" x="140" y="646"/>
+ <use xlink:href="#glyph0-18" x="154" y="646"/>
+ <use xlink:href="#glyph0-5" x="168" y="646"/>
+ <use xlink:href="#glyph0-1" x="182" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 196 620 L 224 620 L 224 651 L 196 651 Z M 196 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 224 620 L 238 620 L 238 651 L 224 651 Z M 224 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 238 620 L 322 620 L 322 651 L 238 651 Z M 238 620 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-30" x="238" y="646"/>
+ <use xlink:href="#glyph0-23" x="252" y="646"/>
+ <use xlink:href="#glyph0-16" x="266" y="646"/>
+ <use xlink:href="#glyph0-10" x="280" y="646"/>
+ <use xlink:href="#glyph0-6" x="294" y="646"/>
+ <use xlink:href="#glyph0-1" x="308" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 322 620 L 406 620 L 406 651 L 322 651 Z M 322 620 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="322" y="646"/>
+ <use xlink:href="#glyph0-10" x="336" y="646"/>
+ <use xlink:href="#glyph0-24" x="350" y="646"/>
+ <use xlink:href="#glyph0-5" x="364" y="646"/>
+ <use xlink:href="#glyph0-28" x="378" y="646"/>
+ <use xlink:href="#glyph0-38" x="392" y="646"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="323" y="646"/>
+ <use xlink:href="#glyph0-10" x="337" y="646"/>
+ <use xlink:href="#glyph0-24" x="351" y="646"/>
+ <use xlink:href="#glyph0-5" x="365" y="646"/>
+ <use xlink:href="#glyph0-28" x="379" y="646"/>
+ <use xlink:href="#glyph0-38" x="393" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 406 620 L 420 620 L 420 651 L 406 651 Z M 406 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 420 620 L 448 620 L 448 651 L 420 651 Z M 420 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 448 620 L 462 620 L 462 651 L 448 651 Z M 448 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 462 620 L 644 620 L 644 651 L 462 651 Z M 462 620 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="462" y="646"/>
+ <use xlink:href="#glyph0-15" x="476" y="646"/>
+ <use xlink:href="#glyph0-18" x="490" y="646"/>
+ <use xlink:href="#glyph0-34" x="504" y="646"/>
+ <use xlink:href="#glyph0-1" x="518" y="646"/>
+ <use xlink:href="#glyph0-50" x="532" y="646"/>
+ <use xlink:href="#glyph0-1" x="546" y="646"/>
+ <use xlink:href="#glyph0-19" x="560" y="646"/>
+ <use xlink:href="#glyph0-5" x="574" y="646"/>
+ <use xlink:href="#glyph0-6" x="588" y="646"/>
+ <use xlink:href="#glyph0-23" x="602" y="646"/>
+ <use xlink:href="#glyph0-24" x="616" y="646"/>
+ <use xlink:href="#glyph0-1" x="630" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 644 620 L 728 620 L 728 651 L 644 651 Z M 644 620 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="644" y="646"/>
+ <use xlink:href="#glyph0-10" x="658" y="646"/>
+ <use xlink:href="#glyph0-24" x="672" y="646"/>
+ <use xlink:href="#glyph0-5" x="686" y="646"/>
+ <use xlink:href="#glyph0-28" x="700" y="646"/>
+ <use xlink:href="#glyph0-25" x="714" y="646"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-19" x="645" y="646"/>
+ <use xlink:href="#glyph0-10" x="659" y="646"/>
+ <use xlink:href="#glyph0-24" x="673" y="646"/>
+ <use xlink:href="#glyph0-5" x="687" y="646"/>
+ <use xlink:href="#glyph0-28" x="701" y="646"/>
+ <use xlink:href="#glyph0-25" x="715" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 728 620 L 742 620 L 742 651 L 728 651 Z M 728 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 742 620 L 770 620 L 770 651 L 742 651 Z M 742 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 770 620 L 784 620 L 784 651 L 770 651 Z M 770 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 784 620 L 840 620 L 840 651 L 784 651 Z M 784 620 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-35" x="784" y="646"/>
+ <use xlink:href="#glyph0-27" x="798" y="646"/>
+ <use xlink:href="#glyph0-14" x="812" y="646"/>
+ <use xlink:href="#glyph0-1" x="826" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 840 620 L 910 620 L 910 651 L 840 651 Z M 840 620 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-8" x="840" y="646"/>
+ <use xlink:href="#glyph0-14" x="854" y="646"/>
+ <use xlink:href="#glyph0-10" x="868" y="646"/>
+ <use xlink:href="#glyph0-6" x="882" y="646"/>
+ <use xlink:href="#glyph0-24" x="896" y="646"/>
+</g>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-8" x="841" y="646"/>
+ <use xlink:href="#glyph0-14" x="855" y="646"/>
+ <use xlink:href="#glyph0-10" x="869" y="646"/>
+ <use xlink:href="#glyph0-6" x="883" y="646"/>
+ <use xlink:href="#glyph0-24" x="897" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 910 620 L 924 620 L 924 651 L 910 651 Z M 910 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 924 620 L 952 620 L 952 651 L 924 651 Z M 924 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 952 620 L 966 620 L 966 651 L 952 651 Z M 952 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 966 620 L 1092 620 L 1092 651 L 966 651 Z M 966 620 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-22" x="966" y="646"/>
+ <use xlink:href="#glyph0-6" x="980" y="646"/>
+ <use xlink:href="#glyph0-10" x="994" y="646"/>
+ <use xlink:href="#glyph0-10" x="1008" y="646"/>
+ <use xlink:href="#glyph0-4" x="1022" y="646"/>
+ <use xlink:href="#glyph0-14" x="1036" y="646"/>
+ <use xlink:href="#glyph0-33" x="1050" y="646"/>
+ <use xlink:href="#glyph0-16" x="1064" y="646"/>
+ <use xlink:href="#glyph0-1" x="1078" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1092 620 L 1106 620 L 1106 651 L 1092 651 Z M 1092 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1106 620 L 1302 620 L 1302 651 L 1106 651 Z M 1106 620 "/>
+<g style="fill:rgb(87.843137%,90.196078%,94.117647%);fill-opacity:1;">
+ <use xlink:href="#glyph0-25" x="1106" y="646"/>
+ <use xlink:href="#glyph0-5" x="1120" y="646"/>
+ <use xlink:href="#glyph0-4" x="1134" y="646"/>
+ <use xlink:href="#glyph0-25" x="1148" y="646"/>
+ <use xlink:href="#glyph0-29" x="1162" y="646"/>
+ <use xlink:href="#glyph0-1" x="1176" y="646"/>
+ <use xlink:href="#glyph0-10" x="1190" y="646"/>
+ <use xlink:href="#glyph0-15" x="1204" y="646"/>
+ <use xlink:href="#glyph0-1" x="1218" y="646"/>
+ <use xlink:href="#glyph0-52" x="1232" y="646"/>
+ <use xlink:href="#glyph0-15" x="1246" y="646"/>
+ <use xlink:href="#glyph0-25" x="1260" y="646"/>
+ <use xlink:href="#glyph0-27" x="1274" y="646"/>
+ <use xlink:href="#glyph0-16" x="1288" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(19.607843%,19.607843%,19.607843%);fill-opacity:1;" d="M 1302 620 L 1316 620 L 1316 651 L 1302 651 Z M 1302 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1316 620 L 1358 620 L 1358 651 L 1316 651 Z M 1316 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 1414 620 L 1428 620 L 1428 651 L 1414 651 Z M 1414 620 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(11.764706%,11.764706%,11.764706%);fill-opacity:1;" d="M 1358 620 L 1414 620 L 1414 651 L 1358 651 Z M 1358 620 "/>
+<g style="fill:rgb(81.176471%,79.215686%,100%);fill-opacity:1;">
+ <use xlink:href="#glyph0-55" x="1358" y="646"/>
+ <use xlink:href="#glyph0-56" x="1372" y="646"/>
+ <use xlink:href="#glyph0-56" x="1386" y="646"/>
+ <use xlink:href="#glyph0-55" x="1400" y="646"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(52.941176%,58.823529%,69.019608%);fill-opacity:1;" d="M 434 124 L 448 124 L 448 155 L 434 155 Z M 434 124 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 0 651 L 28 651 L 28 682 L 0 682 Z M 0 651 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(14.117647%,15.686275%,21.568627%);fill-opacity:1;" d="M 28 651 L 1429 651 L 1429 682 L 28 682 Z M 28 651 "/>
+</g>
+</svg>
diff --git a/pw_console/py/BUILD.gn b/pw_console/py/BUILD.gn
index efa80ed11..b7164c95b 100644
--- a/pw_console/py/BUILD.gn
+++ b/pw_console/py/BUILD.gn
@@ -25,6 +25,7 @@ pw_python_package("py") {
sources = [
"pw_console/__init__.py",
"pw_console/__main__.py",
+ "pw_console/command_runner.py",
"pw_console/console_app.py",
"pw_console/console_prefs.py",
"pw_console/embed.py",
@@ -73,6 +74,7 @@ pw_python_package("py") {
"pw_console/yaml_config_loader_mixin.py",
]
tests = [
+ "command_runner_test.py",
"console_app_test.py",
"console_prefs_test.py",
"help_window_test.py",
diff --git a/pw_console/py/command_runner_test.py b/pw_console/py/command_runner_test.py
new file mode 100644
index 000000000..45362fe90
--- /dev/null
+++ b/pw_console/py/command_runner_test.py
@@ -0,0 +1,258 @@
+# Copyright 2022 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""Tests for pw_console.command_runner dialog."""
+
+import logging
+import re
+import unittest
+from typing import Callable, List, Tuple
+
+from unittest.mock import MagicMock
+
+from prompt_toolkit.application import create_app_session
+from prompt_toolkit.output import ColorDepth
+# inclusive-language: ignore
+from prompt_toolkit.output import DummyOutput as FakeOutput
+
+from pw_console.console_app import ConsoleApp
+from pw_console.console_prefs import ConsolePrefs
+from pw_console.text_formatting import (
+ flatten_formatted_text_tuples,
+ join_adjacent_style_tuples,
+)
+from window_manager_test import target_list_and_pane, window_pane_titles
+
+
+def _create_console_app(log_pane_count=2):
+ console_app = ConsoleApp(color_depth=ColorDepth.DEPTH_8_BIT,
+ prefs=ConsolePrefs(project_file=False,
+ project_user_file=False,
+ user_file=False))
+ console_app.prefs.reset_config()
+
+ # Setup log panes
+ loggers = {}
+ for i in range(log_pane_count):
+ loggers['LogPane-{}'.format(i)] = [
+ logging.getLogger('test_log{}'.format(i))
+ ]
+ for window_title, logger_instances in loggers.items():
+ console_app.add_log_handler(window_title, logger_instances)
+
+ return console_app
+
+
+class TestCommandRunner(unittest.TestCase):
+ """Tests for CommandRunner."""
+ def setUp(self):
+ self.maxDiff = None # pylint: disable=invalid-name
+
+ def test_flatten_menu_items(self) -> None:
+ with create_app_session(output=FakeOutput()):
+ console_app = _create_console_app(log_pane_count=2)
+ flattened_menu_items = [
+ text for text, handler in
+ console_app.command_runner.load_menu_items()
+ ]
+
+ # Check some common menu items exist.
+ self.assertIn('[File] > Open Logger', flattened_menu_items)
+ self.assertIn('[File] > Themes > UI Themes > High Contrast',
+ flattened_menu_items)
+ self.assertIn('[Help] > User Guide', flattened_menu_items)
+ self.assertIn('[Help] > Keyboard Shortcuts', flattened_menu_items)
+ # Check for log windows
+ self.assertRegex(
+ '\n'.join(flattened_menu_items),
+ re.compile(r'^\[Windows\] > .* LogPane-[0-9]+ > .*$',
+ re.MULTILINE),
+ )
+
+ def test_filter_and_highlight_matches(self) -> None:
+ """Check filtering matches and highlighting works correctly."""
+ with create_app_session(output=FakeOutput()):
+ console_app = _create_console_app(log_pane_count=2)
+ command_runner = console_app.command_runner
+
+ command_runner.filter_completions = MagicMock(
+ wraps=command_runner.filter_completions)
+ command_runner.width = 20
+
+ # Define custom completion items
+ def empty_handler() -> None:
+ return None
+
+ def get_completions() -> List[Tuple[str, Callable]]:
+ return [
+ ('[File] > Open Logger', empty_handler),
+ ('[Windows] > 1: Host Logs > Show/Hide', empty_handler),
+ ('[Windows] > 2: Device Logs > Show/Hide', empty_handler),
+ ('[Help] > User Guide', empty_handler),
+ ]
+
+ command_runner.filter_completions.assert_not_called()
+ command_runner.set_completions(window_title='Test Completions',
+ load_completions=get_completions)
+ command_runner.filter_completions.assert_called_once()
+ command_runner.filter_completions.reset_mock()
+
+ # Input field should be empty
+ self.assertEqual(command_runner.input_field.buffer.text, '')
+ # Flatten resulting formatted text
+ result_items = join_adjacent_style_tuples(
+ flatten_formatted_text_tuples(
+ command_runner.completion_fragments))
+
+ # index 0: the selected line
+ # index 1: the rest of the completions with line breaks
+ self.assertEqual(len(result_items), 2)
+ first_item_style = result_items[0][0]
+ first_item_text = result_items[0][1]
+ second_item_text = result_items[1][1]
+ # Check expected number of lines are present
+ self.assertEqual(len(first_item_text.splitlines()), 1)
+ self.assertEqual(len(second_item_text.splitlines()), 3)
+ # First line is highlighted as a selected item
+ self.assertEqual(first_item_style,
+ 'class:command-runner-selected-item')
+ self.assertIn('[File] > Open Logger', first_item_text)
+
+ # Type: file open
+ command_runner.input_field.buffer.text = 'file open'
+ self.assertEqual(command_runner.input_field.buffer.text,
+ 'file open')
+ # Run the filter
+ command_runner.filter_completions()
+ # Flatten resulting formatted text
+ result_items = join_adjacent_style_tuples(
+ flatten_formatted_text_tuples(
+ command_runner.completion_fragments))
+ # Check file and open are highlighted
+ self.assertEqual(
+ result_items[:4],
+ [
+ ('class:command-runner-selected-item', '['),
+ ('class:command-runner-selected-item '
+ 'class:command-runner-fuzzy-highlight-0 ', 'File'),
+ ('class:command-runner-selected-item', '] > '),
+ ('class:command-runner-selected-item '
+ 'class:command-runner-fuzzy-highlight-1 ', 'Open'),
+ ],
+ )
+
+ # Type: open file
+ command_runner.input_field.buffer.text = 'open file'
+ # Run the filter
+ command_runner.filter_completions()
+ result_items = join_adjacent_style_tuples(
+ flatten_formatted_text_tuples(
+ command_runner.completion_fragments))
+ # Check file and open are highlighted, the fuzzy-highlight class
+ # should be swapped.
+ self.assertEqual(
+ result_items[:4],
+ [
+ ('class:command-runner-selected-item', '['),
+ ('class:command-runner-selected-item '
+ 'class:command-runner-fuzzy-highlight-1 ', 'File'),
+ ('class:command-runner-selected-item', '] > '),
+ ('class:command-runner-selected-item '
+ 'class:command-runner-fuzzy-highlight-0 ', 'Open'),
+ ],
+ )
+
+ # Clear input
+ command_runner._reset_selected_item() # pylint: disable=protected-access
+ command_runner.filter_completions()
+ result_items = join_adjacent_style_tuples(
+ flatten_formatted_text_tuples(
+ command_runner.completion_fragments))
+ self.assertEqual(len(first_item_text.splitlines()), 1)
+ self.assertEqual(len(second_item_text.splitlines()), 3)
+
+ # Press down (select the next item)
+ command_runner._next_item() # pylint: disable=protected-access
+ # Filter and check results
+ command_runner.filter_completions()
+ result_items = join_adjacent_style_tuples(
+ flatten_formatted_text_tuples(
+ command_runner.completion_fragments))
+ self.assertEqual(len(result_items), 3)
+ # First line - not selected
+ self.assertEqual(result_items[0], ('', '[File] > Open Logger\n'))
+ # Second line - is selected
+ self.assertEqual(result_items[1],
+ ('class:command-runner-selected-item',
+ '[Windows] > 1: Host Logs > Show/Hide\n'))
+ # Third and fourth lines separated by \n - not selected
+ self.assertEqual(result_items[2],
+ ('', '[Windows] > 2: Device Logs > Show/Hide\n'
+ '[Help] > User Guide'))
+
+ def test_run_action(self) -> None:
+ """Check running an action works correctly."""
+ with create_app_session(output=FakeOutput()):
+ console_app = _create_console_app(log_pane_count=2)
+ command_runner = console_app.command_runner
+ self.assertEqual(
+ window_pane_titles(console_app.window_manager),
+ [
+ # Split 1
+ [
+ 'LogPane-1 - test_log1',
+ 'LogPane-0 - test_log0',
+ 'Python Repl - ',
+ ],
+ ],
+ )
+ command_runner.open_dialog()
+ # Set LogPane-1 as the focused window pane
+ target_list_and_pane(console_app.window_manager, 0, 0)
+
+ command_runner.input_field.buffer.text = 'move right'
+
+ # pylint: disable=protected-access
+ command_runner._make_regexes = MagicMock(
+ wraps=command_runner._make_regexes)
+ # pylint: enable=protected-access
+ command_runner.filter_completions()
+ # Filter should only be re-run if input text changed
+ command_runner.filter_completions()
+ command_runner._make_regexes.assert_called_once() # pylint: disable=protected-access
+
+ self.assertIn('[View] > Move Window Right',
+ command_runner.selected_item_text)
+ # Run the Move Window Right action
+ command_runner._run_selected_item() # pylint: disable=protected-access
+ # Dialog should be closed
+ self.assertFalse(command_runner.show_dialog)
+ # LogPane-1 should be moved to the right in it's own split
+ self.assertEqual(
+ window_pane_titles(console_app.window_manager),
+ [
+ # Split 1
+ [
+ 'LogPane-0 - test_log0',
+ 'Python Repl - ',
+ ],
+ # Split 2
+ [
+ 'LogPane-1 - test_log1',
+ ],
+ ],
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/pw_console/py/log_view_test.py b/pw_console/py/log_view_test.py
index da843166d..a21a5647d 100644
--- a/pw_console/py/log_view_test.py
+++ b/pw_console/py/log_view_test.py
@@ -43,7 +43,9 @@ def _create_log_view():
log_pane.current_log_pane_height = 10
application = MagicMock()
- application.prefs = ConsolePrefs()
+ application.prefs = ConsolePrefs(project_file=False,
+ project_user_file=False,
+ user_file=False)
application.prefs.reset_config()
log_view = LogView(log_pane, application)
return log_view, log_pane
diff --git a/pw_console/py/pw_console/command_runner.py b/pw_console/py/pw_console/command_runner.py
new file mode 100644
index 000000000..3aff8a047
--- /dev/null
+++ b/pw_console/py/pw_console/command_runner.py
@@ -0,0 +1,517 @@
+# Copyright 2022 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""CommandRunner dialog classes."""
+
+from __future__ import annotations
+import functools
+import logging
+import re
+from typing import (
+ Callable,
+ Iterable,
+ Iterator,
+ List,
+ Optional,
+ TYPE_CHECKING,
+ Tuple,
+)
+
+from prompt_toolkit.buffer import Buffer
+from prompt_toolkit.filters import Condition
+from prompt_toolkit.formatted_text import StyleAndTextTuples
+from prompt_toolkit.formatted_text.utils import fragment_list_to_text
+from prompt_toolkit.layout.utils import explode_text_fragments
+from prompt_toolkit.history import InMemoryHistory
+from prompt_toolkit.key_binding import (
+ KeyBindings,
+ KeyBindingsBase,
+ KeyPressEvent,
+)
+from prompt_toolkit.layout import (
+ AnyContainer,
+ ConditionalContainer,
+ DynamicContainer,
+ FormattedTextControl,
+ HSplit,
+ VSplit,
+ Window,
+ WindowAlign,
+)
+from prompt_toolkit.widgets import MenuItem
+from prompt_toolkit.widgets import TextArea
+
+import pw_console.widgets.border
+import pw_console.widgets.checkbox
+import pw_console.widgets.mouse_handlers
+
+if TYPE_CHECKING:
+ from pw_console.console_app import ConsoleApp
+
+_LOG = logging.getLogger(__package__)
+
+
+def flatten_menu_items(items: List[MenuItem],
+ prefix: str = '') -> Iterator[Tuple[str, Callable]]:
+ """Flatten nested prompt_toolkit MenuItems into text and callable tuples."""
+ for item in items:
+ new_text = []
+ if prefix:
+ new_text.append(prefix)
+ new_text.append(item.text)
+ new_prefix = ' > '.join(new_text)
+
+ if item.children:
+ yield from flatten_menu_items(item.children, new_prefix)
+ elif item.handler:
+ # Skip this item if it's a separator or disabled.
+ if item.text == '-' or item.disabled:
+ continue
+ yield (new_prefix, item.handler)
+
+
+def highlight_matches(
+ regexes: Iterable[re.Pattern],
+ line_fragments: StyleAndTextTuples) -> StyleAndTextTuples:
+ """Highlight regex matches in prompt_toolkit FormattedTextTuples."""
+ line_text = fragment_list_to_text(line_fragments)
+ exploded_fragments = explode_text_fragments(line_fragments)
+
+ def apply_highlighting(fragments: StyleAndTextTuples,
+ index: int,
+ matching_regex_index: int = 0) -> None:
+ # Expand all fragments and apply the highlighting style.
+ old_style, _text, *_ = fragments[index]
+ # There are 6 fuzzy-highlight styles defined in style.py. Get an index
+ # from 0-5 to use one style after the other in turn.
+ style_index = matching_regex_index % 6
+ fragments[index] = (
+ old_style +
+ f' class:command-runner-fuzzy-highlight-{style_index} ',
+ fragments[index][1],
+ )
+
+ # Highlight each non-overlapping search match.
+ for regex_i, regex in enumerate(regexes):
+ for match in regex.finditer(line_text):
+ for fragment_i in range(match.start(), match.end()):
+ apply_highlighting(exploded_fragments, fragment_i, regex_i)
+
+ return exploded_fragments
+
+
+class CommandRunner:
+ """CommandRunner dialog box."""
+
+ # pylint: disable=too-many-instance-attributes
+
+ def __init__(
+ self,
+ application: ConsoleApp,
+ window_title: str = None,
+ load_completions: Optional[Callable[[],
+ List[Tuple[str,
+ Callable]]]] = None,
+ width: int = 80,
+ height: int = 10):
+ # Parent pw_console application
+ self.application = application
+ # Visibility toggle
+ self.show_dialog = False
+ # Tracks the last focused container, to enable restoring focus after
+ # closing the dialog.
+ self.last_focused_pane = None
+
+ # List of all possible completion items
+ self.completions: List[Tuple[str, Callable]] = []
+ # Formatted text fragments of matched items
+ self.completion_fragments: List[StyleAndTextTuples] = []
+
+ # Current selected item tracking variables
+ self.selected_item: int = 0
+ self.selected_item_text: str = ''
+ self.selected_item_handler: Optional[Callable] = None
+ # Previous input text
+ self.last_input_field_text: str = 'EMPTY'
+ # Previous selected item
+ self.last_selected_item: int = 0
+
+ # Dialog width, height and title
+ self.width = width
+ self.height = height
+ self.window_title: str
+
+ # Callable to fetch completion items
+ self.load_completions: Callable[[], List[Tuple[str, Callable]]]
+
+ # Command runner text input field
+ self.input_field = TextArea(
+ prompt=[
+ ('class:command-runner-setting', '> ',
+ functools.partial(pw_console.widgets.mouse_handlers.on_click,
+ self.focus_self))
+ ],
+ focusable=True,
+ focus_on_click=True,
+ scrollbar=False,
+ multiline=False,
+ height=1,
+ dont_extend_height=True,
+ dont_extend_width=False,
+ accept_handler=self._command_accept_handler,
+ history=InMemoryHistory(),
+ )
+ # Set additional keybindings for the input field
+ self.input_field.control.key_bindings = self._create_key_bindings()
+
+ # Container for the Cancel and Run buttons
+ input_field_buttons_container = ConditionalContainer(
+ Window(
+ content=FormattedTextControl(
+ self._get_input_field_button_fragments,
+ focusable=False,
+ show_cursor=False,
+ ),
+ height=1,
+ align=WindowAlign.RIGHT,
+ dont_extend_width=True,
+ ),
+ filter=Condition(lambda: self.content_width() > 40),
+ )
+
+ # Container for completion matches
+ command_items_window = Window(
+ content=FormattedTextControl(
+ self.render_completion_items,
+ show_cursor=False,
+ focusable=False,
+ ),
+ align=WindowAlign.LEFT,
+ dont_extend_width=False,
+ height=self.height,
+ )
+
+ # Main content HSplit
+ self.command_runner_content = HSplit(
+ [
+ # Input field and buttons on the same line
+ VSplit([
+ self.input_field,
+ input_field_buttons_container,
+ ]),
+ # Completion items below
+ command_items_window,
+ ],
+ style='class:command-runner class:theme-fg-default',
+ )
+
+ # Set completions if passed in.
+ self.set_completions(window_title, load_completions)
+
+ # bordered_content wraps the above command_runner_content in a border.
+ self.bordered_content: AnyContainer
+ # Root prompt_toolkit container
+ self.container = ConditionalContainer(
+ DynamicContainer(lambda: self.bordered_content),
+ filter=Condition(lambda: self.show_dialog),
+ )
+
+ def _create_bordered_content(self) -> None:
+ """Wrap self.command_runner_content in a border."""
+ # This should be called whenever the window_title changes.
+ self.bordered_content = pw_console.widgets.border.create_border(
+ self.command_runner_content,
+ title=self.window_title,
+ border_style='class:command-runner-border',
+ left_margin_columns=1,
+ right_margin_columns=1,
+ )
+
+ def __pt_container__(self) -> AnyContainer:
+ """Return the prompt_toolkit root container for this dialog."""
+ return self.container
+
+ def _create_key_bindings(self) -> KeyBindingsBase:
+ """Create additional key bindings for the command input field."""
+ key_bindings = KeyBindings()
+
+ @key_bindings.add('escape')
+ @key_bindings.add('c-c')
+ def _cancel(_event: KeyPressEvent) -> None:
+ """Clear input or close command."""
+ if self._get_input_field_text() != '':
+ self._reset_selected_item()
+ return
+
+ self.close_dialog()
+
+ @key_bindings.add('up')
+ @key_bindings.add('s-tab')
+ def _select_previous_item(_event: KeyPressEvent) -> None:
+ """Select previous completion item."""
+ self._previous_item()
+
+ @key_bindings.add('down')
+ @key_bindings.add('tab')
+ def _select_next_item(_event: KeyPressEvent) -> None:
+ """Select next completion item."""
+ self._next_item()
+
+ return key_bindings
+
+ def content_width(self) -> int:
+ """Return the smaller value of self.width and the available width."""
+ window_manager_width = (
+ self.application.window_manager.current_window_manager_width)
+ if not window_manager_width:
+ window_manager_width = self.width
+ return min(self.width, window_manager_width)
+
+ def focus_self(self) -> None:
+ self.application.layout.focus(self)
+
+ def close_dialog(self) -> None:
+ """Close command runner dialog box."""
+ self.show_dialog = False
+ self._reset_selected_item()
+
+ # Restore original focus if possible.
+ if self.last_focused_pane:
+ self.application.focus_on_container(self.last_focused_pane)
+ else:
+ # Fallback to focusing on the main menu.
+ self.application.focus_main_menu()
+
+ def open_dialog(self) -> None:
+ self.show_dialog = True
+ self.last_focused_pane = self.application.focused_window()
+ self.focus_self()
+ self.application.redraw_ui()
+
+ def set_completions(
+ self,
+ window_title: str = None,
+ load_completions: Optional[Callable[[], List[Tuple[str,
+ Callable]]]] = None,
+ ) -> None:
+ """Set window title and callable to fetch possible completions.
+
+ Call this function whenever new completion items need to be loaded.
+ """
+ self.window_title = window_title if window_title else 'Menu Items'
+ self.load_completions = (load_completions
+ if load_completions else self.load_menu_items)
+ self._reset_selected_item()
+
+ self.completions = []
+ self.completion_fragments = []
+
+ # Load and filter completions
+ self.filter_completions()
+
+ # (Re)create the bordered content with the window_title set.
+ self._create_bordered_content()
+
+ def reload_completions(self) -> None:
+ self.completions = self.load_completions()
+
+ def load_menu_items(self) -> List[Tuple[str, Callable]]:
+ # pylint: disable=no-self-use
+ return list(flatten_menu_items(self.application.menu_items))
+
+ def _get_input_field_text(self) -> str:
+ return self.input_field.buffer.text
+
+ def _make_regexes(self, input_text) -> List[re.Pattern]:
+ # pylint: disable=no-self-use
+ regexes: List[re.Pattern] = []
+ if not input_text:
+ return regexes
+
+ text_tokens = input_text.split(' ')
+ if len(text_tokens) > 0:
+ regexes = [
+ re.compile(re.escape(text), re.IGNORECASE)
+ for text in text_tokens
+ ]
+
+ return regexes
+
+ def _matches_orderless(self, regexes: List[re.Pattern], text) -> bool:
+ """Check if all supplied regexs match the input text."""
+ # pylint: disable=no-self-use
+ return all(regex.search(text) for regex in regexes)
+
+ def filter_completions(self) -> None:
+ """Filter completion items if new user input detected."""
+ if not self.input_text_changed() and not self.selected_item_changed():
+ return
+
+ self.reload_completions()
+
+ input_text = self._get_input_field_text()
+ self.completion_fragments = []
+
+ regexes = self._make_regexes(input_text)
+ check_match = self._matches_orderless
+
+ i = 0
+ for text, handler in self.completions:
+ if not (input_text == '' or check_match(regexes, text)):
+ continue
+ style = ''
+ if i == self.selected_item:
+ style = 'class:command-runner-selected-item'
+ self.selected_item_text = text
+ self.selected_item_handler = handler
+ text = text.ljust(self.content_width())
+ fragments: StyleAndTextTuples = highlight_matches(
+ regexes, [(style, text + '\n')])
+ self.completion_fragments.append(fragments)
+ i += 1
+
+ def input_text_changed(self) -> bool:
+ """Return True if text in the input field has changed."""
+ input_text = self._get_input_field_text()
+ if input_text != self.last_input_field_text:
+ self.last_input_field_text = input_text
+ self.selected_item = 0
+ return True
+ return False
+
+ def selected_item_changed(self) -> bool:
+ """Check if the user pressed up or down to select a different item."""
+ return self.last_selected_item != self.selected_item
+
+ def _next_item(self) -> None:
+ self.last_selected_item = self.selected_item
+ self.selected_item = min(
+ # Don't move past the height of the window or the length of possible
+ # items.
+ min(self.height, len(self.completion_fragments)) - 1,
+ self.selected_item + 1)
+ self.application.redraw_ui()
+
+ def _previous_item(self) -> None:
+ self.last_selected_item = self.selected_item
+ self.selected_item = max(0, self.selected_item - 1)
+ self.application.redraw_ui()
+
+ def _get_input_field_button_fragments(self) -> StyleAndTextTuples:
+ # Mouse handlers
+ focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
+ self.focus_self)
+ cancel = functools.partial(pw_console.widgets.mouse_handlers.on_click,
+ self.close_dialog)
+ select_item = functools.partial(
+ pw_console.widgets.mouse_handlers.on_click,
+ self._run_selected_item)
+
+ separator_text = ('', ' ', focus)
+
+ # Default button style
+ button_style = 'class:toolbar-button-inactive'
+
+ fragments: StyleAndTextTuples = []
+
+ # Cancel button
+ fragments.extend(
+ pw_console.widgets.checkbox.to_keybind_indicator(
+ key='Ctrl-c',
+ description='Cancel',
+ mouse_handler=cancel,
+ base_style=button_style,
+ ))
+ fragments.append(separator_text)
+
+ # Run button
+ fragments.extend(
+ pw_console.widgets.checkbox.to_keybind_indicator(
+ 'Enter', 'Run', select_item, base_style=button_style))
+ return fragments
+
+ def render_completion_items(self) -> StyleAndTextTuples:
+ """Render completion items."""
+ fragments: StyleAndTextTuples = []
+
+ # Update completions if any state change since the last render (new text
+ # entered or arrow keys pressed).
+ self.filter_completions()
+
+ for completion_item in self.completion_fragments:
+ fragments.extend(completion_item)
+
+ return fragments
+
+ def _reset_selected_item(self) -> None:
+ self.selected_item = 0
+ self.last_selected_item = 0
+ self.selected_item_text = ''
+ self.selected_item_handler = None
+ self.last_input_field_text = 'EMPTY'
+ self.input_field.buffer.reset()
+
+ def _run_selected_item(self) -> None:
+ """Run the selected action."""
+ if not self.selected_item_handler:
+ return
+ # Save the selected item handler. This is reset by self.close_dialog()
+ handler = self.selected_item_handler
+
+ # Depending on what action is run, the command runner dialog may need to
+ # be closed, left open, or closed before running the selected action.
+ close_dialog = True
+ close_dialog_first = False
+
+ # Actions that launch new command runners, close_dialog should not run.
+ for command_text in [
+ '[File] > Open Logger',
+ ]:
+ if command_text in self.selected_item_text:
+ close_dialog = False
+ break
+
+ # Actions that change what is in focus should be run after closing the
+ # command runner dialog.
+ for command_text in [
+ '[View] > Focus Next Window/Tab',
+ '[View] > Focus Prev Window/Tab',
+ # All help menu entries open popup windows.
+ '[Help] > ',
+ # This focuses on a save dialog bor.
+ 'Save/Export a copy',
+ ]:
+ if command_text in self.selected_item_text:
+ close_dialog_first = True
+ break
+
+ # Close first if needed
+ if close_dialog and close_dialog_first:
+ self.close_dialog()
+
+ # Run the selected item handler
+ handler()
+
+ # If not already closed earlier.
+ if close_dialog and not close_dialog_first:
+ self.close_dialog()
+
+ def _command_accept_handler(self, _buff: Buffer) -> bool:
+ """Function run when pressing Enter in the command runner input box."""
+ # If at least one match is available
+ if len(self.completion_fragments) > 0:
+ self._run_selected_item()
+ # Erase input text
+ return False
+ # Keep input text
+ return True
diff --git a/pw_console/py/pw_console/console_app.py b/pw_console/py/pw_console/console_app.py
index d988dd9e6..78939de2c 100644
--- a/pw_console/py/pw_console/console_app.py
+++ b/pw_console/py/pw_console/console_app.py
@@ -21,7 +21,7 @@ import os
from pathlib import Path
import sys
from threading import Thread
-from typing import Callable, Iterable, Optional, Union
+from typing import Any, Callable, Iterable, List, Optional, Tuple, Union
from jinja2 import Environment, FileSystemLoader, make_logging_undefined
from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
@@ -56,6 +56,7 @@ from ptpython.key_bindings import ( # type: ignore
from pw_console.console_prefs import ConsolePrefs
from pw_console.help_window import HelpWindow
+from pw_console.command_runner import CommandRunner
import pw_console.key_bindings
from pw_console.log_pane import LogPane
from pw_console.log_store import LogStore
@@ -123,7 +124,7 @@ def get_default_colordepth(
class ConsoleApp:
"""The main ConsoleApp class that glues everything together."""
- # pylint: disable=too-many-instance-attributes
+ # pylint: disable=too-many-instance-attributes,too-many-public-methods
def __init__(
self,
global_vars=None,
@@ -187,10 +188,10 @@ class ConsoleApp:
self.message.extend(
pw_console.widgets.checkbox.to_keybind_indicator(
- 'F1',
- 'Help',
+ 'Ctrl-p',
+ 'Search Menu',
functools.partial(pw_console.widgets.mouse_handlers.on_click,
- self.user_guide_window.toggle_display),
+ self.open_command_runner_main_menu),
base_style='class:toolbar-button-inactive',
))
# One space separator
@@ -241,63 +242,77 @@ class ConsoleApp:
# Create help window text based global key_bindings and active panes.
self._update_help_window()
+ self.command_runner = CommandRunner(
+ self,
+ width=self.prefs.command_runner_width,
+ height=self.prefs.command_runner_height,
+ )
+
+ self.floats = [
+ # Top message bar
+ Float(
+ content=FloatingMessageBar(self),
+ top=0,
+ right=0,
+ height=1,
+ ),
+ # Centered floating help windows
+ Float(
+ content=self.app_help_window,
+ top=2,
+ bottom=2,
+ # Callable to get width
+ width=self.app_help_window.content_width,
+ ),
+ Float(
+ content=self.user_guide_window,
+ top=2,
+ bottom=2,
+ # Callable to get width
+ width=self.user_guide_window.content_width,
+ ),
+ Float(
+ content=self.keybind_help_window,
+ top=2,
+ bottom=2,
+ # Callable to get width
+ width=self.keybind_help_window.content_width,
+ ),
+ # Completion menu that can overlap other panes since it lives in
+ # the top level Float container.
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=ConditionalContainer(
+ content=CompletionsMenu(
+ scroll_offset=(lambda: self.pw_ptpython_repl.
+ completion_menu_scroll_offset),
+ max_height=16,
+ ),
+ # Only show our completion if ptpython's is disabled.
+ filter=Condition(
+ lambda: self.pw_ptpython_repl.completion_visualisation
+ == CompletionVisualisation.NONE),
+ ),
+ ),
+ Float(
+ content=self.command_runner,
+ # Callable to get width
+ width=self.command_runner.content_width,
+ **self.prefs.command_runner_position,
+ ),
+ Float(
+ content=self.quit_dialog,
+ top=2,
+ left=2,
+ ),
+ ]
+
# prompt_toolkit root container.
self.root_container = MenuContainer(
body=self.window_manager.create_root_container(),
menu_items=self.menu_items,
- floats=[
- # Top message bar
- Float(
- content=FloatingMessageBar(self),
- top=0,
- right=0,
- height=1,
- ),
- # Centered floating help windows
- Float(
- content=self.app_help_window,
- top=2,
- bottom=2,
- # Callable to get width
- width=self.app_help_window.content_width,
- ),
- Float(
- content=self.user_guide_window,
- top=2,
- bottom=2,
- # Callable to get width
- width=self.user_guide_window.content_width,
- ),
- Float(
- content=self.keybind_help_window,
- top=2,
- bottom=2,
- # Callable to get width
- width=self.keybind_help_window.content_width,
- ),
- Float(
- content=self.quit_dialog,
- top=2,
- left=2,
- ),
- # Completion menu that can overlap other panes since it lives in
- # the top level Float container.
- Float(
- xcursor=True,
- ycursor=True,
- content=ConditionalContainer(
- content=CompletionsMenu(
- scroll_offset=(lambda: self.pw_ptpython_repl.
- completion_menu_scroll_offset),
- max_height=16,
- ),
- # Only show our completion if ptpython's is disabled.
- filter=Condition(lambda: self.pw_ptpython_repl.
- completion_visualisation ==
- CompletionVisualisation.NONE),
- ),
- ),
- ],
+ floats=self.floats,
)
# NOTE: ptpython stores it's completion menus in this HSplit:
@@ -324,7 +339,6 @@ class ConsoleApp:
# Create the prompt_toolkit Application instance.
self.application: Application = Application(
layout=self.layout,
- after_render=self.run_after_render_hooks,
key_bindings=merge_key_bindings([
# Pull key bindings from ptpython
load_python_bindings(self.pw_ptpython_repl),
@@ -393,24 +407,37 @@ class ConsoleApp:
self.menu_items = self._create_menu_items()
self.root_container.menu_items = self.menu_items
- def _create_logger_submenu(self):
- submenu = [
- MenuItem(
+ def open_command_runner_main_menu(self) -> None:
+ self.command_runner.set_completions()
+ if not self.command_runner_is_open():
+ self.command_runner.open_dialog()
+
+ def open_command_runner_loggers(self) -> None:
+ self.command_runner.set_completions(
+ window_title='Open Logger',
+ load_completions=self._create_logger_completions)
+ if not self.command_runner_is_open():
+ self.command_runner.open_dialog()
+
+ def _create_logger_completions(self) -> List[Tuple[str, Callable]]:
+ completions: List[Tuple[str, Callable]] = [
+ (
'root',
- handler=functools.partial(self.open_new_log_pane_for_logger,
- '',
- window_title='root'),
- )
+ functools.partial(self.open_new_log_pane_for_logger,
+ '',
+ window_title='root'),
+ ),
]
+
all_logger_names = sorted([logger.name for logger in all_loggers()])
+
for logger_name in all_logger_names:
- submenu.append(
- MenuItem(
- logger_name,
- handler=functools.partial(
- self.open_new_log_pane_for_logger, logger_name),
- ))
- return submenu
+ completions.append((
+ logger_name,
+ functools.partial(self.open_new_log_pane_for_logger,
+ logger_name),
+ ))
+ return completions
def _create_menu_items(self):
themes_submenu = [
@@ -460,7 +487,7 @@ class ConsoleApp:
'[File]',
children=[
MenuItem('Open Logger',
- children=self._create_logger_submenu()),
+ handler=self.open_command_runner_loggers),
MenuItem(
'Log Table View',
children=[
@@ -526,6 +553,11 @@ class ConsoleApp:
MenuItem('Paste to Python Input',
handler=self.repl_pane.
paste_system_clipboard_to_input_buffer),
+ MenuItem('-'),
+ MenuItem('Copy all Python Output',
+ handler=self.repl_pane.copy_all_output_text),
+ MenuItem('Copy all Python Input',
+ handler=self.repl_pane.copy_all_input_text),
],
),
]
@@ -629,7 +661,13 @@ class ConsoleApp:
def focus_on_container(self, pane):
"""Set application focus to a specific container."""
- self.application.layout.focus(pane)
+ # Try to focus on the given pane
+ try:
+ self.application.layout.focus(pane)
+ except ValueError:
+ # If the container can't be focused, focus on the first visible
+ # window pane.
+ self.window_manager.focus_first_visible_pane()
def toggle_light_theme(self):
"""Toggle light and dark theme colors."""
@@ -706,12 +744,6 @@ class ConsoleApp:
asyncio.set_event_loop(self.user_code_loop)
self.user_code_loop.run_forever()
- def run_after_render_hooks(self, *unused_args, **unused_kwargs):
- """Run each active pane's `after_render_hook` if defined."""
- for pane in self.window_manager.active_panes():
- if hasattr(pane, 'after_render_hook'):
- pane.after_render_hook()
-
def start_user_code_thread(self):
"""Create a thread for running user code so the UI isn't blocked."""
thread = Thread(target=self._user_code_thread_entry,
@@ -760,16 +792,24 @@ class ConsoleApp:
"""Return the currently focused window."""
return self.application.layout.current_window
+ def command_runner_is_open(self) -> bool:
+ return self.command_runner.show_dialog
+
+ def command_runner_last_focused_pane(self) -> Any:
+ return self.command_runner.last_focused_pane
+
def modal_window_is_open(self):
"""Return true if any modal window or dialog is open."""
if self.app_help_text:
return (self.app_help_window.show_window
or self.keybind_help_window.show_window
or self.user_guide_window.show_window
- or self.quit_dialog.show_dialog)
+ or self.quit_dialog.show_dialog
+ or self.command_runner.show_dialog)
return (self.keybind_help_window.show_window
or self.user_guide_window.show_window
- or self.quit_dialog.show_dialog)
+ or self.quit_dialog.show_dialog
+ or self.command_runner.show_dialog)
def exit_console(self):
"""Quit the console prompt_toolkit application UI."""
@@ -787,22 +827,12 @@ class ConsoleApp:
if test_mode:
background_log_task = asyncio.create_task(self.log_forever())
- background_menu_updater_task = asyncio.create_task(
- self.background_menu_updater())
try:
unused_result = await self.application.run_async(
set_exception_handler=True)
finally:
if test_mode:
background_log_task.cancel()
- background_menu_updater_task.cancel()
-
- async def background_menu_updater(self):
- """Periodically update main menu items to capture new logger names."""
- while True:
- await asyncio.sleep(30)
- _LOG.debug('Update main menu items')
- self.update_menu_items()
async def log_forever(self):
"""Test mode async log generator coroutine that runs forever."""
diff --git a/pw_console/py/pw_console/console_prefs.py b/pw_console/py/pw_console/console_prefs.py
index a7d1c7bce..70ac3bef3 100644
--- a/pw_console/py/pw_console/console_prefs.py
+++ b/pw_console/py/pw_console/console_prefs.py
@@ -15,7 +15,7 @@
import os
from pathlib import Path
-from typing import List, Union
+from typing import Dict, List, Union
from pw_console.style import get_theme_colors
from pw_console.yaml_config_loader_mixin import YamlConfigLoaderMixin
@@ -42,6 +42,13 @@ _DEFAULT_CONFIG = {
# Window arrangement
'windows': {},
'window_column_split_method': 'vertical',
+ 'command_runner': {
+ 'width': 80,
+ 'height': 10,
+ 'position': {
+ 'top': 3
+ },
+ },
}
_DEFAULT_PROJECT_FILE = Path('$PW_PROJECT_ROOT/.pw_console.yaml')
@@ -203,6 +210,24 @@ class ConsolePrefs(YamlConfigLoaderMixin):
return list(column_type for column_type in self.windows.keys())
@property
+ def command_runner_position(self) -> Dict[str, int]:
+ position = self._config.get('command_runner',
+ {}).get('position', {'top': 3})
+ return {
+ key: value
+ for key, value in position.items()
+ if key in ['top', 'bottom', 'left', 'right']
+ }
+
+ @property
+ def command_runner_width(self) -> int:
+ return self._config.get('command_runner', {}).get('width', 80)
+
+ @property
+ def command_runner_height(self) -> int:
+ return self._config.get('command_runner', {}).get('height', 10)
+
+ @property
def unique_window_titles(self) -> set:
titles = []
for window_list_title, column in self.windows.items():
diff --git a/pw_console/py/pw_console/docs/user_guide.rst b/pw_console/py/pw_console/docs/user_guide.rst
index 67baef164..7e0f4eadf 100644
--- a/pw_console/py/pw_console/docs/user_guide.rst
+++ b/pw_console/py/pw_console/docs/user_guide.rst
@@ -5,7 +5,9 @@ User Guide
.. seealso::
- This guide can be viewed online at: https://pigweed.dev/pw_console/
+ This guide can be viewed online at:
+ https://pigweed.dev/pw_console/py/pw_console/docs/user_guide.html
+
The Pigweed Console provides a Python repl (read eval print loop) and log viewer
in a single-window terminal based interface.
@@ -27,9 +29,11 @@ There are a few ways to exit the Pigweed Console user interface:
1. Click the :guilabel:`[File]` menu and then :guilabel:`Exit`.
2. Type ``quit`` or ``exit`` in the Python Input window and press :kbd:`Enter`.
3. Press :kbd:`Ctrl-d` once to show the quit confirmation dialog. From there
- pressing :kbd:`Ctrl-d` a second time or :kbd:`y` will exit.
-4. Pressing :kbd:`Ctrl-x` quickly followed by :kbd:`Ctrl-c` will exit without
+ press :kbd:`Ctrl-d` a second time or :kbd:`y` will exit.
+4. Press :kbd:`Ctrl-x` quickly followed by :kbd:`Ctrl-c` will exit without
confirmation.
+5. Press :kbd:`Ctrl-p` to search for commands, type ``exit``, then press
+ :kbd:`Enter`.
Interface Layout
@@ -64,8 +68,36 @@ mouse wheel should work too. This requires that your terminal is able to send
mouse events.
-Main Menu Navigation with the Keyboard
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Navigation with the Keyboard
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main menu can be searched by pressing :kbd:`Ctrl-p`. This opens a fuzzy
+search box containing all main menu item actions.
+
+Words separated by spaces are used to narrow down the match results. The order
+each word is entered does not matter.
+
+.. figure:: /pw_console/images/command_runner_main_menu.svg
+ :alt: Main menu item search dialog.
+
+============================================ =====================
+Function Keys
+============================================ =====================
+Open main menu search :kbd:`Ctrl-p`
+Cancel search :kbd:`Ctrl-c`
+Run selected item :kbd:`Enter`
+
+Select next item :kbd:`Tab`
+ :kbd:`Down`
+Select previous item :kbd:`Shift-Tab`
+ :kbd:`Up`
+============================================ =====================
+
+Switching Focus
+~~~~~~~~~~~~~~~
+
+Clicking on any window will focus on it. Alternatively, the key bindings below
+will switch focus.
============================================ =====================
Function Keys
@@ -189,15 +221,13 @@ Here is a view of the search bar:
::
- +-------------------------------------------------------------------------------+
- | Enter : Search Ctrl-Alt-f : Add Filter Ctrl-Alt-r : Clear Filters |
- | Search Ctrl-t : Column:All Ctrl-v : [ ] Invert Ctrl-n : Matcher:REGEX |
- | / |
- +-------------------------------------------------------------------------------+
+ +--------------------------------------------------------------------------+
+ | Search Column:All Ctrl-t [ ] Invert Ctrl-v Matcher:REGEX Ctrl-n |
+ | / Search Enter Cancel Ctrl-c |
+ +--------------------------------------------------------------------------+
Across the top are various functions with keyboard shortcuts listed. Each of
-these are clickable with the mouse. The second line shows configurable search
-parameters.
+these are clickable with the mouse.
**Search Parameters**
@@ -618,15 +648,14 @@ Example Config
- metadata1
- metadata2
- # If True, any metadata field not listed above in 'column_order' will be hidden in table view.
+ # If True, any metadata field not listed above in 'column_order'
+ # will be hidden in table view.
column_order_omit_unspecified_columns: False
# Unique Colors for Column Values
# Color format: 'bg:#BG-HEX #FG-HEX STYLE'
# All parts are optional.
# Empty strings will leave styling unchanged.
- # See prompt_toolkit style format docs here:
- # https://python-prompt-toolkit.readthedocs.io/en/latest/pages/advanced_topics/styling.html
column_colors:
# Column name
time:
@@ -670,7 +699,8 @@ Example Config
# Second window column
Split 2 tabbed:
- # This is a duplicate of the existing 'Device Logs' window with a new title.
+ # This is a duplicate of the existing 'Device Logs' window.
+ # The title is 'NEW DEVICE'
NEW DEVICE:
duplicate_of: Device Logs
# Log filters are defined here
@@ -713,6 +743,17 @@ Example Config
all:
regex: 'Apple.*USB'
+ # Command Runner dialog size and position
+ command_runner:
+ width: 80
+ height: 10
+ position:
+ top: 3 # 3 lines below the top edge of the screen
+ # Alternatively one of these options can be used instead:
+ # bottom: 2 # 2 lines above the bottom edge of the screen
+ # left: 2 # 2 lines away from the left edge of the screen
+ # right: 2 # 2 lines away from the right edge of the screen
+
Known Issues
------------
@@ -721,7 +762,8 @@ Log Window
~~~~~~~~~~
- Tab character rendering will not work in the log pane view. They will
- appear as ``^I`` since prompt_toolkit can't render them. See this issue for details:
+ appear as ``^I`` since prompt_toolkit can't render them. See this issue for
+ details:
https://github.com/prompt-toolkit/python-prompt-toolkit/issues/556
diff --git a/pw_console/py/pw_console/help_window.py b/pw_console/py/pw_console/help_window.py
index 758a5f68f..ccb6d0302 100644
--- a/pw_console/py/pw_console/help_window.py
+++ b/pw_console/py/pw_console/help_window.py
@@ -203,9 +203,16 @@ class HelpWindow(ConditionalContainer):
scrollbar_padding = 1
scrollbar_width = 1
- return self.max_line_length + (left_side_frame_and_padding_width +
- right_side_frame_and_padding_width +
- scrollbar_padding + scrollbar_width)
+ desired_width = self.max_line_length + (
+ left_side_frame_and_padding_width +
+ right_side_frame_and_padding_width + scrollbar_padding +
+ scrollbar_width)
+
+ window_manager_width = (
+ self.application.window_manager.current_window_manager_width)
+ if not window_manager_width:
+ window_manager_width = 80
+ return min(desired_width, window_manager_width)
def load_user_guide(self):
rstdoc = Path(__file__).parent / 'docs/user_guide.rst'
diff --git a/pw_console/py/pw_console/key_bindings.py b/pw_console/py/pw_console/key_bindings.py
index cec1f613b..22e053de5 100644
--- a/pw_console/py/pw_console/key_bindings.py
+++ b/pw_console/py/pw_console/key_bindings.py
@@ -48,6 +48,13 @@ def create_key_bindings(console_app):
# F2 is ptpython settings
# F3 is ptpython history
+ @bindings.add(
+ 'c-p',
+ filter=Condition(lambda: not console_app.modal_window_is_open()))
+ def show_command_runner(event):
+ """Open command runner window."""
+ console_app.open_command_runner_main_menu()
+
@bindings.add('c-left')
def app_focus_previous(event):
"""Move focus to the previous widget."""
diff --git a/pw_console/py/pw_console/log_pane.py b/pw_console/py/pw_console/log_pane.py
index 79ca5026b..620dd29f6 100644
--- a/pw_console/py/pw_console/log_pane.py
+++ b/pw_console/py/pw_console/log_pane.py
@@ -466,7 +466,7 @@ class LogPane(WindowPane):
else:
self._pane_subtitle = self._pane_subtitle + ', ' + text
- def pane_subtitle(self):
+ def pane_subtitle(self) -> str:
if not self._pane_subtitle:
return ', '.join(self.log_view.log_store.channel_counts.keys())
logger_names = self._pane_subtitle.split(', ')
@@ -550,7 +550,7 @@ class LogPane(WindowPane):
# Menu separator
('-', None),
(
- 'Save a copy',
+ 'Save/Export a copy',
self.start_saveas,
),
('-', None),
@@ -585,7 +585,7 @@ class LogPane(WindowPane):
]
if self.is_a_duplicate:
options += [(
- 'Remove pane',
+ 'Remove/Delete pane',
functools.partial(self.application.window_manager.remove_pane,
self),
)]
@@ -603,7 +603,7 @@ class LogPane(WindowPane):
self.log_view.apply_filter,
),
(
- 'Reset active filters',
+ 'Clear/Reset active filters',
self.log_view.clear_filters,
),
]
diff --git a/pw_console/py/pw_console/repl_pane.py b/pw_console/py/pw_console/repl_pane.py
index 97a8078b8..08ef96cd0 100644
--- a/pw_console/py/pw_console/repl_pane.py
+++ b/pw_console/py/pw_console/repl_pane.py
@@ -277,7 +277,8 @@ class ReplPane(WindowPane):
is_checkbox=True,
checked=lambda: self.wrap_output_lines))
results_toolbar.add_button(
- ToolbarButton('Ctrl-Alt-c', 'Copy All Output', self.copy_text))
+ ToolbarButton('Ctrl-Alt-c', 'Copy All Output',
+ self.copy_all_output_text))
results_toolbar.add_button(
ToolbarButton('Ctrl-c', 'Copy Selected Text',
self.copy_output_selection))
@@ -297,11 +298,16 @@ class ReplPane(WindowPane):
clipboard_data = self.pw_ptpython_repl.default_buffer.copy_selection()
self.application.application.clipboard.set_data(clipboard_data)
- def copy_text(self):
- """Copy visible text in this window pane to the system clipboard."""
+ def copy_all_output_text(self):
+ """Copy all text in the Python output to the system clipboard."""
self.application.application.clipboard.set_text(
self.output_field.buffer.text)
+ def copy_all_input_text(self):
+ """Copy all text in the Python input to the system clipboard."""
+ self.application.application.clipboard.set_text(
+ self.pw_ptpython_repl.default_buffer.text)
+
# pylint: disable=no-self-use
def get_all_key_bindings(self) -> List:
"""Return all keybinds for this plugin."""
@@ -320,9 +326,6 @@ class ReplPane(WindowPane):
def get_all_menu_options(self):
return []
- def after_render_hook(self):
- """Run tasks after the last UI render."""
-
def run_code(self):
"""Trigger a repl code execution on mouse click."""
self.pw_ptpython_repl.default_buffer.validate_and_handle()
diff --git a/pw_console/py/pw_console/search_toolbar.py b/pw_console/py/pw_console/search_toolbar.py
index e0d681c4a..2307a3c61 100644
--- a/pw_console/py/pw_console/search_toolbar.py
+++ b/pw_console/py/pw_console/search_toolbar.py
@@ -57,7 +57,6 @@ class SearchToolbar(ConditionalContainer):
self._search_invert = False
self._search_field = None
- # FormattedText of the search column headers.
self.input_field = TextArea(
prompt=[
('class:search-bar-setting', '/',
diff --git a/pw_console/py/pw_console/style.py b/pw_console/py/pw_console/style.py
index 8a0b486c1..19d41820d 100644
--- a/pw_console/py/pw_console/style.py
+++ b/pw_console/py/pw_console/style.py
@@ -16,6 +16,8 @@
import logging
from dataclasses import dataclass
+from prompt_toolkit.formatted_text import StyleAndTextTuples
+from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple
from prompt_toolkit.styles import Style
from prompt_toolkit.filters import has_focus
@@ -211,7 +213,7 @@ _THEME_NAME_MAPPING = {
'dark': DarkColors(),
'high-contrast-dark': HighContrastDarkColors(),
'ansi': AnsiTerm(),
-} # yapf: disable
+} # yapf: disable
def get_theme_colors(theme_name=''):
@@ -373,6 +375,20 @@ def generate_styles(theme_name='dark'):
'quit-dialog-border': 'bg:{} {}'.format(theme.inactive_bg,
theme.red_accent),
+ 'command-runner': 'bg:{}'.format(theme.inactive_bg),
+ 'command-runner-title': 'bg:{} {}'.format(theme.inactive_bg,
+ theme.default_fg),
+ 'command-runner-setting': '{}'.format(theme.purple_accent),
+ 'command-runner-border': 'bg:{} {}'.format(theme.inactive_bg,
+ theme.purple_accent),
+ 'command-runner-selected-item': 'bg:{}'.format(theme.selected_line_bg),
+ 'command-runner-fuzzy-highlight-0': '{}'.format(theme.blue_accent),
+ 'command-runner-fuzzy-highlight-1': '{}'.format(theme.cyan_accent),
+ 'command-runner-fuzzy-highlight-2': '{}'.format(theme.green_accent),
+ 'command-runner-fuzzy-highlight-3': '{}'.format(theme.yellow_accent),
+ 'command-runner-fuzzy-highlight-4': '{}'.format(theme.orange_accent),
+ 'command-runner-fuzzy-highlight-5': '{}'.format(theme.red_accent),
+
# Progress Bar Styles
# Entire set of ProgressBars - no title is used in pw_console
'title': '',
@@ -427,7 +443,7 @@ def generate_styles(theme_name='dark'):
'theme-bg-button-active': 'bg:{}'.format(theme.button_active_bg),
'theme-bg-button-inactive': 'bg:{}'.format(theme.button_inactive_bg),
- } # yapf: disable
+ } # yapf: disable
return Style.from_dict(pw_console_styles)
@@ -456,8 +472,14 @@ def get_pane_style(pt_container) -> str:
def get_pane_indicator(pt_container,
title,
mouse_handler=None,
- hide_indicator=False):
+ hide_indicator=False) -> StyleAndTextTuples:
"""Return formatted text for a pane indicator and title."""
+
+ inactive_indicator: OneStyleAndTextTuple
+ active_indicator: OneStyleAndTextTuple
+ inactive_title: OneStyleAndTextTuple
+ active_title: OneStyleAndTextTuple
+
if mouse_handler:
inactive_indicator = ('class:pane_indicator_inactive', ' ',
mouse_handler)
@@ -470,7 +492,7 @@ def get_pane_indicator(pt_container,
inactive_title = ('class:pane_title_inactive', title)
active_title = ('class:pane_title_active', title)
- fragments = []
+ fragments: StyleAndTextTuples = []
if has_focus(pt_container.__pt_container__())():
if not hide_indicator:
fragments.append(active_indicator)
diff --git a/pw_console/py/pw_console/widgets/border.py b/pw_console/py/pw_console/widgets/border.py
index d4624e9c9..64a03a3be 100644
--- a/pw_console/py/pw_console/widgets/border.py
+++ b/pw_console/py/pw_console/widgets/border.py
@@ -13,10 +13,11 @@
# the License.
"""Wrapper fuctions to add borders around prompt_toolkit containers."""
-from typing import List
+from typing import List, Optional
from prompt_toolkit.layout import (
AnyContainer,
+ FormattedTextControl,
HSplit,
VSplit,
Window,
@@ -26,7 +27,8 @@ from prompt_toolkit.layout import (
def create_border(
# pylint: disable=too-many-arguments
content: AnyContainer,
- content_height: int,
+ content_height: Optional[int] = None,
+ title: str = '',
border_style: str = '',
base_style: str = '',
top: bool = True,
@@ -48,9 +50,17 @@ def create_border(
if left:
top_border_items.append(
Window(width=1, height=1, char=top_left_char, style=border_style))
+
+ title_text = None
+ if title:
+ title_text = FormattedTextControl([
+ ('', f'{horizontal_char}{horizontal_char} {title} ')
+ ])
+
top_border_items.append(
Window(
- char='━',
+ title_text,
+ char=horizontal_char,
# Expand width to max available space
dont_extend_width=False,
style=border_style))
diff --git a/pw_console/py/pw_console/widgets/window_pane.py b/pw_console/py/pw_console/widgets/window_pane.py
index eb16428cf..ab2484a74 100644
--- a/pw_console/py/pw_console/widgets/window_pane.py
+++ b/pw_console/py/pw_console/widgets/window_pane.py
@@ -21,9 +21,11 @@ from prompt_toolkit.layout.dimension import AnyDimension
from prompt_toolkit.filters import Condition
from prompt_toolkit.layout import (
+ AnyContainer,
ConditionalContainer,
Dimension,
HSplit,
+ walk,
)
from pw_console.get_pw_console_app import get_pw_console_app
@@ -199,3 +201,11 @@ class WindowPane(ABC):
style=functools.partial(pw_console.style.get_pane_style, self),
),
filter=Condition(lambda: self.show_pane))
+
+ def has_child_container(self, child_container: AnyContainer) -> bool:
+ if not child_container:
+ return False
+ for container in walk(self.__pt_container__()):
+ if container == child_container:
+ return True
+ return False
diff --git a/pw_console/py/pw_console/widgets/window_pane_toolbar.py b/pw_console/py/pw_console/widgets/window_pane_toolbar.py
index 76ee0fc11..3c16beb62 100644
--- a/pw_console/py/pw_console/widgets/window_pane_toolbar.py
+++ b/pw_console/py/pw_console/widgets/window_pane_toolbar.py
@@ -66,9 +66,13 @@ class WindowPaneToolbar:
def get_left_text_tokens(self):
"""Return toolbar indicator and title."""
- title = ' {} '.format(self.title)
+ title = self.title
+ if not title and self.parent_window_pane:
+ # No title was set, fetch the parent window pane title if available.
+ parent_pane_title = self.parent_window_pane.pane_title()
+ title = parent_pane_title if parent_pane_title else title
return pw_console.style.get_pane_indicator(self.focus_check_container,
- title,
+ f' {title} ',
self.focus_mouse_handler)
def get_center_text_tokens(self):
@@ -161,8 +165,6 @@ class WindowPaneToolbar:
# Set parent_window_pane related options
if self.parent_window_pane:
- if not title:
- self.title = self.parent_window_pane.pane_title()
if not subtitle:
self.subtitle = self.parent_window_pane.pane_subtitle
self.focus_check_container = self.parent_window_pane
diff --git a/pw_console/py/pw_console/window_list.py b/pw_console/py/pw_console/window_list.py
index 075f4dbba..ec21b5810 100644
--- a/pw_console/py/pw_console/window_list.py
+++ b/pw_console/py/pw_console/window_list.py
@@ -203,8 +203,21 @@ class WindowList:
def get_current_active_pane(self):
"""Return the current active window pane."""
focused_pane = None
+
+ command_runner_focused_pane = None
+ if self.application.command_runner_is_open():
+ command_runner_focused_pane = (
+ self.application.command_runner_last_focused_pane())
+
for index, pane in enumerate(self.active_panes):
+ in_focus = False
if has_focus(pane)():
+ in_focus = True
+ elif command_runner_focused_pane and pane.has_child_container(
+ command_runner_focused_pane):
+ in_focus = True
+
+ if in_focus:
focused_pane = pane
self.focused_pane_index = index
break
diff --git a/pw_console/py/pw_console/window_manager.py b/pw_console/py/pw_console/window_manager.py
index a6dc4ea59..6b880532f 100644
--- a/pw_console/py/pw_console/window_manager.py
+++ b/pw_console/py/pw_console/window_manager.py
@@ -690,7 +690,7 @@ class WindowManager:
"""Focus on the first visible container."""
for pane in self.active_panes():
if pane.show_pane:
- self.application.focus_on_container(pane)
+ self.application.application.layout.focus(pane)
break
def check_for_all_hidden_panes_and_unhide(self) -> None:
@@ -1000,13 +1000,13 @@ class WindowManager:
))
menu_items.extend(
MenuItem(
- '{index}: {title} {subtitle}'.format(
+ '{index}: {title}'.format(
index=pane_index + 1,
title=pane.menu_title(),
- subtitle=pane.pane_subtitle()),
+ ),
children=[
MenuItem(
- '{check} Show Window'.format(
+ '{check} Show/Hide Window'.format(
check=pw_console.widgets.checkbox.
to_checkbox_text(pane.show_pane, end='')),
handler=functools.partial(self.toggle_pane, pane),
diff --git a/pw_console/py/window_manager_test.py b/pw_console/py/window_manager_test.py
index 0193af52e..676d07cb4 100644
--- a/pw_console/py/window_manager_test.py
+++ b/pw_console/py/window_manager_test.py
@@ -98,14 +98,14 @@ def _window_pane_counts(window_manager):
]
-def _window_pane_titles(window_manager):
+def window_pane_titles(window_manager):
return [[
pane.pane_title() + ' - ' + pane.pane_subtitle()
for pane in window_list.active_panes
] for window_list in window_manager.window_lists]
-def _target_list_and_pane(window_manager, list_index, pane_index):
+def target_list_and_pane(window_manager, list_index, pane_index):
# pylint: disable=protected-access
# Bypass prompt_toolkit has_focus()
window_manager._get_active_window_list_and_pane = (
@@ -132,23 +132,23 @@ class TestWindowManager(unittest.TestCase):
self.assertEqual([4], _window_pane_counts(window_manager))
# Move 2 windows to the right into their own splits
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 1, 0)
+ target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_right()
# 3 splits, first split has 2 windows
self.assertEqual([2, 1, 1], _window_pane_counts(window_manager))
# Move the first window in the first split left
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_left()
# 4 splits, each with their own window
self.assertEqual([1, 1, 1, 1], _window_pane_counts(window_manager))
# Move the first window to the right
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
# 3 splits, first split has 2 windows
self.assertEqual([2, 1, 1], _window_pane_counts(window_manager))
@@ -171,7 +171,7 @@ class TestWindowManager(unittest.TestCase):
window_manager = console_app.window_manager
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
# Should have one window list split of size 50.
self.assertEqual(
_window_list_widths(window_manager),
@@ -188,11 +188,11 @@ class TestWindowManager(unittest.TestCase):
# Move another pane to the right twice, creating a third
# window_list split.
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
# Above window pane is at a new location
- _target_list_and_pane(window_manager, 1, 0)
+ target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_right()
# Should have 3 splits now
@@ -209,7 +209,7 @@ class TestWindowManager(unittest.TestCase):
self.assertEqual(len(list(window_manager.active_panes())), 4)
# Target the middle split
- _target_list_and_pane(window_manager, 1, 0)
+ target_list_and_pane(window_manager, 1, 0)
# Shrink the middle split twice
window_manager.shrink_split()
window_manager.shrink_split()
@@ -225,7 +225,7 @@ class TestWindowManager(unittest.TestCase):
)
# Target the first split
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.reset_split_sizes()
# Shrink the first split twice
window_manager.shrink_split()
@@ -241,7 +241,7 @@ class TestWindowManager(unittest.TestCase):
)
# Target the third (last) split
- _target_list_and_pane(window_manager, 2, 0)
+ target_list_and_pane(window_manager, 2, 0)
window_manager.reset_split_sizes()
# Shrink the third split once
window_manager.shrink_split()
@@ -273,7 +273,7 @@ class TestWindowManager(unittest.TestCase):
)
# Target the middle split
- _target_list_and_pane(window_manager, 1, 0)
+ target_list_and_pane(window_manager, 1, 0)
# Move the middle window pane left
window_manager.move_pane_left()
# This is called on the next render pass
@@ -405,7 +405,7 @@ class TestWindowManager(unittest.TestCase):
# Check window pane ordering
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log2 - test_log2',
@@ -419,7 +419,7 @@ class TestWindowManager(unittest.TestCase):
target_window_pane(0)
window_manager.move_pane_down()
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log1 - test_log1',
@@ -434,7 +434,7 @@ class TestWindowManager(unittest.TestCase):
target_window_pane(1)
window_manager.move_pane_up()
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log0 - test_log0',
@@ -447,7 +447,7 @@ class TestWindowManager(unittest.TestCase):
target_window_pane(0)
window_manager.move_pane_up()
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log0 - test_log0',
@@ -465,7 +465,7 @@ class TestWindowManager(unittest.TestCase):
window_manager = console_app.window_manager
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log3 - test_log3',
@@ -480,7 +480,7 @@ class TestWindowManager(unittest.TestCase):
# Scenario: Move between panes with a single stacked window list.
# Set the first pane in focus.
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
# Switch focus to the next pane
window_manager.focus_next_pane()
# Pane index 1 should now be focused.
@@ -489,7 +489,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set the first pane in focus.
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
# Switch focus to the previous pane
window_manager.focus_previous_pane()
# Previous pane should wrap around to the last pane in the first
@@ -499,7 +499,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set the last pane in focus.
- _target_list_and_pane(window_manager, 0, 4)
+ target_list_and_pane(window_manager, 0, 4)
# Switch focus to the next pane
window_manager.focus_next_pane()
# Next pane should wrap around to the first pane in the first
@@ -520,7 +520,7 @@ class TestWindowManager(unittest.TestCase):
wraps=window_manager.window_lists[0].switch_to_tab)
# Set the first pane/tab in focus.
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
# Switch focus to the next pane/tab
window_manager.focus_next_pane()
# Check switch_to_tab is called
@@ -533,7 +533,7 @@ class TestWindowManager(unittest.TestCase):
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Set the last pane/tab in focus.
- _target_list_and_pane(window_manager, 0, 4)
+ target_list_and_pane(window_manager, 0, 4)
# Switch focus to the next pane/tab
window_manager.focus_next_pane()
# Check switch_to_tab is called
@@ -546,7 +546,7 @@ class TestWindowManager(unittest.TestCase):
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Set the first pane/tab in focus.
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
# Switch focus to the prev pane/tab
window_manager.focus_previous_pane()
# Check switch_to_tab is called
@@ -563,12 +563,12 @@ class TestWindowManager(unittest.TestCase):
# Setup: Move two panes to the right into their own stacked
# window_list.
- _target_list_and_pane(window_manager, 0, 4)
+ target_list_and_pane(window_manager, 0, 4)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 0, 3)
+ target_list_and_pane(window_manager, 0, 3)
window_manager.move_pane_right()
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log3 - test_log3',
@@ -587,7 +587,7 @@ class TestWindowManager(unittest.TestCase):
wraps=window_manager.window_lists[1].switch_to_tab)
# Set Log1 in focus
- _target_list_and_pane(window_manager, 0, 2)
+ target_list_and_pane(window_manager, 0, 2)
window_manager.focus_next_pane()
# Log0 should now have focus
console_app.focus_on_container.assert_called_once_with(
@@ -595,7 +595,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set Log0 in focus
- _target_list_and_pane(window_manager, 1, 0)
+ target_list_and_pane(window_manager, 1, 0)
window_manager.focus_previous_pane()
# Log1 should now have focus
console_app.focus_on_container.assert_called_once_with(
@@ -609,7 +609,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set Python Repl in focus
- _target_list_and_pane(window_manager, 1, 1)
+ target_list_and_pane(window_manager, 1, 1)
window_manager.focus_next_pane()
# Log3 should now have focus
console_app.focus_on_container.assert_called_once_with(
@@ -621,7 +621,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set Log3 in focus
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.focus_next_pane()
# Log2 should now have focus
console_app.focus_on_container.assert_called_once_with(
@@ -633,7 +633,7 @@ class TestWindowManager(unittest.TestCase):
console_app.focus_on_container.reset_mock()
# Set Python Repl in focus
- _target_list_and_pane(window_manager, 1, 1)
+ target_list_and_pane(window_manager, 1, 1)
window_manager.focus_previous_pane()
# Log0 should now have focus
console_app.focus_on_container.assert_called_once_with(
@@ -660,16 +660,16 @@ class TestWindowManager(unittest.TestCase):
self.assertTrue(window_manager.vertical_window_list_spliting())
# Move windows to create 3 splits
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 1, 1)
+ target_list_and_pane(window_manager, 1, 1)
window_manager.move_pane_right()
# Check windows are where expected
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log1 - test_log1',
@@ -738,16 +738,16 @@ class TestWindowManager(unittest.TestCase):
window_manager.create_root_container()
# Move windows to create 3 splits
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 0, 0)
+ target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_right()
- _target_list_and_pane(window_manager, 1, 1)
+ target_list_and_pane(window_manager, 1, 1)
window_manager.move_pane_right()
# Check windows are where expected
self.assertEqual(
- _window_pane_titles(window_manager),
+ window_pane_titles(window_manager),
[
[
'Log1 - test_log1',