Skip to content

Instantly share code, notes, and snippets.

@potatosalad
Last active February 27, 2019 16:37
Show Gist options
  • Save potatosalad/603a12547afc2794290901a846574b35 to your computer and use it in GitHub Desktop.
Save potatosalad/603a12547afc2794290901a846574b35 to your computer and use it in GitHub Desktop.

Build or install nghttp2 (optionally with support for the --interval DURATION flag).

Either:

brew install nghttp2

Or:

git clone https://github.com/potatosalad/nghttp2.git
cd nghttp2
git checkout interval-flag
git submodule update --init
autoreconf -ivf
automake
autoconf
./configure --enable-app --disable-silent-rules --disable-python-bindings --enable-asio-lib --with-boost --without-jemalloc
make -j8

Running the server:

go build server.go
./server

Example HTTP/2 load test:

h2load --duration=30s --warm-up-time=1s --interval=1s --clients=100 --max-concurrent-streams=10 --requests=0 "http://127.0.0.1:8080/"

Example HTTP/1.1 load test:

h2load --h1 --duration=30s --warm-up-time=1s --interval=1s --clients=100 --max-concurrent-streams=10 --requests=0 "http://127.0.0.1:8080/"

Note: If you didn't install the custom-built version of nghttp2, remove the --interval=1s part of the preceeding commands.

Generation of the graph(s) involves the custom version of nghttp2 and calling the ./h2load.sh $H2LOAD_BIN name_of_test (h1|h2) 8080 script. It's really, really clunky. You have been warned.

#!/usr/bin/env bash
rrdtool graph go-h1-vs-h2.svg \
--width 600 \
--height 200 \
--start 00:00 \
--end start+38seconds \
--title 'go HTTP/1.1 vs HTTP/2' \
--vertical-label 'requests per second' \
--imgformat SVG \
--border 0 \
--font DEFAULT:0:Consolas \
--upper-limit 100000 \
--lower-limit 0 \
--rigid \
'DEF:gh1requests=go_best_h1.rrd:requests:MAX:start=1544709339:end=1544709377:step=1' \
'DEF:gh2requests=go_best_h2.rrd:requests:MAX:start=1544709272:end=1544709310:step=1' \
'SHIFT:gh1requests:-28539' \
'SHIFT:gh2requests:-28472' \
'CDEF:gh1ln=gh1requests,gh1requests,UNKN,IF' \
'CDEF:gh2ln=gh2requests,gh2requests,UNKN,IF' \
'VDEF:gh1requestsmax=gh1requests,MAXIMUM' \
'VDEF:gh1requestsmin=gh1requests,MINIMUM' \
'VDEF:gh1requestsavg=gh1requests,AVERAGE' \
'VDEF:gh1requestsstd=gh1requests,STDEV' \
'VDEF:gh2requestsmax=gh2requests,MAXIMUM' \
'VDEF:gh2requestsmin=gh2requests,MINIMUM' \
'VDEF:gh2requestsavg=gh2requests,AVERAGE' \
'VDEF:gh2requestsstd=gh2requests,STDEV' \
'AREA:gh1requests#7648ec: go HTTP/1.1\l' \
'COMMENT:\u' \
'GPRINT:gh1requestsavg:AVG %6.0lf' \
'GPRINT:gh1requestsmin:MIN %6.0lf' \
'GPRINT:gh1requestsmax:MAX %6.0lf' \
'GPRINT:gh1requestsstd:STDEV %6.0lf\r' \
'AREA:gh2requests#54ec48: go HTTP/2\l' \
'COMMENT:\u' \
'GPRINT:gh2requestsavg:AVG %6.0lf' \
'GPRINT:gh2requestsmin:MIN %6.0lf' \
'GPRINT:gh2requestsmax:MAX %6.0lf' \
'GPRINT:gh2requestsstd:STDEV %6.0lf\r' \
'LINE1:gh1ln#4d18e4' \
'LINE1:gh2ln#24bc14'
Display the source blob
Display the rendered blob
Raw
<svg height="286pt" viewBox="0 0 685 286" width="685pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m55 39h600v10h-600zm0 0"/></clipPath><clipPath id="b"><path d="m55 126h600v7h-600zm0 0"/></clipPath><symbol id="c" overflow="visible"><path d="m3.546875-2.230469c0 .339844-.03125.652344-.101563.933594-.070312.28125-.171874.523437-.3125.722656-.136718.203125-.308593.359375-.515624.46875-.207032.1132815-.449219.167969-.726563.167969-.238281 0-.457031-.046875-.652344-.1367188-.195312-.0898432-.363281-.2265622-.503906-.4140622s-.246094-.425781-.320313-.714844c-.074218-.289063-.113281-.632813-.113281-1.027344 0-.34375.035157-.65625.105469-.9375s.171875-.523437.308594-.726562c.136718-.203125.3125-.359375.519531-.46875s.449219-.164063.722656-.164063c.238281 0 .457031.042969.652344.132813.195313.089843.367187.230469.503906.417969.140625.1875.246094.425781.320313.714843.074218.289063.113281.632813.113281 1.03125zm-.601563.019531c0-.078124 0-.15625-.007812-.230468-.003906-.078125-.011719-.152344-.019531-.222656l-1.890625 1.402343c.035156.117188.078125.226563.132812.328125.050782.101563.113282.1875.1875.257813.074219.074219.160156.128906.253906.167969.09375.039062.203126.058593.324219.058593.152344 0 .292969-.035156.421875-.113281.125-.074219.234375-.183594.320313-.332031.089843-.148438.160156-.332031.207031-.554688.046875-.21875.070312-.472656.070312-.761719zm-2.042968-.042968v.214844c.003906.070312.007812.136718.011718.203124l1.890626-1.398437c-.03125-.117187-.074219-.222656-.128907-.316406-.050781-.097657-.113281-.179688-.1875-.25-.074219-.066407-.15625-.121094-.25-.160157-.09375-.039062-.199219-.058593-.3125-.058593-.15625 0-.296875.039062-.421875.113281-.128906.074219-.234375.1875-.324218.335938-.089844.148437-.15625.335937-.207032.554687-.046875.21875-.070312.472656-.070312.761719zm0 0"/></symbol><symbol id="d" overflow="visible"><path d="m1.925781-3.492188c.070313 0 .136719.011719.199219.042969.0625.027344.121094.066407.167969.113281.046875.046876.085937.105469.113281.167969.03125.0625.042969.128907.042969.199219 0 .074219-.011719.144531-.042969.207031-.027344.0625-.066406.117188-.113281.164063s-.101563.085937-.167969.113281c-.0625.027344-.128906.039063-.199219.039063-.074219 0-.140625-.011719-.203125-.039063s-.121094-.066406-.167968-.113281c-.046876-.046875-.085938-.101563-.113282-.164063s-.039062-.132812-.039062-.207031c0-.070312.011718-.136719.039062-.199219s.066406-.121093.113282-.167969c.046874-.046874.105468-.085937.167968-.113281.0625-.027343.128906-.042969.203125-.042969zm0 2.503907c.070313 0 .136719.015625.199219.042969.0625.027343.121094.066406.167969.113281.046875.050781.085937.105469.113281.167969.03125.0625.042969.132812.042969.203124 0 .074219-.011719.140626-.042969.203126-.027344.0625-.066406.117187-.113281.164062s-.101563.0859375-.167969.1132812c-.0625.0273438-.128906.0429688-.199219.0429688-.074219 0-.140625-.015625-.203125-.0429688-.0625-.0273437-.121094-.0625-.167968-.1132812-.046876-.046875-.085938-.101562-.113282-.164062s-.039062-.128907-.039062-.203126c0-.070312.011718-.136718.039062-.203124.027344-.0625.066406-.117188.113282-.167969.046874-.046875.105468-.085938.167968-.113281.0625-.027344.128906-.042969.203125-.042969zm0 0"/></symbol><symbol id="e" overflow="visible"><path d="m3.332031-1.429688c0 .222657-.046875.421876-.144531.605469-.09375.183594-.226562.339844-.394531.46875-.167969.132813-.363281.234375-.589844.308594-.230469.0703125-.476563.109375-.742187.109375-.066407 0-.136719-.0039062-.210938-.0078125-.078125-.0039063-.152344-.0078125-.226562-.0117187-.078126-.0039063-.148438-.0117188-.222657-.0195313-.070312-.0078125-.136719-.015625-.191406-.0234375v-.539062c.121094.027343.261719.050781.421875.0625.15625.015624.316406.023437.480469.023437.183593 0 .34375-.023437.492187-.066406.144532-.042969.269532-.105469.371094-.1875s.179688-.175781.234375-.292969c.054687-.113281.085937-.242188.085937-.386719 0-.277343-.101562-.480469-.300781-.609375-.199219-.125-.484375-.1875-.859375-.1875h-.847656v-2.285156h2.40625v.519531h-1.847656v1.253907h.390625c.214843 0 .421875.019531.625.058593.203125.039063.382812.109375.542969.203125.15625.097656.285156.226563.382812.390625.097656.164063.144531.367188.144531.613281zm0 0"/></symbol><symbol id="f" overflow="visible"><path d="m3.40625 0h-2.804688v-.554688h1.148438v-3.257812l-1.070312.578125-.21875-.503906 1.421874-.75h.527344v3.933593h.996094zm0 0"/></symbol><symbol id="g" overflow="visible"><path d="m3.445312 0h-2.941406v-.53125l1.152344-1.148438c.191406-.1875.34375-.351562.460938-.488281.121093-.136719.210937-.261719.277343-.375.066407-.113281.113281-.21875.136719-.316406.023438-.101563.03125-.210937.03125-.328125 0-.109375-.015625-.210938-.042969-.3125-.03125-.097656-.074219-.183594-.136719-.257812-.0625-.078126-.140624-.136719-.238281-.179688-.097656-.042969-.214843-.066406-.355469-.066406-.1875 0-.359374.042968-.515624.128906-.152344.082031-.296876.191406-.425782.328125l-.328125-.394531c.167969-.175782.363281-.320313.582031-.425782.21875-.109374.476563-.160156.769532-.160156.199218 0 .378906.027344.539062.085938.164063.058594.304688.144531.421875.257812.121094.113282.210938.25.277344.410156.0625.160157.097656.34375.097656.546876 0 .171874-.023437.328124-.070312.476562-.042969.144531-.113281.289062-.207031.433594-.089844.144531-.207032.296875-.347657.449218-.140625.15625-.304687.324219-.496093.511719l-.8125.789063h2.171874zm0 0"/></symbol><symbol id="h" overflow="visible"><path d="m3.359375-1.355469c0 .195313-.039063.378907-.117187.550781-.082032.171876-.203126.320313-.359376.449219-.160156.128907-.363281.230469-.601562.3046878-.242188.0742187-.523438.1132812-.84375.1132812-.179688 0-.339844-.0078125-.480469-.0195312-.140625-.0117188-.273437-.0234376-.394531-.0429688v-.53125c.140625.023438.289062.042969.445312.054688.15625.015624.320313.023437.484376.023437.222656 0 .414062-.019531.570312-.0625.160156-.039063.289062-.097656.386719-.171875.101562-.074219.175781-.164062.21875-.273438.046875-.105468.070312-.226562.070312-.363281 0-.121093-.027343-.230469-.082031-.320312-.054688-.089844-.132812-.167969-.230469-.230469-.097656-.058594-.21875-.105469-.355469-.136719-.136718-.03125-.289062-.046875-.453124-.046875h-.507813v-.488281h.515625c.132812 0 .253906-.015625.367188-.050781.109374-.035156.203124-.085938.28125-.152344.078124-.066406.140624-.148438.183593-.246094s.0625-.207031.0625-.328125c0-.238281-.074219-.414062-.21875-.523437s-.359375-.164063-.644531-.164063c-.148438 0-.304688.015625-.464844.042969-.160156.03125-.328125.074219-.511718.132812v-.519531c.078124-.027343.160156-.050781.25-.074219.085937-.019531.171874-.039062.261718-.054687.085938-.015625.175782-.023437.261719-.03125s.167969-.011719.25-.011719c.234375 0 .445313.023438.625.074219s.328125.125.449219.222656c.121094.09375.214844.210938.273437.347657.0625.136718.09375.289062.09375.460937 0 .253906-.066406.46875-.195312.644531-.132813.171875-.3125.308594-.539063.410156.117188.019532.230469.054688.34375.109376.113282.054687.214844.125.304688.210937s.160156.1875.21875.304687c.054687.117188.082031.242188.082031.386719zm0 0"/></symbol><symbol id="i" overflow="visible"/><symbol id="j" overflow="visible"><path d="m3.632812 0h-.816406l-1.597656-1.839844v1.839844h-.597656v-4.828125h.597656v2.964844l1.539062-1.566407h.785157l-1.609375 1.582032zm0 0"/></symbol><symbol id="k" overflow="visible"><path d="m3.667969-.988281h-.761719v.988281h-.609375v-.988281h-2.148437v-.523438l1.902343-2.957031h.855469v2.957031h.761719zm-1.371094-2.90625-1.554687 2.382812h1.554687zm0 0"/></symbol><symbol id="l" overflow="visible"><path d="m3.5-1.414062c0 .203124-.035156.398437-.109375.578124-.074219.179688-.179687.335938-.316406.46875-.136719.132813-.304688.238282-.496094.3125005-.191406.078125-.40625.1171875-.640625.1171875-.246094 0-.464844-.0390625-.652344-.1171875-.1875-.0781245-.347656-.1992185-.476562-.3632815-.125-.164062-.222656-.371093-.289063-.617187-.066406-.25-.097656-.542969-.097656-.882813 0-.226562.011719-.449219.042969-.664062.03125-.214844.078125-.414063.148437-.605469.066407-.1875.15625-.359375.273438-.515625.113281-.160156.253906-.292969.425781-.40625.167969-.113281.367188-.203125.597656-.265625.230469-.0625.496094-.09375.800782-.09375h.441406v.519531h-.480469c-.265625 0-.496094.035157-.691406.097657-.195313.0625-.363281.152343-.492188.269531-.132812.117187-.234375.257812-.304687.421875-.070313.164062-.117188.347656-.132813.550781l-.015625.136719c.144532-.082032.308594-.152344.496094-.203125s.394531-.074219.613281-.074219c.222657 0 .421875.03125.589844.097656.171875.066406.3125.15625.425781.273438.113282.117187.199219.261718.253906.425781.058594.164063.085938.34375.085938.539063zm-.621094.035156c0-.136719-.015625-.257813-.050781-.371094-.03125-.109375-.085937-.203125-.15625-.277344-.070313-.078125-.160156-.136718-.265625-.179687-.109375-.042969-.238281-.0625-.390625-.0625-.085937 0-.171875.007812-.261719.023437s-.175781.039063-.261718.066406c-.085938.027344-.167969.0625-.246094.097657-.078125.035156-.148438.074219-.210938.117187 0 .292969.019532.539063.0625.734375.039063.199219.101563.355469.183594.476563.078125.117187.179688.203125.296875.25.117187.050781.257813.078125.410156.078125.128907 0 .25-.023438.359375-.066407.105469-.039062.199219-.101562.277344-.183593s.140625-.183594.1875-.300781c.042969-.117188.066406-.25.066406-.402344zm0 0"/></symbol><symbol id="m" overflow="visible"><path d="m3.421875-3.914062-1.875 3.914062h-.679687l1.945312-3.914062h-2.414062v-.554688h3.023437zm0 0"/></symbol><symbol id="n" overflow="visible"><path d="m3.445312-1.121094c0 .1875-.039062.355469-.117187.503906-.078125.148438-.183594.269532-.324219.371094-.136718.101563-.300781.1757815-.492187.230469-.1875.0507812-.394531.078125-.613281.078125-.246094 0-.460938-.0273438-.644532-.0820312-.1875-.0546876-.34375-.1328128-.46875-.2304688s-.21875-.214844-.28125-.347656c-.066406-.136719-.097656-.28125-.097656-.445313 0-.273437.078125-.507812.230469-.707031.152343-.199219.386719-.378906.707031-.539062-.292969-.148438-.503906-.3125-.640625-.496094-.132813-.179688-.199219-.386719-.199219-.621094 0-.144531.027344-.285156.085938-.417969.058594-.136719.148437-.253906.269531-.359375.121094-.105468.269531-.1875.449219-.25.179687-.0625.390625-.09375.636718-.09375.230469 0 .433594.023438.605469.070313.175781.050781.320313.121093.441407.210937.117187.089844.207031.203125.265624.332032.058594.128906.089844.273437.089844.433593 0 .261719-.074218.480469-.21875.664063-.144531.183594-.351562.339844-.617187.480468.132812.066407.253906.136719.371093.21875.113282.078126.210938.167969.296876.265626.082031.097656.148437.207031.195312.328124.046875.121094.070312.253907.070312.402344zm-.707031-2.308594c0-.203124-.070312-.355468-.214843-.453124-.140626-.101563-.339844-.148438-.597657-.148438-.257812 0-.457031.046875-.597656.144531-.140625.097657-.214844.246094-.214844.441407 0 .089843.019531.171874.050781.246093.035157.074219.089844.144531.160157.210938.070312.066406.160156.132812.269531.195312.105469.0625.234375.128907.382812.195313.257813-.121094.449219-.246094.574219-.378906.125-.128907.1875-.28125.1875-.453126zm.0625 2.351563c0-.082031-.015625-.164063-.042969-.246094-.027343-.078125-.074218-.15625-.148437-.234375-.070313-.078125-.164063-.15625-.28125-.230468-.117187-.078126-.269531-.160157-.453125-.242188-.152344.074219-.285156.152344-.390625.226562-.105469.074219-.191406.148438-.253906.222657-.066407.078125-.113281.15625-.140625.238281s-.039063.167969-.039063.261719c0 .101562.019531.191406.066407.269531.042968.078125.105468.144531.179687.199219.078125.054687.171875.097656.277344.125.109375.027343.226562.039062.351562.039062.121094 0 .234375-.011719.339844-.035156.109375-.027344.199219-.0625.277344-.117187.078125-.050782.140625-.113282.1875-.191407s.070312-.175781.070312-.285156zm0 0"/></symbol><symbol id="o" overflow="visible"><path d="m3.421875-2.484375c0 .433594-.054687.808594-.15625 1.121094-.105469.3125-.261719.570312-.464844.773437-.207031.203125-.460937.351563-.761719.445313-.304687.097656-.65625.144531-1.050781.144531h-.371093v-.519531h.410156c.292968 0 .550781-.03125.761718-.089844.214844-.058594.394532-.144531.535157-.261719.144531-.113281.253906-.253906.328125-.417968.074218-.164063.121094-.355469.140625-.566407l.011719-.140625c-.140626.085938-.308594.152344-.492188.203125-.1875.050781-.390625.078125-.609375.078125-.226563 0-.425781-.035156-.59375-.101562-.171875-.066406-.316406-.15625-.425781-.277344-.113282-.117188-.199219-.257812-.257813-.421875-.054687-.160156-.082031-.339844-.082031-.53125 0-.207031.035156-.398437.109375-.578125.078125-.179688.183594-.339844.316406-.472656.136719-.132813.300781-.238282.488281-.316406.1875-.078126.398438-.113282.625-.113282.222657 0 .425782.035156.613282.109375.1875.070313.351562.1875.488281.351563.136719.164062.242187.375.320313.636718.078124.257813.117187.574219.117187.945313zm-1.566406-1.554687c-.128907 0-.246094.019531-.351563.0625-.109375.042968-.203125.101562-.28125.183593s-.140625.179688-.1875.300781c-.046875.117188-.066406.253907-.066406.40625 0 .140626.015625.261719.046875.371094.035156.109375.085937.203125.15625.28125.070313.074219.15625.132813.265625.175782.109375.039062.242188.058593.390625.058593.085937 0 .171875-.007812.261719-.023437s.179687-.035156.261718-.0625c.085938-.027344.167969-.0625.246094-.097656.078125-.035157.148438-.074219.207032-.117188 0-.292969-.019532-.539062-.0625-.734375-.042969-.199219-.105469-.355469-.1875-.476563-.082032-.117187-.183594-.203124-.300782-.253906-.117187-.050781-.25-.074218-.398437-.074218zm0 0"/></symbol><symbol id="p" overflow="visible"><path d="m-3.921875-.785156v-.621094l.722656-.019531c-.277343-.230469-.480469-.460938-.605469-.6875-.125-.222657-.1875-.449219-.1875-.679688 0-.40625.132813-.714843.394532-.925781.261718-.207031.652344-.304688 1.171875-.289062v.6875c-.34375-.007813-.59375.042968-.746094.148437-.15625.109375-.234375.269531-.234375.476563 0 .089843.015625.183593.046875.273437.035156.09375.085937.1875.15625.289063.074219.097656.164063.199218.277344.308593s.246093.226563.40625.351563h2.519531v.6875zm0 0"/></symbol><symbol id="q" overflow="visible"><path d="m-2.167969-3.9375c.097657 0 .175781 0 .242188.003906.066406.003906.125.007813.183593.011719v2.753906c.402344 0 .710938-.113281.925782-.335937s.320312-.546875.320312-.96875c0-.113282-.003906-.230469-.011718-.34375-.011719-.113282-.023438-.226563-.039063-.332032-.015625-.105468-.03125-.210937-.050781-.304687-.019532-.097656-.042969-.191406-.066406-.273437h.558593c.0507815.183593.0937502.394531.1289065.625.03125.234374.046875.476562.046875.726562 0 .335938-.046875.625-.1367187.867188-.0898438.242187-.2226558.441406-.3945318.59375-.175781.15625-.386718.273437-.640624.34375-.25.074218-.535157.113281-.851563.113281-.277344 0-.539063-.039063-.78125-.121094-.246094-.078125-.464844-.195313-.648437-.347656-.1875-.152344-.335938-.335938-.445313-.558594s-.164063-.472656-.164063-.753906c0-.273438.042969-.515625.128907-.726563.085937-.210937.207031-.386718.363281-.535156.160156-.144531.351562-.25.578125-.328125.222656-.074219.476563-.109375.753906-.109375zm-.097656.707031c-.175781-.007812-.335937.007813-.476563.050781-.144531.042969-.269531.105469-.375.195313-.105468.085937-.1875.195313-.242187.324219-.058594.128906-.089844.28125-.089844.453125 0 .148437.027344.285156.085938.40625.058593.121093.136719.226562.242187.316406.105469.089844.230469.160156.375.214844.144532.054687.304688.089843.480469.101562zm0 0"/></symbol><symbol id="r" overflow="visible"><path d="m-1.878906-.425781c-.28125 0-.546875-.039063-.800782-.113281-.253906-.074219-.476562-.1875-.664062-.34375-.191406-.152344-.34375-.351563-.457031-.59375-.113281-.242188-.167969-.53125-.167969-.867188 0-.132812.011719-.265625.03125-.394531.019531-.128907.054688-.269531.097656-.414063l-.152344-.601562h5.59375v.683594h-1.480468l-.839844-.035157c.527344.371094.7890625.808594.7890625 1.320313 0 .230468-.046875.429687-.140625.597656-.0937495.167969-.2265625.3125-.3984375.421875-.171875.113281-.378906.199219-.617188.253906-.238281.058594-.503906.085938-.792968.085938zm-.042969-.695313c.21875 0 .414063-.015625.589844-.050781.175781-.03125.324219-.078125.445312-.148437.121094-.066407.210938-.148438.277344-.25.066406-.097657.097656-.214844.097656-.351563 0-.171875-.078125-.351563-.230469-.546875-.152343-.191406-.382812-.390625-.683593-.601562h-1.820313c-.050781.105468-.089844.222656-.121094.351562-.03125.132812-.046874.273438-.046874.421875 0 .382813.125.675781.378906.875s.625.300781 1.113281.300781zm0 0"/></symbol><symbol id="s" overflow="visible"><path d="m0-3.777344v.609375l-.632812.023438c.136718.117187.25.230469.339843.332031.089844.105469.160157.210938.214844.316406.0546875.105469.09375.207032.1171875.316406.0195313.105469.03125.214844.03125.332032 0 .402344-.1171875.707031-.3554685.914062-.238282.207032-.59375.308594-1.074219.308594h-2.5625v-.679688h2.507813c.601562 0 .902343-.226562.902343-.679687 0-.082031-.011719-.164063-.035156-.242187-.027344-.082032-.070313-.164063-.128906-.25-.0625-.089844-.144531-.183594-.25-.28125-.105469-.101563-.234375-.214844-.394531-.339844h-2.601563v-.679688zm0 0"/></symbol><symbol id="t" overflow="visible"><path d="m-1.070312-3.730469c.136718 0 .261718.023438.371093.070313s.207031.109375.292969.191406c.082031.082031.15625.175781.214844.28125s.1093748.21875.1484372.34375c.03906255.121094.0664063.242188.0859376.371094.0195312.128906.0273437.253906.0273437.375 0 .265625-.0117187.511718-.0351563.730468-.0234374.222657-.0625.441407-.1132812.65625h-.625c.066406-.230468.113281-.457031.148437-.683593.035157-.226563.050782-.453125.050782-.675781 0-.324219-.042969-.566407-.132813-.722657-.089843-.15625-.214843-.234375-.378906-.234375-.070313 0-.132813.011719-.1875.035156-.058594.027344-.109375.070313-.160156.136719-.050781.066407-.105469.167969-.160157.300781-.054687.136719-.117187.324219-.1875.5625-.050781.175782-.109374.339844-.179687.488282-.066406.152344-.144531.28125-.234375.390625s-.199219.195312-.320312.257812c-.121094.0625-.265626.09375-.433594.09375-.109375 0-.230469-.027343-.359375-.078125-.128907-.050781-.25-.136718-.363281-.257812-.113282-.121094-.203126-.289063-.28125-.496094-.074219-.207031-.109376-.46875-.109376-.78125 0-.152344.007813-.324219.023438-.511719.019531-.1875.046875-.382812.089844-.585937h.605468c-.050781.214844-.089843.417968-.117187.605468-.023437.191407-.035156.359376-.035156.5 0 .167969.011719.3125.039062.425782.027344.117187.0625.210937.105469.28125.046875.074218.101562.125.164062.15625.058594.03125.125.046875.195313.046875s.132813-.015625.191406-.042969c.058594-.027344.113281-.078125.167969-.152344.050781-.074218.105469-.175781.15625-.308594.054688-.132812.113281-.304687.175781-.519531.066407-.230469.136719-.425781.214844-.585937.074219-.160156.15625-.289063.246094-.386719.089843-.097656.195312-.171875.308593-.210937.113282-.042969.246094-.066407.390626-.066407zm0 0"/></symbol><symbol id="u" overflow="visible"><path d="m-.0546875-3.785156c.0390625.152344.0664063.3125.0859375.476562.015625.164063.0234375.332032.0234375.5 0 .492188-.109375.859375-.3320315 1.101563-.222656.242187-.566406.363281-1.027344.363281h-2.046874v1.097656h-.570313v-1.097656h-1.078125l-.175781-.679688h1.253906v-1.761718h.570313v1.761718h1.992187c.28125 0 .492187-.074218.632813-.226562.136718-.148438.207031-.367188.207031-.660156 0-.125-.007813-.261719-.027344-.410156-.019531-.148438-.050781-.304688-.09375-.464844zm0 0"/></symbol><symbol id="v" overflow="visible"/><symbol id="w" overflow="visible"><path d="m-2.03125-3.976562c.347656 0 .652344.046874.914062.148437.261719.097656.476563.230469.648438.402344s.300781.375.3867188.609375c.08593745.234375.1289062.488281.1289062.761718 0 .125-.0078125.25-.0195312.375-.0117188.121094-.0351563.246094-.0664063.375h1.6406245v.679688h-5.523437v-.605469l.65625-.042969c-.269531-.195312-.457031-.402343-.5625-.625-.109375-.222656-.164063-.460937-.164063-.71875 0-.222656.046876-.421874.140626-.589843s.226562-.3125.398437-.425781c.167969-.113282.375-.199219.617187-.257813.238282-.058594.507813-.085937.804688-.085937zm.03125.695312c-.207031 0-.394531.015625-.566406.046875-.171875.027344-.320313.074219-.441406.140625-.121094.066406-.21875.148438-.289063.25-.066406.101562-.101563.222656-.101563.363281 0 .085938.015626.171875.039063.261719.027344.089844.074219.179688.140625.273438.0625.097656.148438.195312.25.300781.105469.105469.238281.21875.394531.339843h1.902344c.050781-.125.09375-.257812.125-.394531.027344-.136719.042969-.273437.042969-.40625 0-.367187-.125-.65625-.371094-.863281-.25-.207031-.625-.3125-1.125-.3125zm0 0"/></symbol><symbol id="x" overflow="visible"><path d="m-.144531-3.671875c.066406.175781.1171872.359375.1523435.546875.03125.183594.046875.375.046875.574219 0 .621093-.1679685 1.097656-.5039065 1.433593-.335937.332032-.828125.5-1.472656.5-.308594 0-.589844-.046874-.84375-.144531-.253906-.097656-.46875-.230469-.648437-.40625-.179688-.175781-.320313-.382812-.414063-.625-.097656-.242187-.148437-.507812-.148437-.800781 0-.203125.015624-.394531.042968-.570312.027344-.175782.074219-.347657.140625-.507813h.648438c-.089844.167969-.152344.34375-.191407.515625-.042968.175781-.0625.359375-.0625.546875 0 .175781.03125.339844.101563.492187.066406.15625.160156.292969.285156.410157.125.117187.277344.210937.457031.277343.179688.066407.382813.101563.609376.101563.472656 0 .828124-.117187 1.066406-.34375.234375-.230469.351562-.550781.351562-.960937 0-.183594-.019531-.363282-.0625-.539063-.042968-.171875-.105468-.339844-.1875-.5zm0 0"/></symbol><symbol id="y" overflow="visible"><path d="m-1.992188-4.039062c.304688 0 .585938.042968.839844.128906.253906.085937.46875.210937.652344.371094.179688.160156.320312.359374.421875.589843.0976562.230469.1484375.496094.1484375.789063 0 .28125-.0429687.535156-.1289063.753906-.0898442.222656-.2187502.414062-.3867182.570312-.167969.152344-.378907.273438-.628907.351563-.25.082031-.539062.125-.863281.125-.304688 0-.582031-.042969-.835938-.128906-.25-.085938-.464843-.210938-.648437-.371094-.179687-.160156-.320313-.359375-.421875-.589844-.097656-.230469-.148438-.496093-.148438-.789062 0-.28125.042969-.535157.132813-.757813.085937-.222656.210937-.410156.382813-.566406.167968-.152344.375-.273438.625-.351562.25-.082032.535156-.125.859374-.125zm.03125.695312c-.242187 0-.453124.027344-.632812.078125-.183594.054687-.335938.132813-.453125.230469-.121094.097656-.214844.21875-.273437.363281-.0625.140625-.09375.296875-.09375.472656 0 .203125.039062.375.117187.519531.082031.144532.1875.265626.320313.355469.132812.09375.289062.160157.460937.203125.175781.042969.363281.066406.554687.066406.242188 0 .453126-.027343.636719-.078124.183594-.054688.332031-.132813.457031-.230469.121094-.097657.210938-.21875.273438-.359375.058594-.140625.089844-.300782.089844-.476563 0-.203125-.039063-.378906-.117188-.519531-.082031-.144531-.1875-.265625-.320312-.359375-.132813-.089844-.285156-.15625-.460938-.203125-.175781-.042969-.363281-.0625-.558594-.0625zm0 0"/></symbol><symbol id="z" overflow="visible"><path d="m-3.921875-.625v-.605469l.632813-.027343c-.136719-.113282-.25-.226563-.335938-.332032-.089844-.105468-.164062-.210937-.21875-.316406-.054688-.101562-.09375-.207031-.117188-.3125-.019531-.105469-.03125-.21875-.03125-.332031 0-.402344.117188-.710938.359376-.917969.238281-.207031.59375-.308594 1.074218-.308594h2.558594v.679688h-2.503906c-.308594 0-.535156.058594-.683594.171875-.144531.113281-.21875.285156-.21875.511719 0 .082031.011719.164062.039062.242187.023438.082031.066407.164063.125.25.0625.085937.144532.179687.25.277344.105469.101562.234376.214843.390626.339843h2.601562v.679688zm0 0"/></symbol><symbol id="A" overflow="visible"><path d="m-1.878906-.425781c-.332032 0-.628906-.046875-.886719-.136719-.261719-.089844-.480469-.222656-.65625-.390625-.179687-.167969-.316406-.367187-.40625-.605469-.09375-.234375-.140625-.496094-.140625-.785156 0-.125.007812-.25.023438-.371094.015624-.121094.039062-.238281.074218-.355468h-1.648437v-.683594h5.519531v.609375l-.742188.023437c.277344.191406.480469.394532.613282.617188.13281225.222656.1992185.460937.1992185.71875 0 .222656-.046875.421875-.140625.589844-.0937495.171874-.2265625.3125-.3945315.429687-.171875.113281-.378906.195313-.617187.253906-.238281.058594-.503907.085938-.796875.085938zm-.042969-.695313c.472656 0 .828125-.070312 1.0625-.207031.230469-.140625.347656-.339844.347656-.59375 0-.171875-.078125-.351563-.230469-.546875-.152343-.191406-.382812-.390625-.683593-.601562h-1.820313c-.050781.113281-.089844.234374-.121094.371093-.027343.136719-.039062.269531-.039062.402344 0 .371094.121094.65625.359375.863281.238281.207032.613281.3125 1.125.3125zm0 0"/></symbol><symbol id="B" overflow="visible"><path d="m3.878906-3.789062c.082032.101562.148438.222656.191406.359374.046876.136719.070313.28125.070313.441407 0 .230469-.042969.4375-.125.625-.085937.191406-.203125.351562-.355469.488281-.152344.132812-.335937.238281-.546875.3125-.210937.074219-.445312.113281-.699219.113281-.1875 0-.359374-.019531-.519531-.058593-.160156-.039063-.289062-.089844-.382812-.148438-.054688.082031-.101563.160156-.140625.234375-.039063.070313-.058594.152344-.058594.242187 0 .113282.054688.207032.160156.277344.109375.074219.25.113282.425782.121094l1.160156.042969c.21875.003906.421875.035156.609375.082031.183593.050781.34375.125.476562.21875.132813.09375.238281.207031.3125.34375.074219.140625.113281.296875.113281.480469 0 .195312-.042968.382812-.128906.558593-.082031.175782-.214844.328126-.390625.464844-.179687.132813-.402343.238282-.675781.316406-.273438.078126-.597656.117188-.972656.117188-.355469 0-.660156-.027344-.910156-.082031-.25-.058594-.457032-.136719-.617188-.238281-.160156-.101563-.277344-.222657-.351562-.359376-.074219-.140624-.109376-.292968-.109376-.460937 0-.214844.046876-.402344.148438-.5625.101562-.1601562.253906-.316406.460938-.464844-.074219-.035156-.140626-.082031-.195313-.132812-.058594-.050781-.101563-.109375-.136719-.171875s-.0625-.132813-.082031-.203125c-.015625-.070313-.023437-.136719-.023437-.207031 0-.1875.042968-.363282.132812-.519532.089844-.160156.195312-.308594.320312-.449218-.058593-.066407-.105468-.132813-.148437-.199219-.042969-.0625-.078125-.132813-.109375-.207031-.03125-.074219-.054688-.15625-.070312-.242188-.015626-.085938-.023438-.1875-.023438-.296875 0-.226563.039062-.4375.125-.625.082031-.191406.199219-.351563.351562-.488281.148438-.132813.332032-.238282.542969-.3125.210938-.074219.449219-.113282.707031-.113282.109376 0 .210938.007813.3125.023438.097657.015625.1875.03125.261719.054688h1.597657v.625zm-2.652344 4.425781c0 .207031.109376.359375.324219.457031.21875.09375.519531.140625.90625.140625.242188 0 .445313-.023437.613281-.066406.164063-.042969.296876-.101563.398438-.171875.101562-.074219.175781-.15625.21875-.246094.042969-.09375.066406-.1875.066406-.285156 0-.179688-.074218-.308594-.222656-.3945315-.144531-.0859375-.367188-.1328125-.671875-.1484375l-1.148437-.039063c-.097657.0625005-.179688.1250005-.242188.1875005-.0625.0624995-.109375.1249995-.144531.1874995-.035157.0625-.0625.125-.074219.1875-.015625.0625-.023438.128907-.023438.191407zm.234376-3.605469c0 .140625.023437.265625.070312.382812.046875.117188.109375.21875.195312.300782.085938.082031.1875.144531.300782.191406.117187.046875.246094.066406.386718.066406.152344 0 .285157-.023437.40625-.074218.117188-.050782.21875-.121094.296876-.210938.082031-.085938.144531-.1875.183593-.300781.042969-.113281.066407-.234375.066407-.355469 0-.140625-.023438-.273438-.070313-.390625s-.113281-.214844-.199219-.296875c-.085937-.082031-.183594-.144531-.300781-.191406s-.242187-.066406-.382813-.066406c-.152343 0-.289062.023437-.40625.078124-.121093.050782-.21875.121094-.300781.207032-.082031.085937-.140625.1875-.183593.300781-.042969.117187-.0625.234375-.0625.359375zm0 0"/></symbol><symbol id="C" overflow="visible"><path d="m4.542969-2.242188c0 .34375-.046875.65625-.144531.945313-.097657.285156-.234376.527344-.417969.730469-.179688.203125-.402344.363281-.664063.4765622-.261718.1132813-.554687.1679688-.886718.1679688-.316407 0-.597657-.046875-.851563-.1445312-.25-.0976558-.460937-.2460938-.636719-.4335938-.171875-.191406-.304687-.425781-.398437-.707031s-.136719-.605469-.136719-.972657c0-.34375.046875-.65625.144531-.9375.097657-.28125.234375-.527343.417969-.730468.179688-.203125.402344-.363282.660156-.472656.261719-.113282.558594-.171876.890625-.171876.316407 0 .597657.050782.847657.148438s.464843.242188.636718.429688c.175782.1875.308594.425781.402344.707031s.136719.601562.136719.964843zm-.78125.035157c0-.273438-.03125-.507813-.089844-.714844-.058594-.203125-.144531-.371094-.257813-.507813-.109374-.136718-.246093-.238281-.40625-.308593-.160156-.066407-.335937-.101563-.535156-.101563-.226562 0-.421875.042969-.585937.132813-.160157.089843-.296875.207031-.398438.359375-.105469.148437-.179687.320312-.230469.519531-.046874.199219-.070312.40625-.070312.621094 0 .273437.027344.511719.089844.71875.058594.203125.144531.375.257812.511719.109375.136718.246094.238281.402344.304687.160156.070313.335938.105469.535156.105469.230469 0 .425782-.046875.589844-.132813.160156-.089843.292969-.210937.398438-.359375.105468-.148437.179687-.324218.226562-.519531.050781-.199219.074219-.40625.074219-.628906zm0 0"/></symbol><symbol id="D" overflow="visible"/><symbol id="E" overflow="visible"><path d="m4.464844 0h-.78125v-2.636719h-2.414063v2.636719h-.78125v-5.742188h.78125v2.429688h2.414063v-2.429688h.78125zm0 0"/></symbol><symbol id="F" overflow="visible"><path d="m4.570312-5.074219h-1.699218v5.074219h-.792969v-5.074219h-1.699219v-.667969h4.191406zm0 0"/></symbol><symbol id="G" overflow="visible"><path d="m4.464844-3.984375c0 .234375-.042969.464844-.132813.695313-.085937.230468-.222656.4375-.40625.617187-.183593.179687-.421875.328125-.707031.441406-.289062.113281-.632812.167969-1.03125.167969h-.710938v2.0625h-.78125v-5.742188h1.617188c.285156 0 .554688.03125.816406.09375.261719.0625.488282.164063.6875.304688.199219.140625.355469.320312.472656.546875.117188.222656.175782.492187.175782.8125zm-.8125.035156c0-.371093-.121094-.652343-.363282-.847656-.242187-.199219-.578124-.296875-1.011718-.296875h-.800782v2.363281h.730469c.460938 0 .820313-.097656 1.070313-.300781s.375-.507812.375-.917969zm0 0"/></symbol><symbol id="H" overflow="visible"><path d="m4.25-6.210938-3.015625 7.15625h-.730469l3.015625-7.15625zm0 0"/></symbol><symbol id="I" overflow="visible"><path d="m4.382812 0h-3.609374v-.710938h1.476562v-4.195312l-1.375.75-.28125-.652344 1.828125-.960937h.675781v5.058593h1.285156zm0 0"/></symbol><symbol id="J" overflow="visible"><path d="m2.4375-1.382812c.101562 0 .195312.015624.285156.054687s.167969.09375.234375.160156c.066407.066407.117188.144531.152344.234375.039063.089844.058594.183594.058594.289063 0 .097656-.019531.191406-.058594.28125-.035156.085937-.089844.164062-.152344.230469-.066406.0664058-.144531.117187-.234375.1562495s-.183594.0546875-.285156.0546875-.195312-.0195312-.285156-.0546875c-.085938-.0390625-.164063-.0898437-.230469-.1562495-.066406-.066407-.117187-.144532-.15625-.230469-.039063-.089844-.054687-.183594-.054687-.28125 0-.105469.015624-.199219.054687-.289063s.089844-.167968.15625-.234375c.066406-.066406.144531-.121093.230469-.160156.089844-.039063.183594-.054687.285156-.054687zm0 0"/></symbol><symbol id="K" overflow="visible"><path d="m.289062-4.414062h.871094l1.082032 2.921874.230468.710938.242188-.730469 1.074218-2.902343h.839844l-1.734375 4.414062h-.878906zm0 0"/></symbol><symbol id="L" overflow="visible"><path d="m4.195312-1.203125c0 .15625-.023437.292969-.078124.417969-.050782.121094-.125.230468-.214844.324218-.089844.097657-.195313.179688-.316406.246094-.121094.066406-.25.121094-.382813.167969-.136719.04296875-.277344.0742188-.421875.09375-.144531.0234375-.285156.03125-.421875.03125-.296875 0-.574219-.0117188-.824219-.0390625s-.496094-.0703125-.734375-.125v-.7031245c.257813.070312.511719.125.769531.164062.253907.039062.507813.058594.757813.058594.367187 0 .636719-.050782.8125-.148438.175781-.101562.265625-.242187.265625-.425781 0-.082031-.015625-.152344-.042969-.214844-.027343-.0625-.078125-.125-.152343-.179687-.070313-.058594-.183594-.117188-.339844-.179688-.152344-.0625-.363282-.128906-.628906-.210937-.199219-.058594-.382813-.125-.550782-.199219-.167968-.074219-.316406-.164062-.4375-.265625-.125-.101563-.222656-.222656-.292968-.359375-.070313-.136719-.105469-.300781-.105469-.488281 0-.125.03125-.257813.085937-.40625.058594-.144531.15625-.28125.292969-.40625s.324219-.230469.558594-.316407c.234375-.082031.527343-.125.878906-.125.171875 0 .363281.011719.574219.03125.210937.019532.433594.050782.660156.097657v.679687c-.238281-.058594-.46875-.101562-.683594-.128906s-.402344-.042969-.558594-.042969c-.191406 0-.351562.015625-.480468.046875-.132813.027344-.238282.066406-.316406.121094-.082032.050781-.140626.109375-.175782.179688-.035156.066406-.050781.140624-.050781.21875 0 .082031.015625.152343.042969.21875.03125.0625.089844.125.171875.183593.085937.0625.199219.121094.351562.183594.148438.058594.34375.125.582031.195313.261719.074218.480469.15625.660157.238281.179687.082031.324219.175781.433593.277343.113282.101563.191407.21875.242188.347657.046875.128906.070312.277343.070312.441406zm0 0"/></symbol><symbol id="M" overflow="visible"><path d="m4.429688 0h-3.785157v-.6875l1.488281-1.476562c.242188-.238282.4375-.445313.59375-.621094.152344-.175782.269532-.335938.355469-.480469.082031-.144531.140625-.285156.167969-.414063.03125-.128906.046875-.265624.046875-.414062 0-.140625-.019531-.277344-.058594-.402344-.039062-.128906-.097656-.242187-.175781-.339844-.078125-.09375-.179688-.171874-.308594-.226562-.125-.054688-.277344-.082031-.449218-.082031-.246094 0-.464844.050781-.664063.160156s-.382813.25-.550781.421875l-.421875-.503906c.214843-.230469.464843-.410156.75-.550782.28125-.136718.609375-.207031.984375-.207031.253906 0 .488281.039063.699218.117188.207032.074219.390626.183593.542969.328125.152344.144531.269531.320312.351563.527344.082031.207031.125.441406.125.703124 0 .21875-.027344.421876-.085938.609376s-.148437.375-.265625.5625c-.121093.1875-.269531.378906-.449219.578124-.179687.199219-.394531.417969-.640624.652344l-1.039063 1.015625h2.789063zm0 0"/></symbol><symbol id="N" overflow="visible"><path d="m0 2.824219v-.542969l1.121094-.523438c.085937-.039062.160156-.078124.214844-.121093.054687-.039063.101562-.085938.132812-.132813.035156-.046875.058594-.097656.074219-.15625.011719-.054687.019531-.117187.019531-.1875v-.226562h-1.5625v-.476563h3.511719v.9375c0 .207031-.023438.382813-.070313.527344-.042968.148437-.105468.269531-.1875.363281-.078125.09375-.175781.160156-.289062.207032-.113282.042968-.242188.0625-.378906.0625-.109376 0-.210938-.015626-.308594-.046876s-.1875-.078124-.265625-.144531c-.082031-.0625-.148438-.140625-.207031-.234375-.058594-.09375-.101563-.203125-.132813-.324218-.03125.097656-.09375.183593-.175781.25-.085938.070312-.199219.140624-.339844.210937zm2.546875-.765625c.1875 0 .328125-.058594.421875-.175782.09375-.117187.136719-.285156.136719-.496093v-.453125h-1.160157v.386718c0 .113282.015626.214844.039063.304688.027344.089844.066406.167969.117187.230469.050782.066406.113282.113281.1875.148437.074219.035156.160157.054688.257813.054688zm0 0"/></symbol><symbol id="O" overflow="visible"><path d="m1.792969 2.828125c-.167969 0-.328125-.011719-.480469-.039063-.15625-.027343-.300781-.066406-.429688-.125-.132812-.058593-.253906-.132812-.363281-.222656s-.199219-.203125-.277343-.335937c-.078126-.132813-.136719-.285157-.179688-.460938-.0429688-.175781-.0625-.375-.0625-.601562v-.75h3.511719v.90625c0 .546875-.144531.953125-.425781 1.222656s-.710938.40625-1.292969.40625zm-.035157-.503906c.25 0 .460938-.023438.632813-.066407.171875-.046874.308594-.121093.414063-.214843.105468-.09375.183593-.214844.230468-.355469.046875-.144531.070313-.3125.070313-.507812v-.410157h-2.691407v.359375c0 .796875.449219 1.195313 1.34375 1.195313zm0 0"/></symbol><symbol id="P" overflow="visible"><path d="m3.101562 2.792969v-1.039063h-3.101562v-.484375h3.101562v-1.039062h.410157v2.5625zm0 0"/></symbol><symbol id="Q" overflow="visible"><path d="m1.777344 2.875c-.316406 0-.585938-.035156-.816406-.109375-.230469-.074219-.417969-.175781-.566407-.300781-.148437-.125-.261719-.273438-.3359372-.445313-.0703126-.167969-.1054688-.347656-.1054688-.535156 0-.226563.0390625-.421875.1210938-.589844.0820312-.167969.1992192-.304687.3515622-.414062.15625-.109375.34375-.191407.5625-.246094.222657-.054687.472657-.082031.75-.082031.3125 0 .582031.039062.808594.109375.230469.074219.421875.175781.570313.300781.148437.125.261718.273438.332031.441406.074219.167969.109375.347656.109375.535156 0 .226563-.042969.421876-.125.589844-.082032.167969-.199219.304688-.351563.417969-.152343.109375-.339843.191406-.558593.246094-.222657.054687-.46875.082031-.746094.082031zm-.035156-.496094c.207031 0 .394531-.015625.566406-.046875s.316406-.082031.441406-.152343c.125-.070313.21875-.160157.289062-.269532.066407-.109375.101563-.242187.101563-.398437 0-.148438-.039063-.28125-.109375-.386719-.074219-.109375-.171875-.199219-.296875-.269531-.125-.070313-.269531-.121094-.4375-.15625-.167969-.03125-.34375-.050781-.53125-.050781-.207031 0-.398437.015624-.570313.050781-.171874.03125-.316406.082031-.4375.152343-.125.066407-.21875.15625-.289062.265626-.066406.109374-.101562.242187-.101562.394531 0 .152343.035156.28125.109374.390625.074219.109375.171876.199218.296876.269531s.269531.121094.433593.15625c.167969.035156.347657.050781.535157.050781zm0 0"/></symbol><symbol id="R" overflow="visible"><path d="m0 2.644531v-2.019531h3.511719v.488281h-3.101563v1.53125zm0 0"/></symbol><symbol id="S" overflow="visible"/><symbol id="T" overflow="visible"><path d="m3.792969 2.597656-4.371094-1.84375v-.445312l4.371094 1.84375zm0 0"/></symbol><symbol id="U" overflow="visible"><path d="m1.050781 2.726562c-.167969 0-.316406-.03125-.449219-.097656-.128906-.0625-.238281-.15625-.328124-.277344-.089844-.121093-.15625-.265624-.2031255-.4375-.046875-.171874-.0703125-.363281-.0703125-.570312v-.917969h3.511719v1.003907c0 .78125-.285157 1.171874-.855469 1.171874-.191406 0-.351562-.042968-.488281-.136718-.136719-.089844-.238281-.234375-.304688-.441406-.019531.097656-.046875.1875-.089843.269531-.042969.085937-.097657.160156-.167969.226562-.066407.0625-.148438.113281-.242188.152344s-.195312.054687-.3125.054687zm1.539063-.621093c.074218 0 .140625-.011719.203125-.03125.066406-.023438.121093-.058594.164062-.113281.046875-.054688.082031-.125.109375-.21875.027344-.089844.039063-.207032.039063-.347657v-.492187h-1.097657v.476562c0 .109375.011719.210938.035157.296875.023437.089844.058593.167969.109375.230469.046875.0625.109375.113281.179687.148438.074219.035156.160157.050781.257813.050781zm-1.554688.117187c.089844 0 .167969-.019531.242188-.058594.070312-.039062.128906-.089843.179687-.164062.050781-.070312.085938-.15625.113281-.261719.027344-.101562.039063-.21875.039063-.347656v-.488281h-1.207031v.503906c0 .273438.050781.480469.152344.613281.101562.132813.261718.203125.480468.203125zm0 0"/></symbol><symbol id="V" overflow="visible"><path d="m3.105469 1.269531v-.808593h.40625v2.101562h-.40625v-.808594h-2.695313v.808594h-.410156v-2.101562h.410156v.808593zm0 0"/></symbol><symbol id="W" overflow="visible"><path d="m0 2.535156v-1.996094h3.511719v1.996094h-.40625v-1.515625h-1.085938v1.457031h-.402343v-1.457031h-1.207032v1.515625zm0 0"/></symbol><symbol id="X" overflow="visible"><path d="m0 2.8125v-.601562l1.722656-1.3125h-1.722656v-.480469h3.511719v.480469h-1.632813l1.632813 1.285156v.566406l-1.667969-1.386719zm0 0"/></symbol><symbol id="Y" overflow="visible"/><symbol id="Z" overflow="visible"><path d="m3.449219-3.367188c.074219.089844.128906.195313.167969.320313.042968.121094.0625.25.0625.390625 0 .203125-.039063.390625-.109376.554688-.074218.167968-.179687.3125-.316406.433593-.136718.121094-.296875.214844-.488281.277344-.1875.066406-.394531.101563-.621094.101563-.164062 0-.316406-.015626-.460937-.054688-.144532-.035156-.257813-.078125-.339844-.128906-.050781.074218-.089844.140625-.125.207031s-.050781.136719-.050781.21875c0 .097656.046875.179687.144531.246094.09375.066406.21875.101562.375.105469l1.03125.039062c.195312.003906.375.03125.539062.074219.167969.042969.308594.109375.429688.191406.117188.082031.210938.1875.273438.3085938.066406.1210937.101562.2656252.101562.4257812 0 .175781-.039062.339844-.113281.496094s-.191407.292968-.347657.410156c-.160156.121094-.359374.214844-.601562.285156-.242188.070313-.53125.105469-.863281.105469-.316407 0-.589844-.023437-.808594-.078125-.222656-.050781-.40625-.117188-.550781-.210938-.144532-.089843-.246094-.195312-.3125-.320312-.066406-.121094-.097656-.257812-.097656-.40625 0-.191406.042968-.355469.132812-.5.089844-.1445312.226562-.28125.410156-.414062-.066406-.03125-.125-.070313-.175781-.117188s-.089844-.097656-.121094-.15625c-.03125-.054688-.054687-.113281-.070312-.175781s-.023438-.125-.023438-.183594c0-.167969.039063-.324219.121094-.464844.078125-.140625.171875-.273437.28125-.398437-.050781-.058594-.09375-.117188-.132813-.175782-.035156-.058593-.070312-.117187-.09375-.1875-.027343-.066406-.050781-.136718-.0625-.210937-.015624-.078125-.023437-.167969-.023437-.265625 0-.203125.039063-.390625.109375-.554688.074219-.167968.179688-.3125.3125-.433593.136719-.121094.296875-.214844.484375-.277344.191406-.066406.398437-.101563.628906-.101563.097657 0 .1875.007813.277344.019532.089844.011718.167969.03125.234375.050781h1.421875v.554687zm-2.359375 3.933594c0 .183594.097656.320313.289062.402344.191406.085938.460938.128906.804688.128906.214844 0 .398437-.019531.542968-.058594.148438-.039062.265626-.089843.359376-.15625.089843-.0625.152343-.132812.191406-.21875.039062-.082031.058594-.164062.058594-.25 0-.160156-.066407-.277343-.195313-.351562-.128906-.0742188-.328125-.1210938-.597656-.1328125l-1.023438-.0351565c-.085937.058594-.15625.1132815-.214843.167969-.054688.054688-.097657.109375-.128907.164062-.03125.058594-.054687.113282-.066406.171876-.011719.054687-.019531.109374-.019531.167968zm.207031-3.207031c0 .125.019531.238281.0625.34375s.101563.191406.175781.265625c.074219.074219.164063.128906.269532.171875.101562.039063.214843.058594.339843.058594.136719 0 .253907-.023438.363281-.066407.105469-.046874.191407-.109374.265626-.1875.070312-.078124.125-.167968.164062-.269531.035156-.101562.054688-.207031.054688-.316406 0-.125-.019532-.238281-.0625-.34375-.042969-.105469-.101563-.191406-.175782-.265625-.074218-.074219-.164062-.128906-.269531-.171875-.101563-.039063-.214844-.058594-.339844-.058594-.136719 0-.253906.023438-.363281.070313-.105469.046875-.191406.109375-.265625.183594-.070313.078124-.125.167968-.164063.269531-.035156.101562-.054687.207031-.054687.316406zm0 0"/></symbol><symbol id="aa" overflow="visible"><path d="m4.039062-1.992188c0 .304688-.042968.585938-.128906.835938-.085937.253906-.210937.472656-.371094.65625-.160156.179688-.359374.320312-.589843.421875-.230469.0976562-.496094.1484375-.789063.1484375-.28125 0-.535156-.0429687-.753906-.1328125-.222656-.085938-.414062-.214844-.570312-.382812-.152344-.167969-.273438-.378907-.351563-.628907-.082031-.25-.125-.539062-.125-.863281 0-.304688.042969-.582031.128906-.835938.085938-.25.210938-.464843.371094-.648437.160156-.179687.359375-.320313.589844-.421875.230469-.097656.496093-.148438.789062-.148438.28125 0 .535157.042969.753907.132813.222656.085937.414062.210937.570312.382813.152344.167968.273438.375.351562.625.082032.25.125.535156.125.859374zm-.695312.03125c0-.242187-.027344-.453124-.078125-.632812-.054687-.183594-.132813-.335938-.230469-.453125-.097656-.121094-.21875-.214844-.363281-.273437-.140625-.0625-.296875-.09375-.472656-.09375-.203125 0-.378907.039062-.519531.117187-.144532.082031-.265626.1875-.359376.320313-.089843.132812-.15625.289062-.203124.460937-.042969.175781-.0625.363281-.0625.554687 0 .242188.027343.453126.078124.636719.054688.183594.132813.332031.230469.457031.097657.121094.21875.210938.359375.273438.140625.058594.300782.089844.476563.089844.203125 0 .378906-.039063.519531-.121094.144531-.078125.265625-.183594.359375-.316406.089844-.132813.15625-.285156.203125-.464844.042969-.175781.0625-.359375.0625-.554688zm0 0"/></symbol><symbol id="ab" overflow="visible"><path d="m3.96875 0h-.695312v-2.34375h-2.144532v2.34375h-.695312v-5.105469h.695312v2.160157h2.144532v-2.160157h.695312zm0 0"/></symbol><symbol id="ac" overflow="visible"><path d="m4.0625-4.511719h-1.511719v4.511719h-.703125v-4.511719h-1.511718v-.59375h3.726562zm0 0"/></symbol><symbol id="ad" overflow="visible"><path d="m3.96875-3.542969c0 .207031-.039062.414063-.117188.621094-.078124.203125-.199218.386719-.363281.546875-.164062.160156-.375.292969-.628906.390625-.253906.101563-.558594.152344-.914063.152344h-.632812v1.832031h-.695312v-5.105469h1.4375c.253906 0 .496093.027344.726562.082031.230469.058594.4375.148438.609375.273438.175781.125.316406.285156.421875.484375s.15625.4375.15625.722656zm-.722656.03125c0-.328125-.105469-.578125-.324219-.753906-.214844-.175781-.511719-.261719-.898437-.261719h-.710938v2.101563h.648438c.410156 0 .726562-.089844.953124-.269531.222657-.179688.332032-.453126.332032-.816407zm0 0"/></symbol><symbol id="ae" overflow="visible"><path d="m3.777344-5.519531-2.679688 6.359375h-.648437l2.679687-6.359375zm0 0"/></symbol><symbol id="af" overflow="visible"><path d="m3.894531 0h-3.207031v-.632812h1.3125v-3.726563l-1.222656.664063-.25-.578126 1.625-.855468h.601562v4.496094h1.140625zm0 0"/></symbol><symbol id="ag" overflow="visible"><path d="m2.167969-1.230469c.089843 0 .171875.015625.253906.050781.078125.035157.148437.082032.203125.140626.058594.058593.105469.128906.140625.210937.035156.078125.050781.164063.050781.253906 0 .089844-.015625.171875-.050781.25s-.078125.144531-.140625.207031c-.058594.0585942-.125.101563-.203125.1367192-.082031.0351563-.164063.0507813-.253906.0507813-.089844 0-.175781-.015625-.253907-.0507813-.078124-.0351562-.148437-.0820312-.203124-.1367192-.058594-.058593-.105469-.128906-.140626-.207031-.035156-.078125-.050781-.160156-.050781-.25 0-.089843.015625-.175781.050781-.253906.035157-.082031.078126-.152344.140626-.210937.058593-.058594.125-.105469.203124-.140626.078126-.035156.164063-.050781.253907-.050781zm0 0"/></symbol><symbol id="ah" overflow="visible"><path d="m4.359375 0h-.757813l-.355468-1.113281h-2.125l-.359375 1.113281h-.7226565l1.6953125-5.105469h.953125zm-1.3125-1.734375-.863281-2.730469-.863282 2.730469zm0 0"/></symbol><symbol id="ai" overflow="visible"><path d="m4.382812-5.105469-1.734374 5.105469h-.9375l-1.695313-5.105469h.785156l1.101563 3.441407.3125 1.007812.320312-1.007812 1.105469-3.441407zm0 0"/></symbol><symbol id="aj" overflow="visible"><path d="m3.929688-4.230469c-.191407-.101562-.386719-.179687-.585938-.238281-.199219-.054688-.417969-.082031-.65625-.082031-.269531 0-.511719.046875-.722656.144531-.210938.097656-.386719.234375-.535156.40625-.144532.175781-.253907.390625-.328126.636719-.078124.246093-.117187.519531-.117187.820312 0 .3125.03125.59375.09375.839844s.160156.457031.292969.628906c.132812.171875.300781.304688.511718.394531.207032.089844.453126.136719.742188.136719.050781 0 .101562-.003906.160156-.007812.058594-.003907.113282-.011719.171875-.019531.058594-.011719.113281-.023438.167969-.035157.050781-.011719.097656-.027343.140625-.042969v-1.625h-1.042969v-.574218h1.730469v2.609375c-.105469.050781-.21875.09375-.335937.132812-.121094.0390628-.242188.0703128-.367188.0976565-.121094.0273437-.246094.046875-.367188.0585937-.121093.0117188-.242187.0195313-.355468.0195313-.347656 0-.664063-.0546875-.941406-.1640625-.28125-.109375-.519532-.273438-.71875-.484375-.195313-.214844-.34375-.484375-.453126-.804687-.105468-.320313-.15625-.691407-.15625-1.113282 0-.417968.058594-.792968.175782-1.128906.117187-.332031.28125-.609375.496094-.84375.210937-.230469.464843-.40625.765624-.523438.296876-.121093.625-.183593.984376-.183593.230468 0 .445312.019531.65625.058593.207031.042969.402343.105469.59375.195313zm0 0"/></symbol><symbol id="ak" overflow="visible"><path d="m3.910156-2.839844c0 .496094-.058594.925782-.179687 1.285156-.121094.355469-.296875.648438-.53125.882813-.234375.230469-.523438.398437-.871094.507813-.347656.1093745-.746094.164062-1.199219.164062h-.425781v-.59375h.472656c.335938 0 .625-.035156.871094-.101562.246094-.066407.449219-.167969.609375-.296876.164062-.132812.289062-.292968.375-.484374.085938-.1875.140625-.402344.160156-.644532l.015625-.160156c-.164062.097656-.351562.171875-.566406.234375-.214844.058594-.445313.085937-.695313.085937-.257812 0-.484374-.039062-.679687-.113281s-.359375-.179687-.484375-.316406c-.128906-.136719-.226562-.296875-.292969-.484375-.066406-.183594-.097656-.386719-.097656-.605469 0-.238281.042969-.457031.128906-.664062.085938-.207031.207031-.386719.363281-.535157.152344-.152343.339844-.273437.554688-.363281.214844-.089843.453125-.132812.714844-.132812.253906 0 .488281.042969.699218.125.214844.082031.402344.21875.558594.402343.15625.1875.277344.429688.367188.726563s.132812.65625.132812 1.082031zm-1.789062-1.777344c-.144532 0-.28125.023438-.402344.070313-.125.050781-.234375.121094-.320312.210937-.089844.09375-.164063.207032-.214844.34375-.050782.136719-.078125.289063-.078125.464844 0 .160156.019531.300782.058593.425782.035157.125.09375.230468.171876.320312.082031.085938.183593.152344.308593.199219s.273438.070312.445313.070312c.097656 0 .195312-.007812.300781-.027343.101563-.019532.203125-.042969.296875-.074219.097656-.03125.191406-.066407.28125-.109375.089844-.042969.167969-.085938.238281-.132813 0-.335937-.023437-.617187-.074219-.839843-.050781-.226563-.121093-.40625-.214843-.546876-.09375-.136718-.207031-.230468-.339844-.289062-.136719-.058594-.289063-.085938-.457031-.085938zm0 0"/></symbol><symbol id="al" overflow="visible"><path d="m3.808594-1.632812c0 .253906-.054688.484374-.164063.691406-.109375.207031-.261719.386718-.449219.535156-.191406.152344-.417968.269531-.679687.3515625-.261719.0820313-.542969.125-.84375.125-.074219 0-.15625 0-.242187-.0078125-.089844-.0039062-.175782-.0078125-.261719-.015625-.085938-.0039062-.167969-.0117188-.253907-.0195312-.082031-.0078126-.152343-.015625-.21875-.0273438v-.617188c.140626.035157.300782.058594.484376.074219.179687.015625.363281.023438.546874.023438.207032 0 .394532-.023438.5625-.074219.167969-.050781.308594-.121094.425782-.210938.117187-.09375.207031-.207031.269531-.335937.0625-.132813.09375-.28125.09375-.445313 0-.316406-.113281-.546874-.34375-.695312-.226563-.144531-.554687-.214844-.980469-.214844h-.96875v-2.609375h2.75v.59375h-2.109375v1.433594h.445313c.246094 0 .484375.023437.714844.066406.230468.042969.4375.121094.617187.230469.183594.113281.328125.261719.4375.445312.113281.1875.167969.421876.167969.703126zm0 0"/></symbol><symbol id="am" overflow="visible"><path d="m3.839844-1.550781c0 .222656-.046875.433593-.136719.628906-.089844.199219-.226563.371094-.410156.515625-.183594.148438-.410157.265625-.6875.3515625-.277344.0820313-.597657.125-.964844.125-.203125 0-.386719-.0078125-.546875-.0195313-.160156-.0117187-.3125-.03125-.453125-.0507812v-.609375c.160156.027344.332031.050781.511719.066406.179687.015625.363281.023438.550781.023438.253906 0 .472656-.023438.65625-.066407.179687-.046874.328125-.113281.441406-.199218.113281-.085938.199219-.191406.25-.3125s.078125-.261719.078125-.414063c0-.140625-.03125-.261719-.09375-.367187-.0625-.105469-.152344-.191406-.261718-.261719-.113282-.070313-.25-.125-.40625-.15625-.160157-.035156-.332032-.054687-.519532-.054687h-.582031v-.558594h.589844c.152343 0 .292969-.019532.417969-.058594.128906-.042969.234374-.101562.328124-.175781.089844-.074219.15625-.167969.203126-.277344.050781-.113281.074218-.238281.074218-.378906 0-.273438-.082031-.472657-.25-.597657-.167968-.125-.410156-.1875-.734375-.1875-.171875 0-.347656.015626-.53125.050782-.183593.035156-.378906.085937-.585937.152344v-.59375c.089844-.03125.183594-.058594.285156-.085938.097656-.023438.199219-.042969.296875-.0625.101563-.015625.203125-.027344.300781-.039062.097656-.007813.195313-.011719.285156-.011719.269532 0 .507813.027343.714844.089843.207032.058594.378906.140626.515625.25.136719.109376.242188.242188.3125.398438.070313.15625.105469.332031.105469.527344 0 .292968-.074219.535156-.226562.734375-.148438.199219-.351563.355469-.613282.472656.132813.019531.261719.0625.394532.125.128906.0625.242187.140625.34375.242187.105468.097657.1875.210938.25.34375.066406.132813.097656.28125.097656.441407zm0 0"/></symbol><symbol id="an" overflow="visible"><path d="m4.191406-1.128906h-.871094v1.128906h-.695312v-1.128906h-2.457031v-.597656l2.175781-3.378907h.976562v3.378907h.871094zm-1.566406-3.320313-1.777344 2.722657h1.777344zm0 0"/></symbol><symbol id="ao" overflow="visible"><path d="m3.9375-1.28125c0 .214844-.042969.40625-.132812.578125-.089844.167969-.210938.308594-.371094.421875s-.347656.203125-.5625.2617188c-.214844.0585937-.449219.0898437-.703125.0898437-.277344 0-.523438-.03125-.738281-.09375-.210938-.0625-.386719-.1484375-.53125-.2617185-.144532-.113282-.25-.246094-.324219-.398438s-.109375-.324218-.109375-.507812c0-.3125.085937-.582032.261718-.808594.175782-.226562.445313-.433594.808594-.617188-.332031-.167968-.578125-.359374-.730468-.5625-.152344-.207031-.230469-.445312-.230469-.714843 0-.164063.035156-.324219.101562-.476563.066407-.152344.167969-.289062.308594-.410156.136719-.121094.304687-.214844.511719-.289062.207031-.070313.449218-.105469.726562-.105469.261719 0 .496094.027343.691406.082031.199219.058594.367188.136719.503907.242188.136719.105468.238281.230468.304687.378906.066406.148437.101563.3125.101563.496094 0 .296874-.082031.550781-.246094.757812-.167969.207031-.402344.390625-.707031.546875.152344.074219.292968.160156.421875.25.128906.089844.242187.191406.339843.304687.097657.113282.171876.238282.226563.375.050781.136719.078125.292969.078125.460938zm-.808594-2.640625c0-.230469-.082031-.40625-.246094-.515625-.160156-.113281-.390624-.171875-.683593-.171875s-.519531.054687-.683594.167969c-.160156.113281-.242187.28125-.242187.503906 0 .101562.019531.195312.058593.28125.039063.085938.097657.167969.183594.242188.082031.074218.183594.148437.304687.222656.121094.074218.269532.148437.4375.222656.292969-.136719.511719-.28125.65625-.429688.144532-.152343.214844-.324218.214844-.523437zm.070313 2.691406c0-.097656-.015625-.191406-.046875-.28125-.03125-.089843-.085938-.179687-.167969-.269531s-.1875-.175781-.324219-.265625c-.136718-.089844-.308594-.179687-.515625-.273437-.175781.085937-.324219.171874-.449219.257812-.121093.082031-.21875.167969-.289062.257812-.074219.085938-.128906.175782-.160156.269532s-.046875.191406-.046875.296875c0 .117187.027343.222656.074219.308593.050781.089844.121093.167969.210937.230469s.195313.109375.316406.140625c.121094.03125.253907.046875.398438.046875.136719 0 .269531-.015625.390625-.042969.121094-.027343.230468-.070312.316406-.132812.089844-.058594.164062-.132812.214844-.21875.050781-.089844.078125-.199219.078125-.324219zm0 0"/></symbol><symbol id="ap" overflow="visible"><path d="m4.207031 0h-.679687l-.101563-3.183594-.042969-1.222656-.238281.710938-.753906 2.03125h-.480469l-.71875-1.953126-.238281-.789062-.015625 1.277344-.089844 3.128906h-.65625l.25-5.105469h.824219l.6875 1.921875.222656.648438.214844-.648438.722656-1.921875h.847657zm0 0"/></symbol><symbol id="aq" overflow="visible"><path d="m1.847656-4.519531h-1.175781v-.585938h3.054687v.585938h-1.175781v3.925781h1.175781v.59375h-3.054687v-.59375h1.175781zm0 0"/></symbol><symbol id="ar" overflow="visible"><path d="m3.9375 0h-.90625l-1.488281-3.183594-.429688-1.023437v4.207031h-.648437v-5.105469h.894531l1.417969 3.015625.511718 1.167969v-4.183594h.648438zm0 0"/></symbol><symbol id="as" overflow="visible"><path d="m3.9375 0h-3.363281v-.609375l1.320312-1.3125c.214844-.214844.390625-.398437.527344-.554687s.242187-.296876.316406-.429688c.074219-.128906.125-.25.152344-.363281s.039063-.238281.039063-.371094c0-.125-.015626-.242187-.050782-.359375-.035156-.113281-.085937-.210938-.15625-.296875-.070312-.085937-.160156-.152344-.273437-.203125s-.246094-.074219-.402344-.074219c-.214844 0-.414063.046875-.589844.144531-.175781.097657-.339843.222657-.488281.375l-.375-.449218c.191406-.203125.414062-.367188.664062-.488282.253907-.121093.546876-.183593.878907-.183593.226562 0 .433593.035156.621093.101562.183594.066407.34375.164063.480469.292969s.238281.285156.316407.46875c.074218.183594.109374.394531.109374.625 0 .195312-.027343.375-.078124.542969-.050782.167969-.132813.332031-.234376.496093-.105468.167969-.242187.339844-.398437.515626-.160156.175781-.351563.371093-.570313.582031l-.925781.902343h2.480469zm0 0"/></symbol><symbol id="at" overflow="visible"><path d="m4-1.617188c0 .234376-.042969.453126-.125.660157-.085938.207031-.207031.386719-.363281.535156-.15625.152344-.34375.273437-.566407.359375-.21875.0898438-.460937.1328125-.730468.1328125-.28125 0-.53125-.046875-.746094-.1328125-.214844-.089844-.398438-.230469-.542969-.414062-.144531-.1875-.257812-.421876-.332031-.707032s-.113281-.621094-.113281-1.007812c0-.261719.015625-.511719.050781-.757813.035156-.246093.089844-.476562.167969-.691406s.183593-.414063.3125-.59375c.128906-.179687.292969-.335937.488281-.460937.191406-.128907.421875-.230469.683594-.304688.261718-.070312.566406-.105469.914062-.105469h.503906v.59375h-.546874c-.304688 0-.570313.035157-.792969.109375-.222657.074219-.410157.175782-.5625.308594-.152344.132812-.265625.292969-.347657.480469-.082031.1875-.132812.398437-.152343.628906l-.015625.160156c.164062-.097656.355468-.175781.566406-.230469.214844-.058593.449219-.089843.699219-.089843.257812 0 .484375.039062.675781.113281.195312.074219.359375.179688.484375.3125.128906.136719.226563.296875.292969.484375s.097656.394531.097656.617187zm-.710938.042969c0-.15625-.019531-.296875-.054687-.425781-.039063-.125-.097656-.230469-.179687-.320312-.082032-.085938-.183594-.152344-.304688-.203126-.125-.046874-.273438-.070312-.445312-.070312-.097657 0-.199219.007812-.300782.027344-.101562.019531-.199218.042968-.300781.074218-.097656.035157-.1875.070313-.277344.113282-.089843.042968-.167969.085937-.242187.132812 0 .335938.023437.617188.070312.839844.046875.226562.117188.40625.207032.542969.09375.136719.207031.230469.34375.289062.136718.058594.292968.085938.46875.085938.148437 0 .285156-.023438.40625-.074219.125-.046875.234374-.117188.320312-.210938.089844-.09375.164062-.207031.210938-.34375.050781-.132812.078124-.285156.078124-.457031zm0 0"/></symbol><symbol id="au" overflow="visible"><path d="m4.304688 0h-.878907l-1.242187-2.0625-1.246094 2.0625h-.8671875l1.6992185-2.609375-1.5625-2.496094h.824219l1.167969 1.921875 1.175781-1.921875h.800781l-1.566406 2.464844zm0 0"/></symbol><symbol id="av" overflow="visible"><path d="m3.894531-1.382812c0 .242187-.050781.453124-.148437.636718s-.238282.332032-.414063.457032c-.175781.121093-.390625.210937-.636719.2695308-.25.0585937-.523437.0898437-.824218.0898437-.136719 0-.269532-.0039063-.402344-.015625-.136719-.0117187-.265625-.0234375-.390625-.0390625-.121094-.015625-.238281-.0351562-.347656-.0546875s-.207031-.0429687-.296875-.0664065v-.671875c.195312.074219.414062.128906.660156.171875.242188.042969.519531.0625.828125.0625.222656 0 .414063-.019531.570313-.050781.160156-.035156.289062-.089844.390624-.15625.097657-.070312.171876-.15625.21875-.253906.042969-.097656.066407-.210938.066407-.339844 0-.136719-.039063-.257812-.113281-.351562-.078126-.097657-.179688-.1875-.304688-.265626-.125-.074218-.265625-.144531-.429688-.210937-.160156-.0625-.320312-.128906-.488281-.195313-.167969-.066406-.332031-.140624-.488281-.21875-.160156-.082031-.304688-.175781-.429688-.28125-.125-.109374-.226562-.238281-.304687-.382812-.074219-.144531-.113281-.320312-.113281-.519531 0-.175781.035156-.347657.109375-.515625.074219-.167969.1875-.320313.339843-.449219.152344-.132813.351563-.238281.59375-.320313.238282-.082031.527344-.121093.859376-.121093.085937 0 .179687.003906.28125.011719.097656.007812.199218.019531.304687.03125.101563.015624.203125.03125.304687.050781.097657.019531.191407.039062.277344.058593v.625c-.199218-.058593-.402344-.101562-.601562-.132812-.199219-.027344-.394532-.042969-.582032-.042969-.398437 0-.691406.066407-.878906.199219s-.28125.3125-.28125.535156c0 .136719.039063.257813.113282.355469.078124.097656.179687.1875.304687.265625s.265625.148438.429687.210938c.160157.066406.320313.132812.488282.199218.167968.066406.332031.140625.488281.222656.160156.082032.304687.175782.429687.289063.125.109375.226563.238281.304688.386719.074219.148437.113281.324218.113281.527344zm0 0"/></symbol><symbol id="aw" overflow="visible"><path d="m4.113281-2.609375c0 .246094-.019531.480469-.058593.703125-.035157.222656-.097657.433594-.179688.625s-.191406.367188-.324219.523438c-.132812.160156-.296875.292968-.488281.40625-.191406.113281-.417969.199218-.671875.257812-.253906.0625-.546875.09375-.871094.09375h-1.09375v-5.105469h1.316407c.796874 0 1.390624.207031 1.78125.613281.394531.410157.589843 1.039063.589843 1.882813zm-.730469.050781c0-.363281-.035156-.667968-.101562-.917968s-.171875-.453126-.308594-.605469c-.136718-.152344-.3125-.265625-.519531-.332031-.207031-.070313-.453125-.105469-.734375-.105469h-.597656v3.917969h.519531c1.160156 0 1.742187-.652344 1.742187-1.957032zm0 0"/></symbol><symbol id="ax" overflow="visible"><path d="m3.6875 0h-2.902344v-5.105469h2.902344v.585938h-2.207031v1.582031h2.121093v.585938h-2.121093v1.757812h2.207031zm0 0"/></symbol><symbol id="ay" overflow="visible"><path d="m4.054688-2.550781c0 .390625-.039063.746093-.117188 1.066406-.078125.324219-.195312.601563-.355469.828125-.160156.230469-.355469.410156-.589843.539062-.238282.1250005-.515626.1875005-.832032.1875005-.273437 0-.523437-.0507813-.746094-.15625-.222656-.1015625-.414062-.2578125-.574218-.4726565s-.28125-.484375-.367188-.816406c-.085937-.332031-.128906-.722656-.128906-1.175781 0-.390625.039062-.746094.117188-1.070313.082031-.324218.199218-.597656.359374-.832031.15625-.230469.351563-.40625.589844-.53125.238282-.128906.511719-.191406.828125-.191406.273438 0 .523438.050781.746094.152343.222656.105469.414063.265626.574219.476563.160156.214844.28125.488281.367187.820313.085938.332031.128907.722656.128907 1.175781zm-.6875.023437c0-.089844-.003907-.175781-.007813-.261718-.007813-.089844-.015625-.175782-.023437-.257813l-2.160157 1.605469c.039063.136718.089844.261718.148438.375.058593.113281.132812.214844.214843.292968.085938.082032.183594.148438.289063.195313.109375.042969.234375.066406.371094.066406.175781 0 .339843-.042969.480469-.128906.144531-.085937.269531-.214844.371093-.382813.101563-.167968.179688-.378906.234375-.632812.054688-.25.082032-.539062.082032-.871094zm-2.335938-.046875v.242188c.003906.082031.007812.160156.015625.234375l2.160156-1.597656c-.039062-.132813-.089843-.253907-.148437-.363282s-.132813-.203125-.214844-.285156c-.082031-.078125-.179688-.140625-.285156-.183594-.105469-.042968-.226563-.066406-.359375-.066406-.175781 0-.339844.042969-.480469.128906-.144531.085938-.269531.214844-.371094.386719-.101562.167969-.179687.378906-.234375.632813-.054687.25-.082031.539062-.082031.871093zm0 0"/></symbol><symbol id="az" overflow="visible"><path d="m3.910156-4.472656-2.140625 4.472656h-.777343l2.222656-4.472656h-2.757813v-.632813h3.453125zm0 0"/></symbol><path d="m0 0h685v286h-685z" fill="#f2f2f2"/><path d="m55 233h600v-200h-600zm0 0" fill="#fff"/><path d="m55 43.679688v189.519531h599v-185.125h-15v-.644531h-16v-.921876h-16v-1.046874h-16v-1.175782h-15v-.507812h-16v-.628906h-16v-.300782h-16v-.148437h-16v-.023438h-15v-.234375h-16v-.21875h-16v-.15625h-16v-.175781h-16v-.355469h-15v-.347656h-16v-.34375h-16v.066406h-16v-.226562h-16v.117187h-15v.105469h-16v-.121094h-16v-.890625h-16v-.4375h-15v-.03125h-16v.167969h-16v.28125h-16v.148438h-16v-.09375h-15v.347656h-16v.367187h-16v.132813h-16v.957031h-16v-.121094h-15v1.367188h-16v.753906h-16v-.582031h-16v.527344zm0 0" fill="#7648ec"/><path d="m55 127.300781v105.898438h599v-101.183594h-15v-.246094h-16v-.128906h-16v-.160156h-16v-.101563h-15v-.191406h-16v-.109375h-16v.039063h-16v-.007813h-16v-.019531h-15v-.175782h-16v-.242187h-16v.023437h-16v-.058593h-16v-.210938h-15v-.160156h-16v-.054687h-16v-.226563h-16v-.355469h-16v-.53125h-15v-.128906h-16v-.179688h-16v.023438h-16v-.140625h-15v.023437h-16v.0625h-16v.667969h-16v-.191406h-16v.164063h-15v.222656h-16v.609375h-16v.1875h-16v.496093h-16v-.089843h-15v-.296875h-16v-.40625h-16v-3.027344h-16v.207031zm0 0" fill="#54ec48"/><g clip-path="url(#a)"><path d="m55 43.878906h15v-.527344h16v.582032h16v-.75h16v-1.367188h15v.117188h16v-.957032h16v-.132812h16v-.363281h16v-.347657h15v.089844h16v-.148437h16v-.277344h16v-.171875h16v.03125h15v.441406h16v.886719h16v.121094h16v-.105469h15v-.117188h16v.226563h16v-.066406h16v.347656h16v.34375h15v.359375h16v.171875h16v.15625h16v.21875h16v.234375h15v.023438h16v.148437h16v.304687h16v.625h16v.507813h15v1.175781h16v1.046875h16v.921875h16v.648438h15" fill="none" stroke="#4d18e4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/></g><g clip-path="url(#b)"><path d="m55 127.5h15v-.203125h16v3.023437h16v.410157h16v.292969h15v.089843h16v-.496093h16v-.1875h16v-.609376h16v-.222656h15v-.164062h16v.191406h16v-.667969h16v-.058593h16v-.023438h15v.136719h16v-.023438h16v.179688h16v.128906h15v.53125h16v.355469h16v.230468h16v.050782h16v.160156h15v.210938h16v.058593h16v-.023437h16v.242187h16v.175781h15v.023438h16v.007812h16v-.042968h16v.113281h16v.1875h15v.101563h16v.160156h16v.128906h16v.25h15" fill="none" stroke="#24bc14" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/></g><g fill="none" stroke-miterlimit="10"><path d="m70 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m70 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m70 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m86 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m86 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m86 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m102 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m102 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m102 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m118 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m118 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m118 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m149 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m149 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m149 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m165 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m165 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m165 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m181 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m181 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m181 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m197 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m197 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m197 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m228 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m228 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m228 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m244 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m244 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m244 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m260 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m260 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m260 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m276 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m276 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m276 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m307 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m307 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m307 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m323 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m323 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m323 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m339 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m339 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m339 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m355 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m355 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m355 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m386 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m386 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m386 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m402 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m402 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m402 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m418 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m418 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m418 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m433 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m433 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m433 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m465 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m465 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m465 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m481 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m481 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m481 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m497 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m497 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m497 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m512 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m512 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m512 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m544 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m544 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m544 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m560 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m560 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m560 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m576 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m576 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m576 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m591 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m591 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m591 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m623 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m623 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m623 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m639 31v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m639 233v2" stroke="#8f8f8f" stroke-opacity=".75" stroke-width=".4"/><path d="m639 234v-202" stroke="#8f8f8f" stroke-dasharray="1 1" stroke-opacity=".75" stroke-width=".4"/><path d="m55 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m55 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m55 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m133 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m133 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m133 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m212 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m212 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m212 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m291 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m291 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m291 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m370 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m370 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m370 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m449 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m449 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m449 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m528 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m528 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m528 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/><path d="m607 31v2" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m607 233v3" stroke="#de4f4f" stroke-opacity=".6" stroke-width=".6"/><path d="m607 236v-205" stroke="#de4f4f" stroke-dasharray="1 1" stroke-opacity=".6" stroke-width=".6"/></g><g><use x="40" xlink:href="#c" y="241.199219"/><use x="43.848633" xlink:href="#c" y="241.199219"/><use x="47.697266" xlink:href="#d" y="241.199219"/><use x="51.545898" xlink:href="#c" y="241.199219"/><use x="55.394531" xlink:href="#c" y="241.199219"/><use x="59.243164" xlink:href="#d" y="241.199219"/><use x="63.091797" xlink:href="#c" y="241.199219"/><use x="66.94043" xlink:href="#c" y="241.199219"/></g><g><use x="118" xlink:href="#c" y="241.199219"/><use x="121.848633" xlink:href="#c" y="241.199219"/><use x="125.697266" xlink:href="#d" y="241.199219"/><use x="129.545898" xlink:href="#c" y="241.199219"/><use x="133.394531" xlink:href="#c" y="241.199219"/><use x="137.243164" xlink:href="#d" y="241.199219"/><use x="141.091797" xlink:href="#c" y="241.199219"/><use x="144.94043" xlink:href="#e" y="241.199219"/></g><g><use x="197" xlink:href="#c" y="241.199219"/><use x="200.848633" xlink:href="#c" y="241.199219"/><use x="204.697266" xlink:href="#d" y="241.199219"/><use x="208.545898" xlink:href="#c" y="241.199219"/><use x="212.394531" xlink:href="#c" y="241.199219"/><use x="216.243164" xlink:href="#d" y="241.199219"/><use x="220.091797" xlink:href="#f" y="241.199219"/><use x="223.94043" xlink:href="#c" y="241.199219"/></g><g><use x="276" xlink:href="#c" y="241.199219"/><use x="279.848633" xlink:href="#c" y="241.199219"/><use x="283.697266" xlink:href="#d" y="241.199219"/><use x="287.545898" xlink:href="#c" y="241.199219"/><use x="291.394531" xlink:href="#c" y="241.199219"/><use x="295.243164" xlink:href="#d" y="241.199219"/><use x="299.091797" xlink:href="#f" y="241.199219"/><use x="302.94043" xlink:href="#e" y="241.199219"/></g><g><use x="355" xlink:href="#c" y="241.199219"/><use x="358.848633" xlink:href="#c" y="241.199219"/><use x="362.697266" xlink:href="#d" y="241.199219"/><use x="366.545898" xlink:href="#c" y="241.199219"/><use x="370.394531" xlink:href="#c" y="241.199219"/><use x="374.243164" xlink:href="#d" y="241.199219"/><use x="378.091797" xlink:href="#g" y="241.199219"/><use x="381.94043" xlink:href="#c" y="241.199219"/></g><g><use x="434" xlink:href="#c" y="241.199219"/><use x="437.848633" xlink:href="#c" y="241.199219"/><use x="441.697266" xlink:href="#d" y="241.199219"/><use x="445.545898" xlink:href="#c" y="241.199219"/><use x="449.394531" xlink:href="#c" y="241.199219"/><use x="453.243164" xlink:href="#d" y="241.199219"/><use x="457.091797" xlink:href="#g" y="241.199219"/><use x="460.94043" xlink:href="#e" y="241.199219"/></g><g><use x="513" xlink:href="#c" y="241.199219"/><use x="516.848633" xlink:href="#c" y="241.199219"/><use x="520.697266" xlink:href="#d" y="241.199219"/><use x="524.545898" xlink:href="#c" y="241.199219"/><use x="528.394531" xlink:href="#c" y="241.199219"/><use x="532.243164" xlink:href="#d" y="241.199219"/><use x="536.091797" xlink:href="#h" y="241.199219"/><use x="539.94043" xlink:href="#c" y="241.199219"/></g><g><use x="592" xlink:href="#c" y="241.199219"/><use x="595.848633" xlink:href="#c" y="241.199219"/><use x="599.697266" xlink:href="#d" y="241.199219"/><use x="603.545898" xlink:href="#c" y="241.199219"/><use x="607.394531" xlink:href="#c" y="241.199219"/><use x="611.243164" xlink:href="#d" y="241.199219"/><use x="615.091797" xlink:href="#h" y="241.199219"/><use x="618.94043" xlink:href="#e" y="241.199219"/></g><g><use x="24" xlink:href="#i" y="235.199219"/><use x="27.848633" xlink:href="#i" y="235.199219"/><use x="31.697266" xlink:href="#i" y="235.199219"/><use x="35.545898" xlink:href="#c" y="235.199219"/><use x="39.394531" xlink:href="#i" y="235.199219"/><use x="43.243164" xlink:href="#i" y="235.199219"/></g><path d="m53 233h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 233h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 233h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 223h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 223h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 223h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="215.199219"/><use x="27.848633" xlink:href="#i" y="215.199219"/><use x="31.697266" xlink:href="#f" y="215.199219"/><use x="35.545898" xlink:href="#c" y="215.199219"/><use x="39.394531" xlink:href="#i" y="215.199219"/><use x="43.243164" xlink:href="#j" y="215.199219"/></g><path d="m53 213h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 213h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 213h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 203h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 203h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 203h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="195.199219"/><use x="27.848633" xlink:href="#i" y="195.199219"/><use x="31.697266" xlink:href="#g" y="195.199219"/><use x="35.545898" xlink:href="#c" y="195.199219"/><use x="39.394531" xlink:href="#i" y="195.199219"/><use x="43.243164" xlink:href="#j" y="195.199219"/></g><path d="m53 193h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 193h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 193h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 183h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 183h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 183h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="175.199219"/><use x="27.848633" xlink:href="#i" y="175.199219"/><use x="31.697266" xlink:href="#h" y="175.199219"/><use x="35.545898" xlink:href="#c" y="175.199219"/><use x="39.394531" xlink:href="#i" y="175.199219"/><use x="43.243164" xlink:href="#j" y="175.199219"/></g><path d="m53 173h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 173h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 173h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 163h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 163h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 163h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="155.199219"/><use x="27.848633" xlink:href="#i" y="155.199219"/><use x="31.697266" xlink:href="#k" y="155.199219"/><use x="35.545898" xlink:href="#c" y="155.199219"/><use x="39.394531" xlink:href="#i" y="155.199219"/><use x="43.243164" xlink:href="#j" y="155.199219"/></g><path d="m53 153h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 153h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 153h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 143h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 143h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 143h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="135.199219"/><use x="27.848633" xlink:href="#i" y="135.199219"/><use x="31.697266" xlink:href="#e" y="135.199219"/><use x="35.545898" xlink:href="#c" y="135.199219"/><use x="39.394531" xlink:href="#i" y="135.199219"/><use x="43.243164" xlink:href="#j" y="135.199219"/></g><path d="m53 133h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 133h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 133h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 123h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 123h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 123h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="115.199219"/><use x="27.848633" xlink:href="#i" y="115.199219"/><use x="31.697266" xlink:href="#l" y="115.199219"/><use x="35.545898" xlink:href="#c" y="115.199219"/><use x="39.394531" xlink:href="#i" y="115.199219"/><use x="43.243164" xlink:href="#j" y="115.199219"/></g><path d="m53 113h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 113h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 113h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 103h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 103h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 103h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="95.199219"/><use x="27.848633" xlink:href="#i" y="95.199219"/><use x="31.697266" xlink:href="#m" y="95.199219"/><use x="35.545898" xlink:href="#c" y="95.199219"/><use x="39.394531" xlink:href="#i" y="95.199219"/><use x="43.243164" xlink:href="#j" y="95.199219"/></g><path d="m53 93h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 93h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 93h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 83h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 83h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 83h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="75.199219"/><use x="27.848633" xlink:href="#i" y="75.199219"/><use x="31.697266" xlink:href="#n" y="75.199219"/><use x="35.545898" xlink:href="#c" y="75.199219"/><use x="39.394531" xlink:href="#i" y="75.199219"/><use x="43.243164" xlink:href="#j" y="75.199219"/></g><path d="m53 73h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 73h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 73h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 63h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 63h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 63h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="55.199219"/><use x="27.848633" xlink:href="#i" y="55.199219"/><use x="31.697266" xlink:href="#o" y="55.199219"/><use x="35.545898" xlink:href="#c" y="55.199219"/><use x="39.394531" xlink:href="#i" y="55.199219"/><use x="43.243164" xlink:href="#j" y="55.199219"/></g><path d="m53 53h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 53h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 53h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><path d="m53 43h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m655 43h2" fill="none" stroke="#8f8f8f" stroke-miterlimit="10" stroke-opacity=".75" stroke-width=".4"/><path d="m54 43h602" style="fill:none;stroke-width:.4;stroke:#8f8f8f;stroke-opacity:.75;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="24" xlink:href="#i" y="35.199219"/><use x="27.848633" xlink:href="#f" y="35.199219"/><use x="31.697266" xlink:href="#c" y="35.199219"/><use x="35.545898" xlink:href="#c" y="35.199219"/><use x="39.394531" xlink:href="#i" y="35.199219"/><use x="43.243164" xlink:href="#j" y="35.199219"/></g><path d="m53 33h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m655 33h2" fill="none" stroke="#de4f4f" stroke-miterlimit="10" stroke-opacity=".6" stroke-width=".6"/><path d="m53 33h604" style="fill:none;stroke-width:.6;stroke:#de4f4f;stroke-opacity:.6;stroke-dasharray:1 1;stroke-miterlimit:10"/><g><use x="11.941406" xlink:href="#p" y="175"/><use x="11.941406" xlink:href="#q" y="170.601562"/><use x="11.941406" xlink:href="#r" y="166.203125"/><use x="11.941406" xlink:href="#s" y="161.804688"/><use x="11.941406" xlink:href="#q" y="157.40625"/><use x="11.941406" xlink:href="#t" y="153.007812"/><use x="11.941406" xlink:href="#u" y="148.609375"/><use x="11.941406" xlink:href="#t" y="144.210938"/><use x="11.941406" xlink:href="#v" y="139.8125"/><use x="11.941406" xlink:href="#w" y="135.414062"/><use x="11.941406" xlink:href="#q" y="131.015625"/><use x="11.941406" xlink:href="#p" y="126.617188"/><use x="11.941406" xlink:href="#v" y="122.21875"/><use x="11.941406" xlink:href="#t" y="117.820312"/><use x="11.941406" xlink:href="#q" y="113.421875"/><use x="11.941406" xlink:href="#x" y="109.023438"/><use x="11.941406" xlink:href="#y" y="104.625"/><use x="11.941406" xlink:href="#z" y="100.226562"/><use x="11.941406" xlink:href="#A" y="95.828125"/></g><g><use x="290" xlink:href="#B" y="12.68457"/><use x="294.948242" xlink:href="#C" y="12.68457"/><use x="299.896484" xlink:href="#D" y="12.68457"/><use x="304.844727" xlink:href="#E" y="12.68457"/><use x="309.792969" xlink:href="#F" y="12.68457"/><use x="314.741211" xlink:href="#F" y="12.68457"/><use x="319.689453" xlink:href="#G" y="12.68457"/><use x="324.637695" xlink:href="#H" y="12.68457"/><use x="329.585938" xlink:href="#I" y="12.68457"/><use x="334.53418" xlink:href="#J" y="12.68457"/><use x="339.482422" xlink:href="#I" y="12.68457"/><use x="344.430664" xlink:href="#D" y="12.68457"/><use x="349.378906" xlink:href="#K" y="12.68457"/><use x="354.327148" xlink:href="#L" y="12.68457"/><use x="359.275391" xlink:href="#D" y="12.68457"/><use x="364.223633" xlink:href="#E" y="12.68457"/><use x="369.171875" xlink:href="#F" y="12.68457"/><use x="374.120117" xlink:href="#F" y="12.68457"/><use x="379.068359" xlink:href="#G" y="12.68457"/><use x="384.016602" xlink:href="#H" y="12.68457"/><use x="388.964844" xlink:href="#M" y="12.68457"/></g><g fill-opacity=".3"><use x="676.915039" xlink:href="#N" y="5"/><use x="676.915039" xlink:href="#N" y="8.024414"/><use x="676.915039" xlink:href="#O" y="11.048828"/><use x="676.915039" xlink:href="#P" y="14.073242"/><use x="676.915039" xlink:href="#Q" y="17.097656"/><use x="676.915039" xlink:href="#Q" y="20.12207"/><use x="676.915039" xlink:href="#R" y="23.146484"/><use x="676.915039" xlink:href="#S" y="26.170898"/><use x="676.915039" xlink:href="#T" y="29.195312"/><use x="676.915039" xlink:href="#S" y="32.219727"/><use x="676.915039" xlink:href="#P" y="35.244141"/><use x="676.915039" xlink:href="#Q" y="38.268555"/><use x="676.915039" xlink:href="#U" y="41.292969"/><use x="676.915039" xlink:href="#V" y="44.317383"/><use x="676.915039" xlink:href="#S" y="47.341797"/><use x="676.915039" xlink:href="#Q" y="50.366211"/><use x="676.915039" xlink:href="#W" y="53.390625"/><use x="676.915039" xlink:href="#P" y="56.415039"/><use x="676.915039" xlink:href="#V" y="59.439453"/><use x="676.915039" xlink:href="#X" y="62.463867"/><use x="676.915039" xlink:href="#W" y="65.488281"/><use x="676.915039" xlink:href="#N" y="68.512695"/></g><g><use x="16" xlink:href="#Y" y="263.941406"/><use x="20.398438" xlink:href="#Y" y="263.941406"/><use x="24.796875" xlink:href="#Y" y="263.941406"/><use x="29.195312" xlink:href="#Z" y="263.941406"/><use x="33.59375" xlink:href="#aa" y="263.941406"/><use x="37.992188" xlink:href="#Y" y="263.941406"/><use x="42.390625" xlink:href="#ab" y="263.941406"/><use x="46.789062" xlink:href="#ac" y="263.941406"/><use x="51.1875" xlink:href="#ac" y="263.941406"/><use x="55.585938" xlink:href="#ad" y="263.941406"/><use x="59.984375" xlink:href="#ae" y="263.941406"/><use x="64.382812" xlink:href="#af" y="263.941406"/><use x="68.78125" xlink:href="#ag" y="263.941406"/><use x="73.179688" xlink:href="#af" y="263.941406"/></g><path d="m16 257.601562v6h6v-6zm0 0" fill="#f2f2f2"/><path d="m16 257.601562v6h6v-6zm0 0" fill="#7648ec"/><path d="m16 263.601562h6v-6h-6zm0 0" fill="none" stroke="#000" stroke-miterlimit="10"/><g><use x="436" xlink:href="#ah" y="263.941406"/><use x="440.398438" xlink:href="#ai" y="263.941406"/><use x="444.796875" xlink:href="#aj" y="263.941406"/><use x="449.195312" xlink:href="#Y" y="263.941406"/><use x="453.59375" xlink:href="#Y" y="263.941406"/><use x="457.992188" xlink:href="#ak" y="263.941406"/><use x="462.390625" xlink:href="#al" y="263.941406"/><use x="466.789062" xlink:href="#am" y="263.941406"/><use x="471.1875" xlink:href="#an" y="263.941406"/><use x="475.585938" xlink:href="#ao" y="263.941406"/></g><g><use x="496" xlink:href="#ap" y="263.941406"/><use x="500.398438" xlink:href="#aq" y="263.941406"/><use x="504.796875" xlink:href="#ar" y="263.941406"/><use x="509.195312" xlink:href="#Y" y="263.941406"/><use x="513.59375" xlink:href="#Y" y="263.941406"/><use x="517.992188" xlink:href="#ak" y="263.941406"/><use x="522.390625" xlink:href="#as" y="263.941406"/><use x="526.789062" xlink:href="#am" y="263.941406"/><use x="531.1875" xlink:href="#at" y="263.941406"/><use x="535.585938" xlink:href="#as" y="263.941406"/></g><g><use x="556" xlink:href="#ap" y="263.941406"/><use x="560.398438" xlink:href="#ah" y="263.941406"/><use x="564.796875" xlink:href="#au" y="263.941406"/><use x="569.195312" xlink:href="#Y" y="263.941406"/><use x="573.59375" xlink:href="#Y" y="263.941406"/><use x="577.992188" xlink:href="#ak" y="263.941406"/><use x="582.390625" xlink:href="#at" y="263.941406"/><use x="586.789062" xlink:href="#at" y="263.941406"/><use x="591.1875" xlink:href="#ao" y="263.941406"/><use x="595.585938" xlink:href="#ao" y="263.941406"/></g><g><use x="616" xlink:href="#av" y="263.941406"/><use x="620.398438" xlink:href="#ac" y="263.941406"/><use x="624.796875" xlink:href="#aw" y="263.941406"/><use x="629.195312" xlink:href="#ax" y="263.941406"/><use x="633.59375" xlink:href="#ai" y="263.941406"/><use x="637.992188" xlink:href="#Y" y="263.941406"/><use x="642.390625" xlink:href="#Y" y="263.941406"/><use x="646.789062" xlink:href="#Y" y="263.941406"/><use x="651.1875" xlink:href="#af" y="263.941406"/><use x="655.585938" xlink:href="#ay" y="263.941406"/><use x="659.984375" xlink:href="#al" y="263.941406"/><use x="664.382812" xlink:href="#az" y="263.941406"/></g><g><use x="16" xlink:href="#Y" y="277.941406"/><use x="20.398438" xlink:href="#Y" y="277.941406"/><use x="24.796875" xlink:href="#Y" y="277.941406"/><use x="29.195312" xlink:href="#Z" y="277.941406"/><use x="33.59375" xlink:href="#aa" y="277.941406"/><use x="37.992188" xlink:href="#Y" y="277.941406"/><use x="42.390625" xlink:href="#ab" y="277.941406"/><use x="46.789062" xlink:href="#ac" y="277.941406"/><use x="51.1875" xlink:href="#ac" y="277.941406"/><use x="55.585938" xlink:href="#ad" y="277.941406"/><use x="59.984375" xlink:href="#ae" y="277.941406"/><use x="64.382812" xlink:href="#as" y="277.941406"/></g><path d="m16 271.601562v6h6v-6zm0 0" fill="#f2f2f2"/><path d="m16 271.601562v6h6v-6zm0 0" fill="#54ec48"/><path d="m16 277.601562h6v-6h-6zm0 0" fill="none" stroke="#000" stroke-miterlimit="10"/><g><use x="436" xlink:href="#ah" y="276.941406"/><use x="440.398438" xlink:href="#ai" y="276.941406"/><use x="444.796875" xlink:href="#aj" y="276.941406"/><use x="449.195312" xlink:href="#Y" y="276.941406"/><use x="453.59375" xlink:href="#Y" y="276.941406"/><use x="457.992188" xlink:href="#al" y="276.941406"/><use x="462.390625" xlink:href="#af" y="276.941406"/><use x="466.789062" xlink:href="#am" y="276.941406"/><use x="471.1875" xlink:href="#an" y="276.941406"/><use x="475.585938" xlink:href="#al" y="276.941406"/></g><g><use x="496" xlink:href="#ap" y="276.941406"/><use x="500.398438" xlink:href="#aq" y="276.941406"/><use x="504.796875" xlink:href="#ar" y="276.941406"/><use x="509.195312" xlink:href="#Y" y="276.941406"/><use x="513.59375" xlink:href="#Y" y="276.941406"/><use x="517.992188" xlink:href="#al" y="276.941406"/><use x="522.390625" xlink:href="#ay" y="276.941406"/><use x="526.789062" xlink:href="#am" y="276.941406"/><use x="531.1875" xlink:href="#ak" y="276.941406"/><use x="535.585938" xlink:href="#as" y="276.941406"/></g><g><use x="556" xlink:href="#ap" y="276.941406"/><use x="560.398438" xlink:href="#ah" y="276.941406"/><use x="564.796875" xlink:href="#au" y="276.941406"/><use x="569.195312" xlink:href="#Y" y="276.941406"/><use x="573.59375" xlink:href="#Y" y="276.941406"/><use x="577.992188" xlink:href="#al" y="276.941406"/><use x="582.390625" xlink:href="#as" y="276.941406"/><use x="586.789062" xlink:href="#ao" y="276.941406"/><use x="591.1875" xlink:href="#al" y="276.941406"/><use x="595.585938" xlink:href="#as" y="276.941406"/></g><g><use x="616" xlink:href="#av" y="276.941406"/><use x="620.398438" xlink:href="#ac" y="276.941406"/><use x="624.796875" xlink:href="#aw" y="276.941406"/><use x="629.195312" xlink:href="#ax" y="276.941406"/><use x="633.59375" xlink:href="#ai" y="276.941406"/><use x="637.992188" xlink:href="#Y" y="276.941406"/><use x="642.390625" xlink:href="#Y" y="276.941406"/><use x="646.789062" xlink:href="#Y" y="276.941406"/><use x="651.1875" xlink:href="#Y" y="276.941406"/><use x="655.585938" xlink:href="#al" y="276.941406"/><use x="659.984375" xlink:href="#ao" y="276.941406"/><use x="664.382812" xlink:href="#af" y="276.941406"/></g><path d="m51 233h608" fill="none" stroke="#1f1f1f" stroke-miterlimit="10" stroke-width=".6"/><path d="m55 237v-208" fill="none" stroke="#1f1f1f" stroke-miterlimit="10" stroke-width=".6"/><path d="m657 230v6l5-3zm0 0" fill="#7f1f1f"/><path d="m52 31h6l-3-5zm0 0" fill="#7f1f1f"/></svg>
#!/bin/sh -e
echo "kill -9 $$"
exec $*
#!/usr/bin/env escript
%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*-
%% vim: ts=4 sw=4 ft=erlang noet
-module(h2load).
-export([main/1]).
% -define(remote_node, 'phoenix_h2load@127.0.0.1').
-define(load_timeout, 60). % 300
-define(kill_timeout, timer:seconds(45)). % timer:minutes(5)
-define(local_time_shift, 21600). % CST
main([Node, Cookie, Executable, Filename, Type, ConnectPort]) ->
_ = erlang:process_flag(trap_exit, true),
{ok, _} = net_kernel:start([erlang:list_to_atom(Node), longnames]),
true = erlang:set_cookie(erlang:node(), erlang:list_to_atom(Cookie)),
Parent = erlang:self(),
stats = ets:new(stats, [named_table, public, duplicate_bag]),
Worker = erlang:spawn_link(fun() -> init(Parent, Executable, Filename, Type, ConnectPort) end),
true = erlang:register(worker, Worker),
io:format("erl: started~n"),
receive
{stopped, Worker} ->
io:format("erl: stopped~n");
BadMsg ->
io:format("WHAT IN THE WORLD: ~p~n", [BadMsg])
after
infinity ->
ok
end;
main(_) ->
io:format("usage: h2load.escript NODE COOKIE EXECUTABLE FILENAME\n"),
erlang:halt(1).
-record(state, {
parent = nil :: pid(),
poll = nil :: pid(),
test = nil :: pid(),
filename = nil :: string(),
executable = nil :: string(),
type = nil :: h1 | h2,
connect_port = nil :: pos_integer(),
port = nil :: port(),
kill_cmd = nil :: string()
}).
init(Parent, Executable, Filename, Type, ConnectPort) ->
_ = erlang:process_flag(trap_exit, true),
Self = erlang:self(),
% Poll = erlang:spawn_link(fun () -> node_poll_init(Self) end),
Test = erlang:spawn_link(fun () -> stop_after_kill_timeout(Self) end),
State0 = #state{
parent = Parent,
% poll = Poll,
test = Test,
filename = Filename,
executable = Executable,
type =
case Type of
"h1" -> h1;
_ -> h2
end,
connect_port = erlang:list_to_integer(ConnectPort)
},
State1 = start_h2load(State0),
loop(State1).
loop(State=#state{parent=Parent, poll=_Poll, test=Test, port=Port}) ->
receive
{Port, {data, {eol, Line}}} ->
handle_line(State, Line);
{Port, {data, _}} ->
loop(State);
{Port, {exit_status, 0}} ->
loop(start_h2load(State#state{port=nil, kill_cmd=nil}));
stop ->
% _ = erlang:send(Poll, stop),
% receive
% {stopped, Poll} ->
% ok
% after 100 ->
% catch erlang:exit(Poll, kill)
% end,
_ = erlang:send(Test, stop),
receive
{stopped, Test} ->
ok
after 100 ->
catch erlang:exit(Test, kill)
end,
ok = terminate(State),
Stats = reduce_stats(),
ok = write_stats(State, Stats),
_ = erlang:send(Parent, {stopped, erlang:self()}),
ok;
Message ->
io:format("M: ~p~n", [Message]),
loop(State)
end.
handle_line(State, << "RPSI ", Timestamp0:19/binary, $\s, RPS0/binary >>) ->
try erlang:binary_to_integer(Timestamp0) of
Timestamp ->
try erlang:binary_to_float(RPS0) of
RPS ->
io:format("req/s ~w ~w~n", [Timestamp, RPS]),
true = write(requests, Timestamp, RPS),
loop(State)
catch _:_ ->
loop(State)
end
catch _:_ ->
loop(State)
end;
handle_line(State, _) ->
loop(State).
terminate(#state{port=Port, kill_cmd=KillCmd}) when is_port(Port) andalso KillCmd =/= nil ->
catch erlang:port_close(Port),
io:format("~s -> ~s", [KillCmd, os:cmd(KillCmd)]),
ok;
terminate(_) ->
ok.
%%%-------------------------------------------------------------------
%%% h2load functions
%%%-------------------------------------------------------------------
%% @private
start_h2load(State0=#state{executable=Executable, type=h1, connect_port=ConnectPort}) ->
Command = [
Executable,
"--h1",
"--duration=" ++ erlang:integer_to_list(?load_timeout) ++ "s",
"--warm-up-time=5s",
"--interval=1s",
"--clients=100",
"--max-concurrent-streams=10",
"--requests=0",
"http://127.0.0.1:" ++ erlang:integer_to_list(ConnectPort) ++ "/"
],
io:format("Command: ~s~n", [[[Arg, $\s] || Arg <- Command]]),
Port = erlang:open_port({spawn_executable, "./h2load-spawn.sh"}, [
{line, 1024},
{args, Command},
exit_status,
use_stdio,
stderr_to_stdout,
binary
]),
State1 = State0#state{port=Port},
wait_h2load(State1);
start_h2load(State0=#state{executable=Executable, type=h2, connect_port=ConnectPort}) ->
Command = [
Executable,
"--duration=" ++ erlang:integer_to_list(?load_timeout) ++ "s",
"--warm-up-time=5s",
"--interval=1s",
"--clients=100",
"--max-concurrent-streams=1000",
"--requests=0",
% "--window-bits=16",
% "--connection-window-bits=16",
"http://127.0.0.1:" ++ erlang:integer_to_list(ConnectPort) ++ "/"
],
io:format("Command: ~s~n", [[[Arg, $\s] || Arg <- Command]]),
Port = erlang:open_port({spawn_executable, "./h2load-spawn.sh"}, [
{line, 1024},
{args, Command},
exit_status,
use_stdio,
stderr_to_stdout,
binary
]),
State1 = State0#state{port=Port},
wait_h2load(State1).
%% @private
wait_h2load(State=#state{port=Port}) ->
receive
{Port, {data, {eol, KillCmd = <<"kill", _/binary>>}}} ->
State#state{kill_cmd=erlang:binary_to_list(KillCmd)};
{Port, Err} ->
catch erlang:port_close(Port),
erlang:throw({os_process_error, Err})
after 5000 ->
catch erlang:port_close(Port),
erlang:throw({os_process_error, "OS process timed out."})
end.
% %%%-------------------------------------------------------------------
% %%% node poll functions
% %%%-------------------------------------------------------------------
% -record(poll, {
% parent = nil :: pid(),
% node = nil :: node()
% }).
% node_poll_init(Parent) ->
% Node = ?remote_node,
% State = #poll{
% parent = Parent,
% node = Node
% },
% ok = connect(Node),
% node_poll_loop(State).
% node_poll_loop(State=#poll{parent=Parent, node=Node}) ->
% receive
% {phoenix_h2load, {wall_time, Timestamp, Data0}} ->
% {N, D} = scheduler_utilization(Data0),
% true = write(normal, Timestamp, N),
% true = write(dirty, Timestamp, D),
% % true = ets:insert(stats, [{schedulers, {Timestamp, Data}}]),
% % io:format("C: ~w ~p~n", [Timestamp, Data0]),
% node_poll_loop(State);
% stop ->
% ok = disconnect(Node),
% _ = erlang:send(Parent, {stopped, erlang:self()}),
% ok;
% Message ->
% io:format("M: ~p~n", [Message]),
% node_poll_loop(State)
% after 1000 ->
% {Timestamp, Data0} = rpc:call(Node, 'Elixir.PhoenixH2load.SchedulerUtilization', fetch, []),
% {N, D} = scheduler_utilization(Data0),
% true = write(normal, Timestamp, N),
% true = write(dirty, Timestamp, D),
% % true = ets:insert(stats, [{schedulers, {Timestamp, Data}}]),
% % io:format("R: ~w ~p~n", [Timestamp, Data0]),
% node_poll_loop(State)
% end.
%%%-------------------------------------------------------------------
%%% node test functions
%%%-------------------------------------------------------------------
stop_after_kill_timeout(Parent) ->
TRef = erlang:start_timer(?kill_timeout, erlang:self(), stop),
stop_after_kill_timeout_loop(Parent, TRef).
stop_after_kill_timeout_loop(Parent, TRef) ->
receive
{timeout, TRef, stop} when is_reference(TRef) ->
_ = erlang:send(Parent, stop),
stop_after_kill_timeout_loop(Parent, nil);
stop ->
_ = erlang:send(Parent, {stopped, erlang:self()}),
ok;
Message ->
io:format("M: ~p~n", [Message]),
stop_after_kill_timeout_loop(Parent, TRef)
after 10000 ->
io:format("ms remaining: ~p~n", [erlang:read_timer(TRef)]),
stop_after_kill_timeout_loop(Parent, TRef)
end.
% %%%-------------------------------------------------------------------
% %%% node functions
% %%%-------------------------------------------------------------------
% connect(Node) ->
% true = net_kernel:connect_node(Node),
% ok = rpc:call(Node, phoenix_h2load_event, add_handler, [phoenix_h2load_event_handler, erlang:self()]),
% ok.
% disconnect(Node) ->
% ok = rpc:call(Node, phoenix_h2load_event, delete_handler, [phoenix_h2load_event_handler, erlang:self()]),
% ok.
% scheduler_utilization({N, D}) ->
% {
% round_usage(N),
% round_usage(D)
% }.
%%%-------------------------------------------------------------------
%%% time series functions
%%%-------------------------------------------------------------------
reduce_stats() ->
Stats0 = lists:sort(ets:match_object(stats, '_')),
{Tests0, Stats1} = reduce_tests(Stats0, #{}, []),
{Usage, Stats2} = reduce_usage(Stats1, [], []),
Tests = tests_to_stats(maps:to_list(Tests0), []),
{Requests, []} = reduce_requests(Stats2, [], []),
Stats3 = combine_stats(lists:flatten([Usage, Tests, Requests]), #{}),
% io:format("Tests: ~p~n", [Tests]),
% io:format("Usage: ~p~n", [Usage]),
% io:format("Requests: ~p~n", [Requests]),
% io:format("Stats: ~p~n", [Stats3]),
Stats3.
combine_stats([], Acc) ->
lists:sort(maps:to_list(Acc));
combine_stats([{TS, K, V} | Stats], Acc) ->
case maps:find(TS, Acc) of
{ok, Event0} ->
Event1 = maps:put(K, V, Event0),
combine_stats(Stats, maps:put(TS, Event1, Acc));
error ->
Event = maps:put(K, V, maps:new()),
combine_stats(Stats, maps:put(TS, Event, Acc))
end.
tests_to_stats([], Acc) ->
lists:sort(Acc);
tests_to_stats([{Test, {Start, End}} | Tests], Acc) ->
tests_to_stats(Tests, test_to_stats(Test, Start, End, Acc)).
test_to_stats(Test, End, End, Acc) ->
[{End, Test, 1} | Acc];
test_to_stats(Test, Start, End, Acc) when Start < End ->
test_to_stats(Test, Start + 1, End, [{Start, Test, 1} | Acc]).
reduce_tests([], Tests, Acc) ->
{Tests, lists:reverse(Acc)};
reduce_tests([{Bucket, {Test, _, start}} | Stats], Tests, Acc) when is_binary(Test) ->
reduce_tests(Stats, maps:put(Test, Bucket, Tests), Acc);
reduce_tests([{Bucket, {Test, _, 'end'}} | Stats], Tests0, Acc) when is_binary(Test) ->
Tests1 =
case maps:find(Test, Tests0) of
{ok, Start} when (Bucket - Start) < 1->
maps:put(Test, {Start, Bucket + 1}, Tests0);
{ok, Start} ->
maps:put(Test, {Start, Bucket}, Tests0);
_ ->
Tests0
end,
reduce_tests(Stats, Tests1, Acc);
reduce_tests([Stat | Stats], Tests, Acc) ->
reduce_tests(Stats, Tests, [Stat | Acc]).
reduce_requests([], Requests, Acc) ->
{fill_requests_gaps(lists:reverse(Requests), []), lists:reverse(Acc)};
reduce_requests([{Bucket, {requests, _, V0}} | Stats0], Requests, Acc) ->
{V, Stats1} = reduce_request(Stats0, Bucket, V0),
reduce_requests(Stats1, [{Bucket, requests, V} | Requests], Acc);
reduce_requests([Stat | Stats], Requests, Acc) ->
reduce_requests(Stats, Requests, [Stat | Acc]).
reduce_request([{Bucket, {requests, _, V0}} | Stats], Bucket, V1) ->
reduce_request(Stats, Bucket, (V0 + V1) / 2);
reduce_request(Stats, _, V) ->
{V, Stats}.
fill_requests_gaps([], Acc) ->
lists:sort(Acc);
fill_requests_gaps([
{TS0, K, V0},
{TS1, K, V1}
| Requests0
], Acc0) ->
Acc1 =
case TS1 - TS0 of
Diff when Diff > 1 ->
[
{TS0, K, V0}
| fill_average(TS0, Diff - 1, K, (V0 + V1) / 2, Acc0)
];
1 ->
[
{TS0, K, V0}
| Acc0
]
end,
Requests1 = [
{TS1, K, V1}
| Requests0
],
fill_requests_gaps(Requests1, Acc1);
fill_requests_gaps([Stat | Requests], Acc) ->
fill_requests_gaps(Requests, [Stat | Acc]).
reduce_usage([], Usage, Acc) ->
{fill_usage_gaps(lists:reverse(Usage), []), lists:reverse(Acc)};
reduce_usage([{Bucket, {K, _, V0}} | Stats0], Usage, Acc) when K == normal orelse K == dirty ->
{V1, Stats1} = reduce_usage_type(Stats0, Bucket, K, V0),
reduce_usage(Stats1, [{Bucket, K, V1} | Usage], Acc);
reduce_usage([Stat | Stats], Usage, Acc) ->
reduce_usage(Stats, Usage, [Stat | Acc]).
reduce_usage_type([{Bucket, {K, _, V0}} | Stats], Bucket, K, V1) ->
reduce_usage_type(Stats, Bucket, K, erlang:max(V0, V1));
reduce_usage_type(Stats, _, _, V) ->
{V, Stats}.
fill_usage_gaps([], Acc) ->
lists:sort(Acc);
fill_usage_gaps([
{TS0, Ka, Va0},
{TS0, Kb, Vb0},
{TS1, Ka, Va1},
{TS1, Kb, Vb1}
| Usage0
], Acc0) ->
Acc1 =
case (TS1 - TS0) of
Diff when Diff > 2 ->
[
{TS0, Ka, Va0},
{TS0, Kb, Vb0}
| fill_error(TS0, Diff - 1, Acc0)
];
2 ->
[
{TS0, Ka, Va0},
{TS0, Kb, Vb0},
{TS0 + 1, Ka, round_usage((Va0 + Va1) / 2)},
{TS0 + 1, Kb, round_usage((Vb0 + Vb1) / 2)}
| Acc0
];
1 ->
[
{TS0, Ka, Va0},
{TS0, Kb, Vb0}
| Acc0
]
end,
Usage1 = [
{TS1, Ka, Va1},
{TS1, Kb, Vb1}
| Usage0
],
fill_usage_gaps(Usage1, Acc1);
fill_usage_gaps([Stat | Usage], Acc) ->
fill_usage_gaps(Usage, [Stat | Acc]).
fill_average(TS, I, K, V, Acc) when I > 0 ->
fill_average(TS, I - 1, K, V, [{TS + I, K, V} | Acc]);
fill_average(_TS, _I, _K, _V, Acc) ->
Acc.
fill_error(TS, I, Acc) when I > 0 ->
fill_error(TS, I - 1, [{TS + I, error, 1} | Acc]);
fill_error(_TS, _I, Acc) ->
Acc.
round_usage(X) ->
erlang:round(X * 10000) / 10000.
write(Key, Timestamp, Value) ->
Bucket = erlang:round(Timestamp / 1000000000),
true = ets:insert(stats, {Bucket, {Key, Timestamp, Value}}).
write_stats(State, Stats) ->
true = rrdtool_create(State, Stats),
ok = rrdtool_update(State, Stats),
% ok = rrdtool_graph0(State, Stats),
ok = rrdtool_graph1(State, Stats),
ok.
%%%-------------------------------------------------------------------
%%% rrdtool functions
%%%-------------------------------------------------------------------
rrdtool_create(#state{filename=Filename}, Stats = [{TS, _} | _]) ->
Command = io_lib:format(
"rrdtool create \"~s.rrd\""
" --start ~w"
" --step 1"
" DS:normal:GAUGE:1:0:1"
" DS:dirty:GAUGE:1:0:1"
" DS:error:ABSOLUTE:1:0:1"
" DS:requests:GAUGE:1:0:1000000"
" ~s"
" RRA:MAX:0:1:7200",
[
Filename,
TS - 1,
rrdtool_datasets(Stats)
]
),
Result = os:cmd(Command),
io:format("~s~n~n~s~n", [Command, Result]),
true;
rrdtool_create(_, _) ->
false.
rrdtool_datasets(Stats) ->
rrdtool_datasets_uniq(Stats, #{}).
rrdtool_datasets([], []) ->
<<>>;
rrdtool_datasets([], [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_datasets([K | Rest], Acc) ->
Dataset = io_lib:format(
"DS:~s:ABSOLUTE:1:0:1",
[
K
]
),
rrdtool_datasets(Rest, [$\s, Dataset | Acc]).
rrdtool_datasets_uniq([], Acc) ->
rrdtool_datasets(lists:sort(maps:keys(Acc)), []);
rrdtool_datasets_uniq([{_, M} | Stats], Acc0) ->
Acc1 = lists:foldl(fun
(K, A) when is_binary(K) ->
maps:put(K, [], A);
(_, A) ->
A
end, Acc0, maps:keys(M)),
rrdtool_datasets_uniq(Stats, Acc1);
rrdtool_datasets_uniq([_ | Stats], Acc) ->
rrdtool_datasets_uniq(Stats, Acc).
rrdtool_update(State, Stats) ->
Groups = rrdtool_update_groups(Stats),
rrdtool_updates(State, Groups).
rrdtool_updates(_, []) ->
ok;
rrdtool_updates(State=#state{filename=Filename}, [Group | Groups]) ->
Template = rrdtool_update_template(Group),
Values = rrdtool_update_values(Group),
Command = io_lib:format(
"rrdtool update \"~s.rrd\""
" --template ~s"
" ~s",
[
Filename,
Template,
Values
]
),
Result = os:cmd(Command),
io:format("~s~n~n~s~n", [Command, Result]),
rrdtool_updates(State, Groups).
rrdtool_update_template([{_, Event} | _]) ->
rrdtool_update_template(lists:sort(maps:keys(Event)), []).
rrdtool_update_template([], []) ->
<<>>;
rrdtool_update_template([], [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_update_template([Key0 | Keys], Acc) ->
Key =
case Key0 of
_ when is_atom(Key0) ->
erlang:atom_to_binary(Key0, unicode);
_ when is_binary(Key0) ->
Key0
end,
rrdtool_update_template(Keys, [$:, Key | Acc]).
rrdtool_update_values(Group) ->
rrdtool_update_values(Group, []).
rrdtool_update_values([], []) ->
<<>>;
rrdtool_update_values([], [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_update_values([{TS, Event0} | Group], Acc) ->
Event = lists:sort(maps:to_list(Event0)),
Value = rrdtool_update_event([{timestamp, TS} | Event]),
rrdtool_update_values(Group, [$\s, Value | Acc]).
rrdtool_update_event(Event) ->
rrdtool_update_event(Event, []).
rrdtool_update_event([], []) ->
<<>>;
rrdtool_update_event([], [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_update_event([{_, V} | Event], Acc) ->
Value =
case V of
_ when is_float(V) ->
io_lib:format("~w", [V]);
_ when is_integer(V) ->
erlang:integer_to_binary(V)
end,
rrdtool_update_event(Event, [$:, Value | Acc]).
rrdtool_update_groups([{TS, Event} | Stats]) ->
Keys = lists:sort(maps:keys(Event)),
rrdtool_update_groups(Stats, Keys, [], [{TS, Event}]).
rrdtool_update_groups([], _, Groups, Acc) ->
Group = lists:reverse(Acc),
lists:reverse([Group | Groups]);
rrdtool_update_groups([{TS, Event} | Stats], Keys, Groups, Acc) ->
case lists:sort(maps:keys(Event)) of
Keys ->
rrdtool_update_groups(Stats, Keys, Groups, [{TS, Event} | Acc]);
NewKeys ->
Group = lists:reverse(Acc),
rrdtool_update_groups(Stats, NewKeys, [Group | Groups], [{TS, Event}])
end.
% %%%-------------------------------------------------------------------
% %%% rrdtool graph0 functions
% %%%-------------------------------------------------------------------
% rrdtool_graph0(_State=#state{filename=Filename}, Stats = [{Start, _} | _]) ->
% {End, _} = lists:last(Stats),
% Current = erlang:system_time(second),
% StartOfDay = (Current - (Current rem 86400)) + ?local_time_shift, % convert to midnight local time
% Shift = StartOfDay - Start,
% Seconds = End - Start,
% Command = io_lib:format(
% "rrdtool graph ~s.cpu.svg \\~n"
% "--width 600 \\~n"
% "--height 200 \\~n"
% "--start 00:00 \\~n"
% "--end start+~wseconds \\~n"
% "--title '~s' \\~n"
% "--vertical-label 'scheduler usage' \\~n"
% "--imgformat SVG \\~n"
% "--border 0 \\~n"
% "--font DEFAULT:0:Consolas \\~n"
% "--upper-limit 1 \\~n"
% "--lower-limit -1 \\~n"
% "--rigid \\~n"
% "~s \\~n"
% "~s \\~n"
% "'CDEF:normal=normal0,1,/' \\~n"
% "'CDEF:dirty=dirty0,1,/,-1,*' \\~n"
% "'CDEF:ln1=normal,normal,UNKN,IF' \\~n"
% "'CDEF:ln2=dirty,dirty,UNKN,IF' \\~n"
% "~s \\~n"
% "'TICK:error#e60073a0:1: Error' \\~n"
% "'AREA:normal#48c4eca0: Normal' \\~n"
% "'AREA:dirty#54ec48a0: Dirty' \\~n"
% "'LINE1:ln1#1598c3' \\~n"
% "'LINE1:ln2#24bc14' \\~n"
% "'HRULE:0#000000:dashes=3,5:dash-offset=5' ~n"
% , [
% Filename,
% Seconds,
% Filename,
% rrdtool_graph0_def(Stats, Filename, Start, End),
% rrdtool_graph0_shift(Stats, Shift),
% rrdtool_graph0_tick(Stats)
% ]
% ),
% file:write_file(Filename ++ ".cpu.sh", "#!/usr/bin/env bash\n\n" ++ Command),
% _ = os:cmd("chmod +x " ++ Filename ++ ".cpu.sh"),
% _Result = os:cmd(Command),
% % io:format("~s~n~n~s~n", [Command, Result]),
% ok.
% rrdtool_graph0_def(Stats, Filename, Start, End) ->
% Keys = rrdtool_graph0_keys(Stats, #{}),
% rrdtool_graph0_def(Keys, Filename, Start, End, []).
% rrdtool_graph0_def([], _, _, _, []) ->
% <<>>;
% rrdtool_graph0_def([], _, _, _, [_ | Acc]) ->
% erlang:iolist_to_binary(lists:reverse(Acc));
% rrdtool_graph0_def([Key | Keys], Filename, Start, End, Acc0) ->
% Source =
% case Key of
% _ when is_atom(Key) ->
% erlang:atom_to_binary(Key);
% _ when is_binary(Key) ->
% Key
% end,
% Label =
% case Key of
% <<"normal">> ->
% <<"normal0">>;
% <<"dirty">> ->
% <<"dirty0">>;
% _ ->
% Source
% end,
% Value = io_lib:format("'DEF:~s=~s.rrd:~s:MAX:start=~w:end=~w:step=1'", [
% Label,
% Filename,
% Source,
% Start,
% End
% ]),
% Acc1 = [<<" \\\n">>, Value | Acc0],
% rrdtool_graph0_def(Keys, Filename, Start, End, Acc1).
% rrdtool_graph0_keys([], Acc) ->
% lists:usort([<<"error">> | maps:keys(Acc)]);
% rrdtool_graph0_keys([{_, Event} | Stats], Acc0) ->
% Acc1 = lists:foldl(fun
% (K, A) when K == normal orelse K == dirty orelse K == error -> maps:put(erlang:atom_to_binary(K, unicode), [], A);
% (K, A) when is_binary(K) -> maps:put(K, [], A);
% (_, A) -> A
% end, Acc0, lists:sort(maps:keys(Event))),
% rrdtool_graph0_keys(Stats, Acc1).
% rrdtool_graph0_shift(Stats, Shift) ->
% Keys = rrdtool_graph0_keys(Stats, #{}),
% rrdtool_graph0_shift(Keys, Shift, []).
% rrdtool_graph0_shift([], _, []) ->
% <<>>;
% rrdtool_graph0_shift([], _, [_ | Acc]) ->
% erlang:iolist_to_binary(lists:reverse(Acc));
% rrdtool_graph0_shift([Key | Keys], Shift, Acc0) ->
% Label =
% case Key of
% <<"normal">> ->
% <<"normal0">>;
% <<"dirty">> ->
% <<"dirty0">>;
% _ when is_binary(Key) ->
% Key
% end,
% Value = io_lib:format("'SHIFT:~s:~w'", [
% Label,
% Shift
% ]),
% Acc1 = [<<" \\\n">>, Value | Acc0],
% rrdtool_graph0_shift(Keys, Shift, Acc1).
% rrdtool_graph0_tick(Stats) ->
% Keys0 = rrdtool_graph0_keys(Stats, #{}) -- [<<"normal">>, <<"dirty">>, <<"error">>],
% Keys = lists:sort(fun (A, B) ->
% [A0 | _] = binary:split(A, <<"x">>),
% [B0 | _] = binary:split(B, <<"x">>),
% Ai = erlang:binary_to_integer(A0),
% Bi = erlang:binary_to_integer(B0),
% Ai =< Bi
% end, Keys0),
% rrdtool_graph0_tick(Keys, []).
% rrdtool_graph0_tick([], []) ->
% <<>>;
% rrdtool_graph0_tick([], [_ | Acc]) ->
% erlang:iolist_to_binary(lists:reverse(Acc));
% rrdtool_graph0_tick([Key | Keys], Acc0) ->
% Tick = io_lib:format("'TICK:~s#00000020:1: ~s'", [
% Key,
% Key
% ]),
% Acc1 = [<<" \\\n">>, Tick | Acc0],
% rrdtool_graph0_tick(Keys, Acc1).
%%%-------------------------------------------------------------------
%%% rrdtool graph1 functions
%%%-------------------------------------------------------------------
rrdtool_graph1(_State=#state{filename=Filename}, Stats = [{Start, _} | _]) ->
{End, _} = lists:last(Stats),
Current = erlang:system_time(second),
StartOfDay = (Current - (Current rem 86400)) + ?local_time_shift, % convert to midnight local time
Shift = StartOfDay - Start,
Seconds = End - Start,
Command = io_lib:format(
"rrdtool graph ~s.req.svg \\~n"
"--width 600 \\~n"
"--height 200 \\~n"
"--start 00:00 \\~n"
"--end start+~wseconds \\~n"
"--title '~s' \\~n"
"--vertical-label 'requests per second' \\~n"
"--imgformat SVG \\~n"
"--border 0 \\~n"
"--font DEFAULT:0:Consolas \\~n"
"--upper-limit 1000 \\~n"
"--lower-limit 0 \\~n"
"--rigid \\~n"
"~s \\~n"
"~s \\~n"
"'CDEF:ln1=requests,requests,UNKN,IF' \\~n"
"~s \\~n"
"'TICK:error#e60073a0:1: Error' \\~n"
"'AREA:requests#7648eca0: req/s\\l' \\~n"
"'LINE1:ln1#4d18e4' \\~n"
% "'CDEF:requests10s=requests,10,TRENDNAN' \\~n"
% "'LINE1:requests10s#000000' \\~n"
"'VDEF:requestsmax=requests,MAXIMUM' \\~n"
"'VDEF:requestsmin=requests,MINIMUM' \\~n"
"'VDEF:requestsavg=requests,AVERAGE' \\~n"
"'COMMENT:\\u' \\~n"
"'GPRINT:requestsavg:AVG %6.0lf' \\~n"
"'GPRINT:requestsmin:MIN %6.0lf' \\~n"
"'GPRINT:requestsmax:MAX %6.0lf\\r'~n"
, [
Filename,
Seconds,
Filename,
rrdtool_graph1_def(Stats, Filename, Start, End),
rrdtool_graph1_shift(Stats, Shift),
rrdtool_graph1_tick(Stats)
]
),
file:write_file(Filename ++ ".req.sh", "#!/usr/bin/env bash\n\n" ++ Command),
_ = os:cmd("chmod +x " ++ Filename ++ ".req.sh"),
_Result = os:cmd(Command),
% io:format("~s~n~n~s~n", [Command, Result]),
ok.
rrdtool_graph1_def(Stats, Filename, Start, End) ->
Keys = rrdtool_graph1_keys(Stats, #{}),
rrdtool_graph1_def(Keys, Filename, Start, End, []).
rrdtool_graph1_def([], _, _, _, []) ->
<<>>;
rrdtool_graph1_def([], _, _, _, [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_graph1_def([Key | Keys], Filename, Start, End, Acc0) ->
Source =
case Key of
_ when is_atom(Key) ->
erlang:atom_to_binary(Key);
_ when is_binary(Key) ->
Key
end,
Label = Source,
Value = io_lib:format("'DEF:~s=~s.rrd:~s:MAX:start=~w:end=~w:step=1'", [
Label,
Filename,
Source,
Start,
End
]),
Acc1 = [<<" \\\n">>, Value | Acc0],
rrdtool_graph1_def(Keys, Filename, Start, End, Acc1).
rrdtool_graph1_keys([], Acc) ->
lists:usort([<<"requests">>, <<"error">> | maps:keys(Acc)]);
rrdtool_graph1_keys([{_, Event} | Stats], Acc0) ->
Acc1 = lists:foldl(fun
(K, A) when K == requests orelse K == error -> maps:put(erlang:atom_to_binary(K, unicode), [], A);
(K, A) when is_binary(K) -> maps:put(K, [], A);
(_, A) -> A
end, Acc0, lists:sort(maps:keys(Event))),
rrdtool_graph1_keys(Stats, Acc1).
rrdtool_graph1_shift(Stats, Shift) ->
Keys = rrdtool_graph1_keys(Stats, #{}),
rrdtool_graph1_shift(Keys, Shift, []).
rrdtool_graph1_shift([], _, []) ->
<<>>;
rrdtool_graph1_shift([], _, [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_graph1_shift([Key | Keys], Shift, Acc0) ->
Label = Key,
Value = io_lib:format("'SHIFT:~s:~w'", [
Label,
Shift
]),
Acc1 = [<<" \\\n">>, Value | Acc0],
rrdtool_graph1_shift(Keys, Shift, Acc1).
rrdtool_graph1_tick(Stats) ->
Keys0 = rrdtool_graph1_keys(Stats, #{}) -- [<<"requests">>, <<"error">>],
Keys = lists:sort(fun (A, B) ->
[A0 | _] = binary:split(A, <<"x">>),
[B0 | _] = binary:split(B, <<"x">>),
Ai = erlang:binary_to_integer(A0),
Bi = erlang:binary_to_integer(B0),
Ai =< Bi
end, Keys0),
rrdtool_graph1_tick(Keys, []).
rrdtool_graph1_tick([], []) ->
<<>>;
rrdtool_graph1_tick([], [_ | Acc]) ->
erlang:iolist_to_binary(lists:reverse(Acc));
rrdtool_graph1_tick([Key | Keys], Acc0) ->
Tick = io_lib:format("'TICK:~s#00000020:1: ~s'", [
Key,
Key
]),
Acc1 = [<<" \\\n">>, Tick | Acc0],
rrdtool_graph1_tick(Keys, Acc1).
#!/usr/bin/env bash
node="h2load${RANDOM}@127.0.0.1"
cookie="mycookie"
if [ $# -lt 4 ]; then
echo 1>&2 "$0: requires an EXECUTABLE, FILENAME, TYPE=(h1|h2), and PORT argument"
exit 2
fi
function notify_erl {
echo "exiting h2load"
erl -name "notify${RANDOM}@127.0.0.1" -setcookie "${cookie}" -noshell -eval "{worker, '${node}'} ! stop, erlang:halt(0)."
exit 1
}
trap notify_erl SIGHUP SIGINT SIGTERM
./h2load.escript "${node}" "${cookie}" "$1" "$2" "$3" "$4" &
while true; do sleep 1; done
package main
import (
"fmt"
"log"
"net/http"
// "time"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
// func spinsleep(n int) int {
// // defer timeTrack(time.Now(), "spinsleep")
// j := 0
// for i := 0; i <= n; i++ {
// j = i
// }
// return j
// }
// func timeTrack(start time.Time, name string) {
// elapsed := time.Since(start)
// log.Printf("%s took %s", name, elapsed)
// }
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// go spinsleep(100000000)
fmt.Fprint(w, "Hello world")
})
h2s := &http2.Server{
}
h1s := &http.Server{
Addr: ":8080",
Handler: h2c.NewHandler(handler, h2s),
}
log.Fatal(h1s.ListenAndServe())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment